@leanmcp/ui 0.1.0 → 0.2.1

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/index.mjs CHANGED
@@ -1,53 +1,41 @@
1
- import 'reflect-metadata';
2
- import React7, { forwardRef, useState, useEffect, useCallback, createContext, useContext, useMemo, useRef } from 'react';
3
- import { PostMessageTransport, App } from '@modelcontextprotocol/ext-apps';
1
+ import { __name } from './chunk-WORZ46KI.mjs';
2
+ export { UIApp, getUIAppMetadata, getUIAppUri } from './chunk-WORZ46KI.mjs';
3
+ import * as React25 from 'react';
4
+ import React25__default, { forwardRef, Component, useState, useRef, useCallback, useEffect, createContext, useContext, useMemo } from 'react';
5
+ import { applyDocumentTheme, applyHostStyleVariables, PostMessageTransport, App } from '@modelcontextprotocol/ext-apps';
6
+ export { App, PostMessageTransport } from '@modelcontextprotocol/ext-apps';
7
+ import { XIcon, ChevronDownIcon, CheckIcon, ChevronUpIcon, Loader2, SearchIcon, Search, X, AlertCircle, RefreshCw, ChevronLeft, ChevronRight, WifiOff, CircleIcon, ChevronRightIcon, Check, ArrowUpDown, ArrowUp, ArrowDown, Loader2Icon, OctagonXIcon, TriangleAlertIcon, InfoIcon, CircleCheckIcon } from 'lucide-react';
8
+ import { useTheme } from 'next-themes';
9
+ import { toast, Toaster as Toaster$1 } from 'sonner';
4
10
  import { Slot } from '@radix-ui/react-slot';
11
+ import { cva } from 'class-variance-authority';
5
12
  import { clsx } from 'clsx';
13
+ import { twMerge } from 'tailwind-merge';
14
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
15
+ import * as SelectPrimitive from '@radix-ui/react-select';
16
+ import { Command as Command$1 } from 'cmdk';
17
+ import * as PopoverPrimitive from '@radix-ui/react-popover';
18
+ import * as LabelPrimitive from '@radix-ui/react-label';
19
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
20
+ import * as SliderPrimitive from '@radix-ui/react-slider';
21
+ import * as SwitchPrimitive from '@radix-ui/react-switch';
22
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
23
+ import { useFormContext, useFormState, FormProvider, Controller } from 'react-hook-form';
24
+ import * as TabsPrimitive2 from '@radix-ui/react-tabs';
25
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
26
+ import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
27
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
28
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
6
29
  import { useReactTable, getFilteredRowModel, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
7
- import { Chart as Chart$1, CategoryScale, LinearScale, PointElement, LineElement, BarElement, ArcElement, Title, Tooltip, Legend } from 'chart.js';
30
+ import { Chart as Chart$1, CategoryScale, LinearScale, PointElement, LineElement, BarElement, ArcElement, Title, Tooltip as Tooltip$1, Legend } from 'chart.js';
8
31
  import { Chart as Chart$2 } from 'react-chartjs-2';
9
32
  import { Highlight, themes } from 'prism-react-renderer';
33
+ export { AppBridge } from '@modelcontextprotocol/ext-apps/app-bridge';
10
34
 
11
- var __defProp = Object.defineProperty;
12
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
13
- var UI_APP_COMPONENT_KEY = "ui:app:component";
14
- var UI_APP_URI_KEY = "ui:app:uri";
15
- var UI_APP_OPTIONS_KEY = "ui:app:options";
16
- function UIApp(options) {
17
- return (target, propertyKey, descriptor) => {
18
- const methodName = String(propertyKey);
19
- const className = target.constructor.name.toLowerCase().replace("service", "");
20
- const uri = options.uri ?? `ui://${className}/${methodName}`;
21
- Reflect.defineMetadata(UI_APP_COMPONENT_KEY, options.component, descriptor.value);
22
- Reflect.defineMetadata(UI_APP_URI_KEY, uri, descriptor.value);
23
- Reflect.defineMetadata(UI_APP_OPTIONS_KEY, options, descriptor.value);
24
- const existingMeta = Reflect.getMetadata("tool:meta", descriptor.value) || {};
25
- Reflect.defineMetadata("tool:meta", {
26
- ...existingMeta,
27
- "ui/resourceUri": uri
28
- }, descriptor.value);
29
- return descriptor;
30
- };
31
- }
32
- __name(UIApp, "UIApp");
33
- function getUIAppMetadata(target) {
34
- const component = Reflect.getMetadata(UI_APP_COMPONENT_KEY, target);
35
- if (!component) return void 0;
36
- return {
37
- component,
38
- uri: Reflect.getMetadata(UI_APP_URI_KEY, target),
39
- ...Reflect.getMetadata(UI_APP_OPTIONS_KEY, target)
40
- };
41
- }
42
- __name(getUIAppMetadata, "getUIAppMetadata");
43
- function getUIAppUri(target) {
44
- return Reflect.getMetadata(UI_APP_URI_KEY, target);
45
- }
46
- __name(getUIAppUri, "getUIAppUri");
47
35
  var McpAppContext = /* @__PURE__ */ createContext(null);
48
36
  function AppProvider({ appInfo, capabilities = {}, options = {
49
37
  autoResize: true
50
- }, children }) {
38
+ }, onTeardown, children }) {
51
39
  const [app, setApp] = useState(null);
52
40
  const [isConnected, setIsConnected] = useState(false);
53
41
  const [error, setError] = useState(null);
@@ -55,6 +43,18 @@ function AppProvider({ appInfo, capabilities = {}, options = {
55
43
  const [toolInput, setToolInput] = useState(null);
56
44
  const [toolInputPartial, setToolInputPartial] = useState(null);
57
45
  const [toolResult, setToolResult] = useState(null);
46
+ const [toolCancelled, setToolCancelled] = useState({
47
+ cancelled: false
48
+ });
49
+ const stylesApplied = useRef(false);
50
+ const applyHostStyles = useCallback((context) => {
51
+ if (context.theme) {
52
+ applyDocumentTheme(context.theme);
53
+ }
54
+ if (context.styles?.variables) {
55
+ applyHostStyleVariables(context.styles.variables);
56
+ }
57
+ }, []);
58
58
  useEffect(() => {
59
59
  let mounted = true;
60
60
  let appInstance = null;
@@ -65,6 +65,9 @@ function AppProvider({ appInfo, capabilities = {}, options = {
65
65
  appInstance.ontoolinput = (params) => {
66
66
  if (mounted) {
67
67
  setToolInput(params.arguments);
68
+ setToolCancelled({
69
+ cancelled: false
70
+ });
68
71
  }
69
72
  };
70
73
  appInstance.ontoolinputpartial = (params) => {
@@ -77,19 +80,42 @@ function AppProvider({ appInfo, capabilities = {}, options = {
77
80
  setToolResult(params);
78
81
  }
79
82
  };
83
+ appInstance.ontoolcancelled = (params) => {
84
+ if (mounted) {
85
+ setToolCancelled({
86
+ cancelled: true,
87
+ reason: params.reason
88
+ });
89
+ }
90
+ };
80
91
  appInstance.onhostcontextchanged = (params) => {
81
92
  if (mounted) {
82
93
  setHostContext((prev) => ({
83
94
  ...prev,
84
95
  ...params
85
96
  }));
97
+ applyHostStyles(params);
86
98
  }
87
99
  };
100
+ if (onTeardown) {
101
+ appInstance.onteardown = async () => {
102
+ await onTeardown();
103
+ return {};
104
+ };
105
+ }
88
106
  await appInstance.connect(transport);
89
107
  if (mounted) {
90
108
  setApp(appInstance);
91
109
  setIsConnected(true);
92
110
  setError(null);
111
+ const initialContext = appInstance.getHostContext();
112
+ if (initialContext) {
113
+ setHostContext(initialContext);
114
+ if (!stylesApplied.current) {
115
+ applyHostStyles(initialContext);
116
+ stylesApplied.current = true;
117
+ }
118
+ }
93
119
  }
94
120
  } catch (err) {
95
121
  if (mounted) {
@@ -108,12 +134,17 @@ function AppProvider({ appInfo, capabilities = {}, options = {
108
134
  };
109
135
  }, [
110
136
  appInfo.name,
111
- appInfo.version
137
+ appInfo.version,
138
+ applyHostStyles,
139
+ onTeardown
112
140
  ]);
113
141
  const callTool = useCallback(async (name, args = {}) => {
114
142
  if (!app) {
115
143
  throw new Error("Not connected to host");
116
144
  }
145
+ setToolCancelled({
146
+ cancelled: false
147
+ });
117
148
  const result = await app.callServerTool({
118
149
  name,
119
150
  arguments: args
@@ -157,12 +188,24 @@ function AppProvider({ appInfo, capabilities = {}, options = {
157
188
  window.open(url, "_blank", "noopener,noreferrer");
158
189
  return;
159
190
  }
160
- await app.sendOpenLink({
191
+ await app.openLink({
161
192
  url
162
193
  });
163
194
  }, [
164
195
  app
165
196
  ]);
197
+ const requestDisplayMode = useCallback(async (mode) => {
198
+ if (!app) {
199
+ console.warn("[AppProvider] Not connected - cannot request display mode");
200
+ return "inline";
201
+ }
202
+ const result = await app.requestDisplayMode({
203
+ mode
204
+ });
205
+ return result.mode;
206
+ }, [
207
+ app
208
+ ]);
166
209
  const value = {
167
210
  app,
168
211
  isConnected,
@@ -171,15 +214,17 @@ function AppProvider({ appInfo, capabilities = {}, options = {
171
214
  toolInput,
172
215
  toolInputPartial,
173
216
  toolResult,
217
+ toolCancelled,
174
218
  callTool,
175
219
  sendMessage,
176
220
  sendLog,
177
- openLink
221
+ openLink,
222
+ requestDisplayMode
178
223
  };
179
224
  const theme = hostContext.theme ?? "light";
180
- return /* @__PURE__ */ React7.createElement(McpAppContext.Provider, {
225
+ return /* @__PURE__ */ React25__default.createElement(McpAppContext.Provider, {
181
226
  value
182
- }, /* @__PURE__ */ React7.createElement("div", {
227
+ }, /* @__PURE__ */ React25__default.createElement("div", {
183
228
  className: "lui-root",
184
229
  "data-theme": theme
185
230
  }, children));
@@ -193,6 +238,9 @@ var ssrDefaultContext = {
193
238
  toolInput: null,
194
239
  toolInputPartial: null,
195
240
  toolResult: null,
241
+ toolCancelled: {
242
+ cancelled: false
243
+ },
196
244
  callTool: /* @__PURE__ */ __name(async () => {
197
245
  throw new Error("callTool not available during SSR");
198
246
  }, "callTool"),
@@ -204,7 +252,11 @@ var ssrDefaultContext = {
204
252
  }, "sendLog"),
205
253
  openLink: /* @__PURE__ */ __name(async () => {
206
254
  console.warn("openLink not available during SSR");
207
- }, "openLink")
255
+ }, "openLink"),
256
+ requestDisplayMode: /* @__PURE__ */ __name(async () => {
257
+ console.warn("requestDisplayMode not available during SSR");
258
+ return "inline";
259
+ }, "requestDisplayMode")
208
260
  };
209
261
  function useMcpApp() {
210
262
  const context = useContext(McpAppContext);
@@ -214,311 +266,2611 @@ function useMcpApp() {
214
266
  return context;
215
267
  }
216
268
  __name(useMcpApp, "useMcpApp");
217
- function useTool(toolName) {
269
+ var DEFAULT_CONTEXT = {
270
+ resultDisplay: {
271
+ display: "none"
272
+ },
273
+ showLoading: true
274
+ };
275
+ var ToolContext = /* @__PURE__ */ createContext(DEFAULT_CONTEXT);
276
+ function ToolProvider({ defaults = {}, children }) {
277
+ const parentContext = useContext(ToolContext);
278
+ const value = useMemo(() => ({
279
+ resultDisplay: defaults.resultDisplay ?? parentContext.resultDisplay,
280
+ onError: defaults.onError ?? parentContext.onError,
281
+ showLoading: defaults.showLoading ?? parentContext.showLoading
282
+ }), [
283
+ defaults,
284
+ parentContext
285
+ ]);
286
+ return /* @__PURE__ */ React25.createElement(ToolContext.Provider, {
287
+ value
288
+ }, children);
289
+ }
290
+ __name(ToolProvider, "ToolProvider");
291
+ function useToolContext() {
292
+ return useContext(ToolContext);
293
+ }
294
+ __name(useToolContext, "useToolContext");
295
+ var Toaster = /* @__PURE__ */ __name(({ ...props }) => {
296
+ const { theme = "system" } = useTheme();
297
+ return /* @__PURE__ */ React25__default.createElement(Toaster$1, {
298
+ theme,
299
+ className: "toaster group",
300
+ icons: {
301
+ success: /* @__PURE__ */ React25__default.createElement(CircleCheckIcon, {
302
+ className: "size-4"
303
+ }),
304
+ info: /* @__PURE__ */ React25__default.createElement(InfoIcon, {
305
+ className: "size-4"
306
+ }),
307
+ warning: /* @__PURE__ */ React25__default.createElement(TriangleAlertIcon, {
308
+ className: "size-4"
309
+ }),
310
+ error: /* @__PURE__ */ React25__default.createElement(OctagonXIcon, {
311
+ className: "size-4"
312
+ }),
313
+ loading: /* @__PURE__ */ React25__default.createElement(Loader2Icon, {
314
+ className: "size-4 animate-spin"
315
+ })
316
+ },
317
+ style: {
318
+ "--normal-bg": "var(--popover)",
319
+ "--normal-text": "var(--popover-foreground)",
320
+ "--normal-border": "var(--border)",
321
+ "--border-radius": "var(--radius)"
322
+ },
323
+ ...props
324
+ });
325
+ }, "Toaster");
326
+ function cn(...inputs) {
327
+ return twMerge(clsx(inputs));
328
+ }
329
+ __name(cn, "cn");
330
+
331
+ // src/components/ui/button.tsx
332
+ var buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
333
+ variants: {
334
+ variant: {
335
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
336
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
337
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
338
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
339
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
340
+ link: "text-primary underline-offset-4 hover:underline"
341
+ },
342
+ size: {
343
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
344
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
345
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
346
+ icon: "size-9",
347
+ "icon-sm": "size-8",
348
+ "icon-lg": "size-10"
349
+ }
350
+ },
351
+ defaultVariants: {
352
+ variant: "default",
353
+ size: "default"
354
+ }
355
+ });
356
+ function Button({ className, variant = "default", size = "default", asChild = false, ...props }) {
357
+ const Comp = asChild ? Slot : "button";
358
+ return /* @__PURE__ */ React25.createElement(Comp, {
359
+ "data-slot": "button",
360
+ "data-variant": variant,
361
+ "data-size": size,
362
+ className: cn(buttonVariants({
363
+ variant,
364
+ size,
365
+ className
366
+ })),
367
+ ...props
368
+ });
369
+ }
370
+ __name(Button, "Button");
371
+ function Dialog({ ...props }) {
372
+ return /* @__PURE__ */ React25.createElement(DialogPrimitive.Root, {
373
+ "data-slot": "dialog",
374
+ ...props
375
+ });
376
+ }
377
+ __name(Dialog, "Dialog");
378
+ function DialogTrigger({ ...props }) {
379
+ return /* @__PURE__ */ React25.createElement(DialogPrimitive.Trigger, {
380
+ "data-slot": "dialog-trigger",
381
+ ...props
382
+ });
383
+ }
384
+ __name(DialogTrigger, "DialogTrigger");
385
+ function DialogPortal({ ...props }) {
386
+ return /* @__PURE__ */ React25.createElement(DialogPrimitive.Portal, {
387
+ "data-slot": "dialog-portal",
388
+ ...props
389
+ });
390
+ }
391
+ __name(DialogPortal, "DialogPortal");
392
+ function DialogClose({ ...props }) {
393
+ return /* @__PURE__ */ React25.createElement(DialogPrimitive.Close, {
394
+ "data-slot": "dialog-close",
395
+ ...props
396
+ });
397
+ }
398
+ __name(DialogClose, "DialogClose");
399
+ function DialogOverlay({ className, ...props }) {
400
+ return /* @__PURE__ */ React25.createElement(DialogPrimitive.Overlay, {
401
+ "data-slot": "dialog-overlay",
402
+ className: cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", className),
403
+ ...props
404
+ });
405
+ }
406
+ __name(DialogOverlay, "DialogOverlay");
407
+ function DialogContent({ className, children, showCloseButton = true, ...props }) {
408
+ return /* @__PURE__ */ React25.createElement(DialogPortal, {
409
+ "data-slot": "dialog-portal"
410
+ }, /* @__PURE__ */ React25.createElement(DialogOverlay, null), /* @__PURE__ */ React25.createElement(DialogPrimitive.Content, {
411
+ "data-slot": "dialog-content",
412
+ className: cn("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg", className),
413
+ ...props
414
+ }, children, showCloseButton && /* @__PURE__ */ React25.createElement(DialogPrimitive.Close, {
415
+ "data-slot": "dialog-close",
416
+ className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
417
+ }, /* @__PURE__ */ React25.createElement(XIcon, null), /* @__PURE__ */ React25.createElement("span", {
418
+ className: "sr-only"
419
+ }, "Close"))));
420
+ }
421
+ __name(DialogContent, "DialogContent");
422
+ function DialogHeader({ className, ...props }) {
423
+ return /* @__PURE__ */ React25.createElement("div", {
424
+ "data-slot": "dialog-header",
425
+ className: cn("flex flex-col gap-2 text-center sm:text-left", className),
426
+ ...props
427
+ });
428
+ }
429
+ __name(DialogHeader, "DialogHeader");
430
+ function DialogFooter({ className, ...props }) {
431
+ return /* @__PURE__ */ React25.createElement("div", {
432
+ "data-slot": "dialog-footer",
433
+ className: cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className),
434
+ ...props
435
+ });
436
+ }
437
+ __name(DialogFooter, "DialogFooter");
438
+ function DialogTitle({ className, ...props }) {
439
+ return /* @__PURE__ */ React25.createElement(DialogPrimitive.Title, {
440
+ "data-slot": "dialog-title",
441
+ className: cn("text-lg leading-none font-semibold", className),
442
+ ...props
443
+ });
444
+ }
445
+ __name(DialogTitle, "DialogTitle");
446
+ function DialogDescription({ className, ...props }) {
447
+ return /* @__PURE__ */ React25.createElement(DialogPrimitive.Description, {
448
+ "data-slot": "dialog-description",
449
+ className: cn("text-muted-foreground text-sm", className),
450
+ ...props
451
+ });
452
+ }
453
+ __name(DialogDescription, "DialogDescription");
454
+ function extractResultData(result) {
455
+ if ("structuredContent" in result && result.structuredContent) {
456
+ return result.structuredContent;
457
+ }
458
+ if (result.content && result.content.length > 0) {
459
+ const textContent = result.content.filter((c) => c.type === "text").map((c) => c.text).join("");
460
+ if (textContent) {
461
+ try {
462
+ const parsed = JSON.parse(textContent);
463
+ if (parsed && typeof parsed === "object" && "content" in parsed && Array.isArray(parsed.content)) {
464
+ const nested = extractResultData(parsed);
465
+ if (nested !== null) {
466
+ return nested;
467
+ }
468
+ }
469
+ return parsed;
470
+ } catch {
471
+ return textContent;
472
+ }
473
+ }
474
+ }
475
+ return result;
476
+ }
477
+ __name(extractResultData, "extractResultData");
478
+ function useTool(toolName, options = {}) {
218
479
  const { callTool } = useMcpApp();
219
- const [loading, setLoading] = useState(false);
480
+ const [state, setState] = useState("idle");
220
481
  const [result, setResult] = useState(null);
221
482
  const [error, setError] = useState(null);
222
- const call = useCallback(async (args = {}) => {
223
- setLoading(true);
483
+ const abortControllerRef = useRef(null);
484
+ const lastArgsRef = useRef(void 0);
485
+ const retryCountRef = useRef(0);
486
+ const { defaultArgs, transform, retry, onStart, onSuccess, onError, onComplete } = options;
487
+ const retryConfig = typeof retry === "number" ? {
488
+ count: retry,
489
+ delay: 1e3
490
+ } : retry ?? {
491
+ count: 0,
492
+ delay: 1e3
493
+ };
494
+ const executeCall = useCallback(async (args) => {
495
+ const mergedArgs = {
496
+ ...defaultArgs,
497
+ ...args
498
+ };
499
+ lastArgsRef.current = mergedArgs;
500
+ abortControllerRef.current = new AbortController();
501
+ setState("loading");
224
502
  setError(null);
503
+ onStart?.();
225
504
  try {
226
- const response = await callTool(toolName, args);
227
- const data = response?.structuredContent ?? response;
505
+ const response = await callTool(toolName, mergedArgs);
506
+ if (abortControllerRef.current?.signal.aborted) {
507
+ throw new Error("Tool call aborted");
508
+ }
509
+ let data;
510
+ if (transform) {
511
+ data = transform(response);
512
+ } else {
513
+ data = extractResultData(response);
514
+ }
515
+ setState("success");
228
516
  setResult(data);
517
+ retryCountRef.current = 0;
518
+ onSuccess?.(data);
519
+ onComplete?.();
229
520
  return data;
230
521
  } catch (err) {
231
522
  const error2 = err instanceof Error ? err : new Error(String(err));
523
+ if (retryCountRef.current < retryConfig.count) {
524
+ retryCountRef.current++;
525
+ await new Promise((resolve) => setTimeout(resolve, retryConfig.delay));
526
+ return executeCall(args);
527
+ }
528
+ setState("error");
232
529
  setError(error2);
530
+ retryCountRef.current = 0;
531
+ onError?.(error2);
532
+ onComplete?.();
233
533
  throw error2;
234
- } finally {
235
- setLoading(false);
236
534
  }
237
535
  }, [
238
536
  callTool,
239
- toolName
537
+ toolName,
538
+ defaultArgs,
539
+ transform,
540
+ retryConfig,
541
+ onStart,
542
+ onSuccess,
543
+ onError,
544
+ onComplete
545
+ ]);
546
+ const call = useCallback(async (args) => {
547
+ retryCountRef.current = 0;
548
+ return executeCall(args);
549
+ }, [
550
+ executeCall
551
+ ]);
552
+ const mutate = useCallback(async (args) => {
553
+ return call(args);
554
+ }, [
555
+ call
240
556
  ]);
241
557
  const reset = useCallback(() => {
558
+ setState("idle");
242
559
  setResult(null);
243
560
  setError(null);
561
+ retryCountRef.current = 0;
562
+ abortControllerRef.current?.abort();
563
+ }, []);
564
+ const retryCall = useCallback(async () => {
565
+ if (lastArgsRef.current === void 0 && !defaultArgs) {
566
+ return null;
567
+ }
568
+ retryCountRef.current = 0;
569
+ return executeCall(lastArgsRef.current);
570
+ }, [
571
+ executeCall,
572
+ defaultArgs
573
+ ]);
574
+ const abort = useCallback(() => {
575
+ abortControllerRef.current?.abort();
576
+ setState("idle");
244
577
  }, []);
245
578
  return {
246
579
  call,
580
+ mutate,
581
+ state,
582
+ loading: state === "loading",
583
+ result,
584
+ error,
585
+ reset,
586
+ retry: retryCall,
587
+ abort
588
+ };
589
+ }
590
+ __name(useTool, "useTool");
591
+ function ToolButton({ tool, args = {}, resultDisplay = "none", renderResult, resultDuration = 3e3, successMessage, errorMessage, onToolStart, onToolSuccess, onToolError, onToolComplete, loadingText, loadingIcon, disableWhileLoading = true, confirm, children, className, variant = "default", size = "default", disabled, asChild = false, ...props }) {
592
+ const toolConfig = typeof tool === "string" ? {
593
+ name: tool
594
+ } : tool;
595
+ const mergedArgs = {
596
+ ...toolConfig.args,
597
+ ...args
598
+ };
599
+ const { call, state, loading, result, error, reset } = useTool(toolConfig.name, {
600
+ defaultArgs: mergedArgs,
601
+ transform: toolConfig.transform,
602
+ onStart: onToolStart,
603
+ onSuccess: onToolSuccess,
604
+ onError: onToolError,
605
+ onComplete: onToolComplete
606
+ });
607
+ const [showConfirm, setShowConfirm] = useState(false);
608
+ const [showResult, setShowResult] = useState(false);
609
+ const buttonState = {
247
610
  loading,
611
+ state,
248
612
  result,
249
613
  error,
250
- reset
614
+ hasResult: result !== null || error !== null
615
+ };
616
+ const executeCall = useCallback(async () => {
617
+ try {
618
+ const res = await call();
619
+ if (resultDisplay === "toast") {
620
+ const message = typeof successMessage === "function" ? successMessage(res) : successMessage ?? "Success";
621
+ toast.success(message);
622
+ } else if (resultDisplay === "inline") {
623
+ setShowResult(true);
624
+ setTimeout(() => setShowResult(false), resultDuration);
625
+ }
626
+ } catch (err) {
627
+ if (resultDisplay === "toast") {
628
+ const message = typeof errorMessage === "function" ? errorMessage(err instanceof Error ? err : new Error(String(err))) : errorMessage ?? (err instanceof Error ? err.message : "An error occurred");
629
+ toast.error(message);
630
+ } else if (resultDisplay === "inline") {
631
+ setShowResult(true);
632
+ setTimeout(() => setShowResult(false), resultDuration);
633
+ }
634
+ }
635
+ }, [
636
+ call,
637
+ resultDisplay,
638
+ successMessage,
639
+ errorMessage,
640
+ resultDuration
641
+ ]);
642
+ const handleClick = useCallback(() => {
643
+ if (confirm) {
644
+ setShowConfirm(true);
645
+ } else {
646
+ executeCall();
647
+ }
648
+ }, [
649
+ confirm,
650
+ executeCall
651
+ ]);
652
+ const handleConfirm = useCallback(() => {
653
+ setShowConfirm(false);
654
+ executeCall();
655
+ }, [
656
+ executeCall
657
+ ]);
658
+ const confirmConfig = typeof confirm === "object" ? confirm : {
659
+ title: "Confirm Action",
660
+ description: "Are you sure you want to proceed?",
661
+ confirmText: "Confirm",
662
+ cancelText: "Cancel"
251
663
  };
664
+ const renderChildren = /* @__PURE__ */ __name(() => {
665
+ if (typeof children === "function") {
666
+ return children(buttonState);
667
+ }
668
+ if (loading) {
669
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, loadingIcon ?? /* @__PURE__ */ React25.createElement(Loader2, {
670
+ className: "animate-spin"
671
+ }), loadingText && /* @__PURE__ */ React25.createElement("span", null, loadingText), !loadingText && children);
672
+ }
673
+ if (showResult && resultDisplay === "inline") {
674
+ if (error) {
675
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(X, {
676
+ className: "text-destructive"
677
+ }), /* @__PURE__ */ React25.createElement("span", null, error.message));
678
+ }
679
+ if (renderResult) {
680
+ return renderResult(result);
681
+ }
682
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Check, {
683
+ className: "text-success"
684
+ }), /* @__PURE__ */ React25.createElement("span", null, "Done"));
685
+ }
686
+ return children;
687
+ }, "renderChildren");
688
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Button, {
689
+ type: "button",
690
+ variant,
691
+ size,
692
+ className: cn(className),
693
+ disabled: disabled || disableWhileLoading && loading,
694
+ onClick: handleClick,
695
+ asChild,
696
+ ...props
697
+ }, renderChildren()), confirm && /* @__PURE__ */ React25.createElement(Dialog, {
698
+ open: showConfirm,
699
+ onOpenChange: setShowConfirm
700
+ }, /* @__PURE__ */ React25.createElement(DialogContent, null, /* @__PURE__ */ React25.createElement(DialogHeader, null, /* @__PURE__ */ React25.createElement(DialogTitle, null, confirmConfig.title), confirmConfig.description && /* @__PURE__ */ React25.createElement(DialogDescription, null, confirmConfig.description)), /* @__PURE__ */ React25.createElement(DialogFooter, null, /* @__PURE__ */ React25.createElement(Button, {
701
+ variant: "outline",
702
+ onClick: /* @__PURE__ */ __name(() => setShowConfirm(false), "onClick")
703
+ }, confirmConfig.cancelText ?? "Cancel"), /* @__PURE__ */ React25.createElement(Button, {
704
+ variant: confirmConfig.confirmVariant ?? (variant === "destructive" ? "destructive" : "default"),
705
+ onClick: handleConfirm
706
+ }, confirmConfig.confirmText ?? "Confirm")))));
707
+ }
708
+ __name(ToolButton, "ToolButton");
709
+ function Select({ ...props }) {
710
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Root, {
711
+ "data-slot": "select",
712
+ ...props
713
+ });
714
+ }
715
+ __name(Select, "Select");
716
+ function SelectGroup({ ...props }) {
717
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Group, {
718
+ "data-slot": "select-group",
719
+ ...props
720
+ });
721
+ }
722
+ __name(SelectGroup, "SelectGroup");
723
+ function SelectValue({ ...props }) {
724
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Value, {
725
+ "data-slot": "select-value",
726
+ ...props
727
+ });
728
+ }
729
+ __name(SelectValue, "SelectValue");
730
+ function SelectTrigger({ className, size = "default", children, ...props }) {
731
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Trigger, {
732
+ "data-slot": "select-trigger",
733
+ "data-size": size,
734
+ className: cn("border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
735
+ ...props
736
+ }, children, /* @__PURE__ */ React25.createElement(SelectPrimitive.Icon, {
737
+ asChild: true
738
+ }, /* @__PURE__ */ React25.createElement(ChevronDownIcon, {
739
+ className: "size-4 opacity-50"
740
+ })));
741
+ }
742
+ __name(SelectTrigger, "SelectTrigger");
743
+ function SelectContent({ className, children, position = "item-aligned", align = "center", ...props }) {
744
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Portal, null, /* @__PURE__ */ React25.createElement(SelectPrimitive.Content, {
745
+ "data-slot": "select-content",
746
+ className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md", position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className),
747
+ position,
748
+ align,
749
+ ...props
750
+ }, /* @__PURE__ */ React25.createElement(SelectScrollUpButton, null), /* @__PURE__ */ React25.createElement(SelectPrimitive.Viewport, {
751
+ className: cn("p-1", position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1")
752
+ }, children), /* @__PURE__ */ React25.createElement(SelectScrollDownButton, null)));
753
+ }
754
+ __name(SelectContent, "SelectContent");
755
+ function SelectLabel({ className, ...props }) {
756
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Label, {
757
+ "data-slot": "select-label",
758
+ className: cn("text-muted-foreground px-2 py-1.5 text-xs", className),
759
+ ...props
760
+ });
761
+ }
762
+ __name(SelectLabel, "SelectLabel");
763
+ function SelectItem({ className, children, ...props }) {
764
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Item, {
765
+ "data-slot": "select-item",
766
+ className: cn("focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className),
767
+ ...props
768
+ }, /* @__PURE__ */ React25.createElement("span", {
769
+ "data-slot": "select-item-indicator",
770
+ className: "absolute right-2 flex size-3.5 items-center justify-center"
771
+ }, /* @__PURE__ */ React25.createElement(SelectPrimitive.ItemIndicator, null, /* @__PURE__ */ React25.createElement(CheckIcon, {
772
+ className: "size-4"
773
+ }))), /* @__PURE__ */ React25.createElement(SelectPrimitive.ItemText, null, children));
774
+ }
775
+ __name(SelectItem, "SelectItem");
776
+ function SelectSeparator({ className, ...props }) {
777
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.Separator, {
778
+ "data-slot": "select-separator",
779
+ className: cn("bg-border pointer-events-none -mx-1 my-1 h-px", className),
780
+ ...props
781
+ });
782
+ }
783
+ __name(SelectSeparator, "SelectSeparator");
784
+ function SelectScrollUpButton({ className, ...props }) {
785
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.ScrollUpButton, {
786
+ "data-slot": "select-scroll-up-button",
787
+ className: cn("flex cursor-default items-center justify-center py-1", className),
788
+ ...props
789
+ }, /* @__PURE__ */ React25.createElement(ChevronUpIcon, {
790
+ className: "size-4"
791
+ }));
792
+ }
793
+ __name(SelectScrollUpButton, "SelectScrollUpButton");
794
+ function SelectScrollDownButton({ className, ...props }) {
795
+ return /* @__PURE__ */ React25.createElement(SelectPrimitive.ScrollDownButton, {
796
+ "data-slot": "select-scroll-down-button",
797
+ className: cn("flex cursor-default items-center justify-center py-1", className),
798
+ ...props
799
+ }, /* @__PURE__ */ React25.createElement(ChevronDownIcon, {
800
+ className: "size-4"
801
+ }));
802
+ }
803
+ __name(SelectScrollDownButton, "SelectScrollDownButton");
804
+ function ToolSelect({ onSelectTool, argName = "value", additionalArgs = {}, optionsTool, optionsArgs = {}, transformOptions, options: staticOptions = [], placeholder = "Select an option", loadingPlaceholder = "Loading...", emptyMessage = "No options available", value: controlledValue, defaultValue, onValueChange, onOptionsLoaded, onSelectionSuccess, onSelectionError, showSuccessToast = false, successMessage, className, disabled = false }) {
805
+ const [fetchedOptions, setFetchedOptions] = useState([]);
806
+ const [internalValue, setInternalValue] = useState(defaultValue ?? "");
807
+ const optionsToolConfig = optionsTool ? typeof optionsTool === "string" ? {
808
+ name: optionsTool
809
+ } : optionsTool : null;
810
+ const selectToolConfig = onSelectTool ? typeof onSelectTool === "string" ? {
811
+ name: onSelectTool
812
+ } : onSelectTool : null;
813
+ const optionsHook = useTool(optionsToolConfig?.name ?? "", {
814
+ defaultArgs: {
815
+ ...optionsToolConfig?.args,
816
+ ...optionsArgs
817
+ }
818
+ });
819
+ const selectHook = useTool(selectToolConfig?.name ?? "", {
820
+ onSuccess: /* @__PURE__ */ __name((result) => {
821
+ onSelectionSuccess?.(result);
822
+ if (showSuccessToast) {
823
+ const message = typeof successMessage === "function" ? successMessage(result) : successMessage ?? "Selection saved";
824
+ toast.success(message);
825
+ }
826
+ }, "onSuccess"),
827
+ onError: onSelectionError
828
+ });
829
+ useEffect(() => {
830
+ if (optionsToolConfig) {
831
+ optionsHook.call().then((result) => {
832
+ const options = transformOptions ? transformOptions(result) : result;
833
+ setFetchedOptions(options);
834
+ onOptionsLoaded?.(options);
835
+ }).catch(() => {
836
+ });
837
+ }
838
+ }, [
839
+ optionsToolConfig?.name
840
+ ]);
841
+ const allOptions = [
842
+ ...staticOptions,
843
+ ...fetchedOptions
844
+ ];
845
+ const value = controlledValue ?? internalValue;
846
+ const handleValueChange = useCallback((newValue) => {
847
+ setInternalValue(newValue);
848
+ onValueChange?.(newValue);
849
+ if (selectToolConfig) {
850
+ selectHook.call({
851
+ [argName]: newValue,
852
+ ...additionalArgs
853
+ });
854
+ }
855
+ }, [
856
+ onValueChange,
857
+ selectToolConfig,
858
+ argName,
859
+ additionalArgs,
860
+ selectHook
861
+ ]);
862
+ const isLoading = optionsHook.loading || selectHook.loading;
863
+ const hasError = optionsHook.error || selectHook.error;
864
+ return /* @__PURE__ */ React25.createElement(Select, {
865
+ value,
866
+ onValueChange: handleValueChange,
867
+ disabled: disabled || isLoading
868
+ }, /* @__PURE__ */ React25.createElement(SelectTrigger, {
869
+ className: cn("w-full", className)
870
+ }, isLoading ? /* @__PURE__ */ React25.createElement("div", {
871
+ className: "flex items-center gap-2"
872
+ }, /* @__PURE__ */ React25.createElement(Loader2, {
873
+ className: "h-4 w-4 animate-spin"
874
+ }), /* @__PURE__ */ React25.createElement("span", {
875
+ className: "text-muted-foreground"
876
+ }, optionsHook.loading ? loadingPlaceholder : "Saving...")) : /* @__PURE__ */ React25.createElement(SelectValue, {
877
+ placeholder
878
+ })), /* @__PURE__ */ React25.createElement(SelectContent, null, allOptions.length === 0 ? /* @__PURE__ */ React25.createElement("div", {
879
+ className: "py-6 text-center text-sm text-muted-foreground"
880
+ }, hasError ? "Error loading options" : emptyMessage) : allOptions.map((option) => /* @__PURE__ */ React25.createElement(SelectItem, {
881
+ key: option.value,
882
+ value: option.value,
883
+ disabled: option.disabled
884
+ }, /* @__PURE__ */ React25.createElement("div", {
885
+ className: "flex items-center gap-2"
886
+ }, option.icon, /* @__PURE__ */ React25.createElement("div", null, /* @__PURE__ */ React25.createElement("div", null, option.label), option.description && /* @__PURE__ */ React25.createElement("div", {
887
+ className: "text-xs text-muted-foreground"
888
+ }, option.description)))))));
889
+ }
890
+ __name(ToolSelect, "ToolSelect");
891
+ function Input({ className, type, ...props }) {
892
+ return /* @__PURE__ */ React25.createElement("input", {
893
+ type,
894
+ "data-slot": "input",
895
+ className: cn("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className),
896
+ ...props
897
+ });
898
+ }
899
+ __name(Input, "Input");
900
+ function Command({ className, ...props }) {
901
+ return /* @__PURE__ */ React25.createElement(Command$1, {
902
+ "data-slot": "command",
903
+ className: cn("bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md", className),
904
+ ...props
905
+ });
906
+ }
907
+ __name(Command, "Command");
908
+ function CommandDialog({ title = "Command Palette", description = "Search for a command to run...", children, className, showCloseButton = true, ...props }) {
909
+ return /* @__PURE__ */ React25.createElement(Dialog, props, /* @__PURE__ */ React25.createElement(DialogHeader, {
910
+ className: "sr-only"
911
+ }, /* @__PURE__ */ React25.createElement(DialogTitle, null, title), /* @__PURE__ */ React25.createElement(DialogDescription, null, description)), /* @__PURE__ */ React25.createElement(DialogContent, {
912
+ className: cn("overflow-hidden p-0", className),
913
+ showCloseButton
914
+ }, /* @__PURE__ */ React25.createElement(Command, {
915
+ className: "[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"
916
+ }, children)));
917
+ }
918
+ __name(CommandDialog, "CommandDialog");
919
+ function CommandInput({ className, ...props }) {
920
+ return /* @__PURE__ */ React25.createElement("div", {
921
+ "data-slot": "command-input-wrapper",
922
+ className: "flex h-9 items-center gap-2 border-b px-3"
923
+ }, /* @__PURE__ */ React25.createElement(SearchIcon, {
924
+ className: "size-4 shrink-0 opacity-50"
925
+ }), /* @__PURE__ */ React25.createElement(Command$1.Input, {
926
+ "data-slot": "command-input",
927
+ className: cn("placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50", className),
928
+ ...props
929
+ }));
930
+ }
931
+ __name(CommandInput, "CommandInput");
932
+ function CommandList({ className, ...props }) {
933
+ return /* @__PURE__ */ React25.createElement(Command$1.List, {
934
+ "data-slot": "command-list",
935
+ className: cn("max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto", className),
936
+ ...props
937
+ });
938
+ }
939
+ __name(CommandList, "CommandList");
940
+ function CommandEmpty({ ...props }) {
941
+ return /* @__PURE__ */ React25.createElement(Command$1.Empty, {
942
+ "data-slot": "command-empty",
943
+ className: "py-6 text-center text-sm",
944
+ ...props
945
+ });
946
+ }
947
+ __name(CommandEmpty, "CommandEmpty");
948
+ function CommandGroup({ className, ...props }) {
949
+ return /* @__PURE__ */ React25.createElement(Command$1.Group, {
950
+ "data-slot": "command-group",
951
+ className: cn("text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium", className),
952
+ ...props
953
+ });
954
+ }
955
+ __name(CommandGroup, "CommandGroup");
956
+ function CommandSeparator({ className, ...props }) {
957
+ return /* @__PURE__ */ React25.createElement(Command$1.Separator, {
958
+ "data-slot": "command-separator",
959
+ className: cn("bg-border -mx-1 h-px", className),
960
+ ...props
961
+ });
962
+ }
963
+ __name(CommandSeparator, "CommandSeparator");
964
+ function CommandItem({ className, ...props }) {
965
+ return /* @__PURE__ */ React25.createElement(Command$1.Item, {
966
+ "data-slot": "command-item",
967
+ className: cn("data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
968
+ ...props
969
+ });
970
+ }
971
+ __name(CommandItem, "CommandItem");
972
+ function CommandShortcut({ className, ...props }) {
973
+ return /* @__PURE__ */ React25.createElement("span", {
974
+ "data-slot": "command-shortcut",
975
+ className: cn("text-muted-foreground ml-auto text-xs tracking-widest", className),
976
+ ...props
977
+ });
978
+ }
979
+ __name(CommandShortcut, "CommandShortcut");
980
+ function Popover({ ...props }) {
981
+ return /* @__PURE__ */ React25.createElement(PopoverPrimitive.Root, {
982
+ "data-slot": "popover",
983
+ ...props
984
+ });
985
+ }
986
+ __name(Popover, "Popover");
987
+ function PopoverTrigger({ ...props }) {
988
+ return /* @__PURE__ */ React25.createElement(PopoverPrimitive.Trigger, {
989
+ "data-slot": "popover-trigger",
990
+ ...props
991
+ });
992
+ }
993
+ __name(PopoverTrigger, "PopoverTrigger");
994
+ function PopoverContent({ className, align = "center", sideOffset = 4, ...props }) {
995
+ return /* @__PURE__ */ React25.createElement(PopoverPrimitive.Portal, null, /* @__PURE__ */ React25.createElement(PopoverPrimitive.Content, {
996
+ "data-slot": "popover-content",
997
+ align,
998
+ sideOffset,
999
+ className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden", className),
1000
+ ...props
1001
+ }));
1002
+ }
1003
+ __name(PopoverContent, "PopoverContent");
1004
+ function PopoverAnchor({ ...props }) {
1005
+ return /* @__PURE__ */ React25.createElement(PopoverPrimitive.Anchor, {
1006
+ "data-slot": "popover-anchor",
1007
+ ...props
1008
+ });
1009
+ }
1010
+ __name(PopoverAnchor, "PopoverAnchor");
1011
+
1012
+ // src/mcp/ToolInput.tsx
1013
+ function ToolInput({ searchTool, debounce = 300, minChars = 1, argName = "query", additionalArgs = {}, autocomplete = false, transformSuggestions, onSuggestionSelect, emptyMessage = "No results found", value: controlledValue, onChange, onSearchResults, onSearchError, showSearchIcon = true, showClearButton = true, showLoadingIndicator = true, className, placeholder = "Search...", disabled, ...props }) {
1014
+ const [internalValue, setInternalValue] = useState("");
1015
+ const [suggestions, setSuggestions] = useState([]);
1016
+ const [isOpen, setIsOpen] = useState(false);
1017
+ const debounceRef = useRef(null);
1018
+ const inputRef = useRef(null);
1019
+ const toolConfig = searchTool ? typeof searchTool === "string" ? {
1020
+ name: searchTool
1021
+ } : searchTool : null;
1022
+ const { call, loading, error, reset } = useTool(toolConfig?.name ?? "", {
1023
+ defaultArgs: {
1024
+ ...toolConfig?.args,
1025
+ ...additionalArgs
1026
+ },
1027
+ onSuccess: /* @__PURE__ */ __name((result) => {
1028
+ onSearchResults?.(result);
1029
+ if (autocomplete && transformSuggestions) {
1030
+ const suggestions2 = transformSuggestions(result);
1031
+ setSuggestions(suggestions2);
1032
+ if (suggestions2.length > 0) {
1033
+ setIsOpen(true);
1034
+ }
1035
+ }
1036
+ }, "onSuccess"),
1037
+ onError: onSearchError
1038
+ });
1039
+ const value = controlledValue ?? internalValue;
1040
+ const handleChange = useCallback((e) => {
1041
+ const newValue = e.target.value;
1042
+ setInternalValue(newValue);
1043
+ onChange?.(newValue);
1044
+ if (debounceRef.current) {
1045
+ clearTimeout(debounceRef.current);
1046
+ }
1047
+ if (newValue.length < minChars) {
1048
+ setSuggestions([]);
1049
+ setIsOpen(false);
1050
+ return;
1051
+ }
1052
+ if (toolConfig) {
1053
+ debounceRef.current = setTimeout(() => {
1054
+ call({
1055
+ [argName]: newValue
1056
+ });
1057
+ }, debounce);
1058
+ }
1059
+ }, [
1060
+ onChange,
1061
+ minChars,
1062
+ toolConfig,
1063
+ argName,
1064
+ debounce,
1065
+ call
1066
+ ]);
1067
+ const handleClear = useCallback(() => {
1068
+ setInternalValue("");
1069
+ onChange?.("");
1070
+ setSuggestions([]);
1071
+ setIsOpen(false);
1072
+ reset();
1073
+ inputRef.current?.focus();
1074
+ }, [
1075
+ onChange,
1076
+ reset
1077
+ ]);
1078
+ const handleSelect = useCallback((suggestion) => {
1079
+ setInternalValue(suggestion.label);
1080
+ onChange?.(suggestion.label);
1081
+ setIsOpen(false);
1082
+ onSuggestionSelect?.(suggestion);
1083
+ }, [
1084
+ onChange,
1085
+ onSuggestionSelect
1086
+ ]);
1087
+ useEffect(() => {
1088
+ return () => {
1089
+ if (debounceRef.current) {
1090
+ clearTimeout(debounceRef.current);
1091
+ }
1092
+ };
1093
+ }, []);
1094
+ const inputElement = /* @__PURE__ */ React25.createElement("div", {
1095
+ className: cn("relative", className)
1096
+ }, showSearchIcon && /* @__PURE__ */ React25.createElement(Search, {
1097
+ className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"
1098
+ }), /* @__PURE__ */ React25.createElement(Input, {
1099
+ ref: inputRef,
1100
+ value,
1101
+ onChange: handleChange,
1102
+ placeholder,
1103
+ disabled,
1104
+ className: cn(showSearchIcon && "pl-9", (showClearButton || showLoadingIndicator) && "pr-9"),
1105
+ ...props
1106
+ }), /* @__PURE__ */ React25.createElement("div", {
1107
+ className: "absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1"
1108
+ }, showLoadingIndicator && loading && /* @__PURE__ */ React25.createElement(Loader2, {
1109
+ className: "h-4 w-4 animate-spin text-muted-foreground"
1110
+ }), showClearButton && value && !loading && /* @__PURE__ */ React25.createElement("button", {
1111
+ type: "button",
1112
+ onClick: handleClear,
1113
+ className: "h-4 w-4 text-muted-foreground hover:text-foreground transition-colors"
1114
+ }, /* @__PURE__ */ React25.createElement(X, {
1115
+ className: "h-4 w-4"
1116
+ }))));
1117
+ if (!autocomplete) {
1118
+ return inputElement;
1119
+ }
1120
+ return /* @__PURE__ */ React25.createElement(Popover, {
1121
+ open: isOpen,
1122
+ onOpenChange: setIsOpen
1123
+ }, /* @__PURE__ */ React25.createElement(PopoverTrigger, {
1124
+ asChild: true
1125
+ }, inputElement), /* @__PURE__ */ React25.createElement(PopoverContent, {
1126
+ className: "p-0 w-[var(--radix-popover-trigger-width)]",
1127
+ align: "start",
1128
+ onOpenAutoFocus: /* @__PURE__ */ __name((e) => e.preventDefault(), "onOpenAutoFocus")
1129
+ }, /* @__PURE__ */ React25.createElement(Command, null, /* @__PURE__ */ React25.createElement(CommandList, null, /* @__PURE__ */ React25.createElement(CommandEmpty, null, emptyMessage), /* @__PURE__ */ React25.createElement(CommandGroup, null, suggestions.map((suggestion) => /* @__PURE__ */ React25.createElement(CommandItem, {
1130
+ key: suggestion.value,
1131
+ value: suggestion.value,
1132
+ onSelect: /* @__PURE__ */ __name(() => handleSelect(suggestion), "onSelect")
1133
+ }, /* @__PURE__ */ React25.createElement("div", {
1134
+ className: "flex items-center gap-2"
1135
+ }, suggestion.icon, /* @__PURE__ */ React25.createElement("div", null, /* @__PURE__ */ React25.createElement("div", null, suggestion.label), suggestion.description && /* @__PURE__ */ React25.createElement("div", {
1136
+ className: "text-xs text-muted-foreground"
1137
+ }, suggestion.description))))))))));
1138
+ }
1139
+ __name(ToolInput, "ToolInput");
1140
+ function Label2({ className, ...props }) {
1141
+ return /* @__PURE__ */ React25.createElement(LabelPrimitive.Root, {
1142
+ "data-slot": "label",
1143
+ className: cn("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className),
1144
+ ...props
1145
+ });
1146
+ }
1147
+ __name(Label2, "Label");
1148
+ function Textarea({ className, ...props }) {
1149
+ return /* @__PURE__ */ React25.createElement("textarea", {
1150
+ "data-slot": "textarea",
1151
+ className: cn("border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className),
1152
+ ...props
1153
+ });
1154
+ }
1155
+ __name(Textarea, "Textarea");
1156
+ function Checkbox({ className, ...props }) {
1157
+ return /* @__PURE__ */ React25.createElement(CheckboxPrimitive.Root, {
1158
+ "data-slot": "checkbox",
1159
+ className: cn("peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", className),
1160
+ ...props
1161
+ }, /* @__PURE__ */ React25.createElement(CheckboxPrimitive.Indicator, {
1162
+ "data-slot": "checkbox-indicator",
1163
+ className: "grid place-content-center text-current transition-none"
1164
+ }, /* @__PURE__ */ React25.createElement(CheckIcon, {
1165
+ className: "size-3.5"
1166
+ })));
1167
+ }
1168
+ __name(Checkbox, "Checkbox");
1169
+ function Slider({ className, defaultValue, value, min = 0, max = 100, ...props }) {
1170
+ const _values = React25.useMemo(() => Array.isArray(value) ? value : Array.isArray(defaultValue) ? defaultValue : [
1171
+ min,
1172
+ max
1173
+ ], [
1174
+ value,
1175
+ defaultValue,
1176
+ min,
1177
+ max
1178
+ ]);
1179
+ return /* @__PURE__ */ React25.createElement(SliderPrimitive.Root, {
1180
+ "data-slot": "slider",
1181
+ defaultValue,
1182
+ value,
1183
+ min,
1184
+ max,
1185
+ className: cn("relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col", className),
1186
+ ...props
1187
+ }, /* @__PURE__ */ React25.createElement(SliderPrimitive.Track, {
1188
+ "data-slot": "slider-track",
1189
+ className: cn("bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5")
1190
+ }, /* @__PURE__ */ React25.createElement(SliderPrimitive.Range, {
1191
+ "data-slot": "slider-range",
1192
+ className: cn("bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full")
1193
+ })), Array.from({
1194
+ length: _values.length
1195
+ }, (_, index) => /* @__PURE__ */ React25.createElement(SliderPrimitive.Thumb, {
1196
+ "data-slot": "slider-thumb",
1197
+ key: index,
1198
+ className: "border-primary ring-ring/50 block size-4 shrink-0 rounded-full border bg-white shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
1199
+ })));
1200
+ }
1201
+ __name(Slider, "Slider");
1202
+ function Switch({ className, ...props }) {
1203
+ return /* @__PURE__ */ React25.createElement(SwitchPrimitive.Root, {
1204
+ "data-slot": "switch",
1205
+ className: cn("peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", className),
1206
+ ...props
1207
+ }, /* @__PURE__ */ React25.createElement(SwitchPrimitive.Thumb, {
1208
+ "data-slot": "switch-thumb",
1209
+ className: cn("bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block size-4 rounded-full ring-0 transition-transform data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0")
1210
+ }));
1211
+ }
1212
+ __name(Switch, "Switch");
1213
+ var alertVariants = cva("relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", {
1214
+ variants: {
1215
+ variant: {
1216
+ default: "bg-card text-card-foreground",
1217
+ destructive: "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90"
1218
+ }
1219
+ },
1220
+ defaultVariants: {
1221
+ variant: "default"
1222
+ }
1223
+ });
1224
+ function Alert({ className, variant, ...props }) {
1225
+ return /* @__PURE__ */ React25.createElement("div", {
1226
+ "data-slot": "alert",
1227
+ role: "alert",
1228
+ className: cn(alertVariants({
1229
+ variant
1230
+ }), className),
1231
+ ...props
1232
+ });
1233
+ }
1234
+ __name(Alert, "Alert");
1235
+ function AlertTitle({ className, ...props }) {
1236
+ return /* @__PURE__ */ React25.createElement("div", {
1237
+ "data-slot": "alert-title",
1238
+ className: cn("col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight", className),
1239
+ ...props
1240
+ });
1241
+ }
1242
+ __name(AlertTitle, "AlertTitle");
1243
+ function AlertDescription({ className, ...props }) {
1244
+ return /* @__PURE__ */ React25.createElement("div", {
1245
+ "data-slot": "alert-description",
1246
+ className: cn("text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed", className),
1247
+ ...props
1248
+ });
1249
+ }
1250
+ __name(AlertDescription, "AlertDescription");
1251
+ function ToolForm({ toolName, fields: manualFields, autoSchema = false, submitText = "Submit", loadingText, onSuccess, onError, showResult = false, showSuccessToast = false, successMessage, resetOnSuccess = false, className, layout = "vertical" }) {
1252
+ const { app, isConnected } = useMcpApp();
1253
+ const { call, loading, result, error, reset } = useTool(toolName, {
1254
+ onSuccess: /* @__PURE__ */ __name((result2) => {
1255
+ onSuccess?.(result2);
1256
+ if (showSuccessToast) {
1257
+ const message = typeof successMessage === "function" ? successMessage(result2) : successMessage ?? "Form submitted successfully";
1258
+ toast.success(message);
1259
+ }
1260
+ if (resetOnSuccess) {
1261
+ resetForm();
1262
+ }
1263
+ }, "onSuccess"),
1264
+ onError
1265
+ });
1266
+ const [fields, setFields] = useState(manualFields ?? []);
1267
+ const [schemaLoading, setSchemaLoading] = useState(autoSchema);
1268
+ const [formData, setFormData] = useState({});
1269
+ const initializeFormData = /* @__PURE__ */ __name((fields2) => {
1270
+ const initial = {};
1271
+ fields2.forEach((field) => {
1272
+ if (field.defaultValue !== void 0) {
1273
+ initial[field.name] = field.defaultValue;
1274
+ } else if (field.type === "checkbox" || field.type === "switch") {
1275
+ initial[field.name] = false;
1276
+ } else if (field.type === "number" || field.type === "slider") {
1277
+ initial[field.name] = field.min ?? 0;
1278
+ } else {
1279
+ initial[field.name] = "";
1280
+ }
1281
+ });
1282
+ setFormData(initial);
1283
+ }, "initializeFormData");
1284
+ const resetForm = /* @__PURE__ */ __name(() => {
1285
+ initializeFormData(fields);
1286
+ reset();
1287
+ }, "resetForm");
1288
+ useEffect(() => {
1289
+ if (autoSchema && app && isConnected) {
1290
+ setSchemaLoading(true);
1291
+ const fetchSchema = /* @__PURE__ */ __name(async () => {
1292
+ try {
1293
+ console.warn("[ToolForm] Auto-schema not fully implemented, use manual fields");
1294
+ if (manualFields) {
1295
+ setFields(manualFields);
1296
+ initializeFormData(manualFields);
1297
+ }
1298
+ } catch (err) {
1299
+ console.error("[ToolForm] Failed to fetch schema:", err);
1300
+ } finally {
1301
+ setSchemaLoading(false);
1302
+ }
1303
+ }, "fetchSchema");
1304
+ fetchSchema();
1305
+ } else if (manualFields) {
1306
+ setFields(manualFields);
1307
+ initializeFormData(manualFields);
1308
+ }
1309
+ }, [
1310
+ autoSchema,
1311
+ app,
1312
+ isConnected,
1313
+ manualFields,
1314
+ toolName
1315
+ ]);
1316
+ const handleSubmit = /* @__PURE__ */ __name(async (e) => {
1317
+ e.preventDefault();
1318
+ const args = {};
1319
+ fields.forEach((field) => {
1320
+ let value = formData[field.name];
1321
+ if (field.type === "number" || field.type === "slider") {
1322
+ value = Number(value);
1323
+ }
1324
+ args[field.name] = value;
1325
+ });
1326
+ await call(args);
1327
+ }, "handleSubmit");
1328
+ const handleChange = /* @__PURE__ */ __name((name, value) => {
1329
+ setFormData((prev) => ({
1330
+ ...prev,
1331
+ [name]: value
1332
+ }));
1333
+ }, "handleChange");
1334
+ const renderField = /* @__PURE__ */ __name((field) => {
1335
+ const value = formData[field.name];
1336
+ switch (field.type) {
1337
+ case "textarea":
1338
+ return /* @__PURE__ */ React25.createElement(Textarea, {
1339
+ id: field.name,
1340
+ placeholder: field.placeholder,
1341
+ value: value ?? "",
1342
+ onChange: /* @__PURE__ */ __name((e) => handleChange(field.name, e.target.value), "onChange"),
1343
+ disabled: field.disabled || loading,
1344
+ required: field.required
1345
+ });
1346
+ case "select":
1347
+ return /* @__PURE__ */ React25.createElement(Select, {
1348
+ value: value ?? "",
1349
+ onValueChange: /* @__PURE__ */ __name((v) => handleChange(field.name, v), "onValueChange"),
1350
+ disabled: field.disabled || loading
1351
+ }, /* @__PURE__ */ React25.createElement(SelectTrigger, null, /* @__PURE__ */ React25.createElement(SelectValue, {
1352
+ placeholder: field.placeholder ?? "Select..."
1353
+ })), /* @__PURE__ */ React25.createElement(SelectContent, null, field.options?.map((option) => /* @__PURE__ */ React25.createElement(SelectItem, {
1354
+ key: option.value,
1355
+ value: option.value
1356
+ }, option.label))));
1357
+ case "checkbox":
1358
+ return /* @__PURE__ */ React25.createElement("div", {
1359
+ className: "flex items-center space-x-2"
1360
+ }, /* @__PURE__ */ React25.createElement(Checkbox, {
1361
+ id: field.name,
1362
+ checked: value ?? false,
1363
+ onCheckedChange: /* @__PURE__ */ __name((checked) => handleChange(field.name, checked), "onCheckedChange"),
1364
+ disabled: field.disabled || loading
1365
+ }), /* @__PURE__ */ React25.createElement("label", {
1366
+ htmlFor: field.name,
1367
+ className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
1368
+ }, field.label));
1369
+ case "switch":
1370
+ return /* @__PURE__ */ React25.createElement("div", {
1371
+ className: "flex items-center space-x-2"
1372
+ }, /* @__PURE__ */ React25.createElement(Switch, {
1373
+ id: field.name,
1374
+ checked: value ?? false,
1375
+ onCheckedChange: /* @__PURE__ */ __name((checked) => handleChange(field.name, checked), "onCheckedChange"),
1376
+ disabled: field.disabled || loading
1377
+ }), /* @__PURE__ */ React25.createElement(Label2, {
1378
+ htmlFor: field.name
1379
+ }, field.label));
1380
+ case "slider":
1381
+ return /* @__PURE__ */ React25.createElement("div", {
1382
+ className: "space-y-2"
1383
+ }, /* @__PURE__ */ React25.createElement("div", {
1384
+ className: "flex justify-between text-sm"
1385
+ }, /* @__PURE__ */ React25.createElement("span", null, field.min ?? 0), /* @__PURE__ */ React25.createElement("span", null, value ?? field.min ?? 0), /* @__PURE__ */ React25.createElement("span", null, field.max ?? 100)), /* @__PURE__ */ React25.createElement(Slider, {
1386
+ value: [
1387
+ value ?? field.min ?? 0
1388
+ ],
1389
+ onValueChange: /* @__PURE__ */ __name(([v]) => handleChange(field.name, v), "onValueChange"),
1390
+ min: field.min ?? 0,
1391
+ max: field.max ?? 100,
1392
+ step: field.step ?? 1,
1393
+ disabled: field.disabled || loading
1394
+ }));
1395
+ case "number":
1396
+ return /* @__PURE__ */ React25.createElement(Input, {
1397
+ id: field.name,
1398
+ type: "number",
1399
+ placeholder: field.placeholder,
1400
+ value: value ?? "",
1401
+ onChange: /* @__PURE__ */ __name((e) => handleChange(field.name, e.target.value), "onChange"),
1402
+ min: field.min,
1403
+ max: field.max,
1404
+ step: field.step,
1405
+ disabled: field.disabled || loading,
1406
+ required: field.required
1407
+ });
1408
+ default:
1409
+ return /* @__PURE__ */ React25.createElement(Input, {
1410
+ id: field.name,
1411
+ type: field.type ?? "text",
1412
+ placeholder: field.placeholder,
1413
+ value: value ?? "",
1414
+ onChange: /* @__PURE__ */ __name((e) => handleChange(field.name, e.target.value), "onChange"),
1415
+ disabled: field.disabled || loading,
1416
+ required: field.required
1417
+ });
1418
+ }
1419
+ }, "renderField");
1420
+ if (schemaLoading) {
1421
+ return /* @__PURE__ */ React25.createElement("div", {
1422
+ className: "flex items-center justify-center p-8"
1423
+ }, /* @__PURE__ */ React25.createElement(Loader2, {
1424
+ className: "h-6 w-6 animate-spin text-muted-foreground"
1425
+ }));
1426
+ }
1427
+ return /* @__PURE__ */ React25.createElement("form", {
1428
+ className: cn("space-y-4", className),
1429
+ onSubmit: handleSubmit
1430
+ }, /* @__PURE__ */ React25.createElement("div", {
1431
+ className: cn("space-y-4", layout === "horizontal" && "grid grid-cols-2 gap-4")
1432
+ }, fields.map((field) => /* @__PURE__ */ React25.createElement("div", {
1433
+ key: field.name,
1434
+ className: "space-y-2"
1435
+ }, field.type !== "checkbox" && field.type !== "switch" && /* @__PURE__ */ React25.createElement(Label2, {
1436
+ htmlFor: field.name
1437
+ }, field.label, field.required && /* @__PURE__ */ React25.createElement("span", {
1438
+ className: "text-destructive ml-1"
1439
+ }, "*")), renderField(field), field.description && /* @__PURE__ */ React25.createElement("p", {
1440
+ className: "text-sm text-muted-foreground"
1441
+ }, field.description)))), /* @__PURE__ */ React25.createElement("div", {
1442
+ className: "flex items-center gap-2"
1443
+ }, /* @__PURE__ */ React25.createElement(Button, {
1444
+ type: "submit",
1445
+ disabled: loading
1446
+ }, loading ? /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement(Loader2, {
1447
+ className: "h-4 w-4 animate-spin mr-2"
1448
+ }), loadingText ?? "Submitting...") : submitText)), error && /* @__PURE__ */ React25.createElement(Alert, {
1449
+ variant: "destructive"
1450
+ }, /* @__PURE__ */ React25.createElement(AlertDescription, null, error.message)), showResult && result !== null && /* @__PURE__ */ React25.createElement("div", {
1451
+ className: "rounded-md bg-muted p-4"
1452
+ }, /* @__PURE__ */ React25.createElement("pre", {
1453
+ className: "text-sm overflow-auto"
1454
+ }, JSON.stringify(result, null, 2))));
1455
+ }
1456
+ __name(ToolForm, "ToolForm");
1457
+ function useResource(uri, options = {}) {
1458
+ const { app, isConnected } = useMcpApp();
1459
+ const { refreshInterval, subscribe = false, transform, skip = false } = options;
1460
+ const [data, setData] = useState(null);
1461
+ const [loading, setLoading] = useState(!skip);
1462
+ const [error, setError] = useState(null);
1463
+ const [lastUpdated, setLastUpdated] = useState(null);
1464
+ const intervalRef = useRef(null);
1465
+ const mountedRef = useRef(true);
1466
+ const fetchResource = useCallback(async () => {
1467
+ if (!app || !isConnected) {
1468
+ throw new Error("Not connected to MCP host");
1469
+ }
1470
+ setLoading(true);
1471
+ setError(null);
1472
+ try {
1473
+ const result = await app.readResource?.({
1474
+ uri
1475
+ });
1476
+ if (!result) {
1477
+ throw new Error("readResource not supported by host");
1478
+ }
1479
+ let resourceData;
1480
+ if (result.contents && result.contents.length > 0) {
1481
+ const content = result.contents[0];
1482
+ if (content.text) {
1483
+ try {
1484
+ resourceData = JSON.parse(content.text);
1485
+ } catch {
1486
+ resourceData = content.text;
1487
+ }
1488
+ } else if (content.blob) {
1489
+ resourceData = content.blob;
1490
+ } else {
1491
+ resourceData = content;
1492
+ }
1493
+ } else {
1494
+ resourceData = result;
1495
+ }
1496
+ if (transform) {
1497
+ resourceData = transform(resourceData);
1498
+ }
1499
+ if (mountedRef.current) {
1500
+ setData(resourceData);
1501
+ setLastUpdated(/* @__PURE__ */ new Date());
1502
+ setLoading(false);
1503
+ }
1504
+ return resourceData;
1505
+ } catch (err) {
1506
+ const error2 = err instanceof Error ? err : new Error(String(err));
1507
+ if (mountedRef.current) {
1508
+ setError(error2);
1509
+ setLoading(false);
1510
+ }
1511
+ throw error2;
1512
+ }
1513
+ }, [
1514
+ app,
1515
+ isConnected,
1516
+ uri,
1517
+ transform
1518
+ ]);
1519
+ const refresh = useCallback(async () => {
1520
+ return fetchResource();
1521
+ }, [
1522
+ fetchResource
1523
+ ]);
1524
+ useEffect(() => {
1525
+ mountedRef.current = true;
1526
+ if (!skip && isConnected) {
1527
+ fetchResource().catch(() => {
1528
+ });
1529
+ }
1530
+ return () => {
1531
+ mountedRef.current = false;
1532
+ };
1533
+ }, [
1534
+ uri,
1535
+ isConnected,
1536
+ skip,
1537
+ fetchResource
1538
+ ]);
1539
+ useEffect(() => {
1540
+ if (refreshInterval && refreshInterval > 0 && isConnected && !skip) {
1541
+ intervalRef.current = setInterval(() => {
1542
+ fetchResource().catch(() => {
1543
+ });
1544
+ }, refreshInterval);
1545
+ }
1546
+ return () => {
1547
+ if (intervalRef.current) {
1548
+ clearInterval(intervalRef.current);
1549
+ intervalRef.current = null;
1550
+ }
1551
+ };
1552
+ }, [
1553
+ refreshInterval,
1554
+ isConnected,
1555
+ skip,
1556
+ fetchResource
1557
+ ]);
1558
+ useEffect(() => {
1559
+ if (subscribe) {
1560
+ console.warn("[useResource] Subscription support not yet implemented");
1561
+ }
1562
+ }, [
1563
+ subscribe
1564
+ ]);
1565
+ return {
1566
+ data,
1567
+ loading,
1568
+ error,
1569
+ refresh,
1570
+ lastUpdated
1571
+ };
1572
+ }
1573
+ __name(useResource, "useResource");
1574
+ function Skeleton({ className, ...props }) {
1575
+ return /* @__PURE__ */ React25__default.createElement("div", {
1576
+ "data-slot": "skeleton",
1577
+ className: cn("bg-accent animate-pulse rounded-md", className),
1578
+ ...props
1579
+ });
1580
+ }
1581
+ __name(Skeleton, "Skeleton");
1582
+
1583
+ // src/mcp/ResourceView.tsx
1584
+ function DefaultLoading() {
1585
+ return /* @__PURE__ */ React25.createElement("div", {
1586
+ className: "flex flex-col gap-3 p-4"
1587
+ }, /* @__PURE__ */ React25.createElement(Skeleton, {
1588
+ className: "h-4 w-3/4"
1589
+ }), /* @__PURE__ */ React25.createElement(Skeleton, {
1590
+ className: "h-4 w-1/2"
1591
+ }), /* @__PURE__ */ React25.createElement(Skeleton, {
1592
+ className: "h-20 w-full"
1593
+ }));
1594
+ }
1595
+ __name(DefaultLoading, "DefaultLoading");
1596
+ function DefaultError({ error, onRetry }) {
1597
+ return /* @__PURE__ */ React25.createElement(Alert, {
1598
+ variant: "destructive"
1599
+ }, /* @__PURE__ */ React25.createElement(AlertCircle, {
1600
+ className: "h-4 w-4"
1601
+ }), /* @__PURE__ */ React25.createElement(AlertTitle, null, "Error loading resource"), /* @__PURE__ */ React25.createElement(AlertDescription, {
1602
+ className: "flex flex-col gap-2"
1603
+ }, /* @__PURE__ */ React25.createElement("span", null, error.message), /* @__PURE__ */ React25.createElement(Button, {
1604
+ variant: "outline",
1605
+ size: "sm",
1606
+ onClick: onRetry,
1607
+ className: "w-fit"
1608
+ }, /* @__PURE__ */ React25.createElement(RefreshCw, {
1609
+ className: "h-4 w-4 mr-2"
1610
+ }), "Retry")));
1611
+ }
1612
+ __name(DefaultError, "DefaultError");
1613
+ function ResourceView({ uri, refreshInterval, subscribe, transform, loading: loadingContent, error: errorContent, children, className, skip = false }) {
1614
+ const { data, loading, error, refresh, lastUpdated } = useResource(uri, {
1615
+ refreshInterval,
1616
+ subscribe,
1617
+ transform,
1618
+ skip
1619
+ });
1620
+ const meta = {
1621
+ uri,
1622
+ refresh,
1623
+ lastUpdated,
1624
+ isRefreshing: loading && data !== null
1625
+ };
1626
+ if (loading && data === null) {
1627
+ if (loadingContent) {
1628
+ return /* @__PURE__ */ React25.createElement("div", {
1629
+ className
1630
+ }, loadingContent);
1631
+ }
1632
+ return /* @__PURE__ */ React25.createElement("div", {
1633
+ className: cn("flex items-center justify-center p-8", className)
1634
+ }, /* @__PURE__ */ React25.createElement(Loader2, {
1635
+ className: "h-8 w-8 animate-spin text-muted-foreground"
1636
+ }));
1637
+ }
1638
+ if (error && data === null) {
1639
+ if (errorContent) {
1640
+ if (typeof errorContent === "function") {
1641
+ return /* @__PURE__ */ React25.createElement("div", {
1642
+ className
1643
+ }, errorContent(error, refresh));
1644
+ }
1645
+ return /* @__PURE__ */ React25.createElement("div", {
1646
+ className
1647
+ }, errorContent);
1648
+ }
1649
+ return /* @__PURE__ */ React25.createElement("div", {
1650
+ className
1651
+ }, /* @__PURE__ */ React25.createElement(DefaultError, {
1652
+ error,
1653
+ onRetry: refresh
1654
+ }));
1655
+ }
1656
+ if (data !== null) {
1657
+ return /* @__PURE__ */ React25.createElement("div", {
1658
+ className
1659
+ }, children(data, meta));
1660
+ }
1661
+ return /* @__PURE__ */ React25.createElement("div", {
1662
+ className
1663
+ }, loadingContent ?? /* @__PURE__ */ React25.createElement(DefaultLoading, null));
1664
+ }
1665
+ __name(ResourceView, "ResourceView");
1666
+ function useToolStream(options = {}) {
1667
+ const { toolInputPartial, toolInput, toolResult } = useMcpApp();
1668
+ const { onPartial, onComplete } = options;
1669
+ const [partial, setPartial] = useState(null);
1670
+ const [complete, setComplete] = useState(null);
1671
+ const [isStreaming, setIsStreaming] = useState(false);
1672
+ const [isComplete, setIsComplete] = useState(false);
1673
+ useEffect(() => {
1674
+ if (toolInputPartial) {
1675
+ setPartial(toolInputPartial);
1676
+ setIsStreaming(true);
1677
+ setIsComplete(false);
1678
+ onPartial?.(toolInputPartial);
1679
+ }
1680
+ }, [
1681
+ toolInputPartial,
1682
+ onPartial
1683
+ ]);
1684
+ useEffect(() => {
1685
+ if (toolInput) {
1686
+ setComplete(toolInput);
1687
+ setIsStreaming(false);
1688
+ setIsComplete(true);
1689
+ onComplete?.(toolInput);
1690
+ }
1691
+ }, [
1692
+ toolInput,
1693
+ onComplete
1694
+ ]);
1695
+ useEffect(() => {
1696
+ if (toolResult && !toolResult.isError) {
1697
+ setIsStreaming(false);
1698
+ setIsComplete(true);
1699
+ }
1700
+ }, [
1701
+ toolResult
1702
+ ]);
1703
+ return {
1704
+ partial,
1705
+ complete,
1706
+ isStreaming,
1707
+ isComplete
1708
+ };
1709
+ }
1710
+ __name(useToolStream, "useToolStream");
1711
+ function Progress({ className, value, ...props }) {
1712
+ return /* @__PURE__ */ React25.createElement(ProgressPrimitive.Root, {
1713
+ "data-slot": "progress",
1714
+ className: cn("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className),
1715
+ ...props
1716
+ }, /* @__PURE__ */ React25.createElement(ProgressPrimitive.Indicator, {
1717
+ "data-slot": "progress-indicator",
1718
+ className: "bg-primary h-full w-full flex-1 transition-all",
1719
+ style: {
1720
+ transform: `translateX(-${100 - (value || 0)}%)`
1721
+ }
1722
+ }));
1723
+ }
1724
+ __name(Progress, "Progress");
1725
+
1726
+ // src/mcp/StreamingContent.tsx
1727
+ function StreamingContent({ fallback, showProgress = false, progress: externalProgress, onPartial, onComplete, children, className, streamingStyle = "opacity" }) {
1728
+ const { partial, complete, isStreaming, isComplete } = useToolStream({
1729
+ onPartial,
1730
+ onComplete
1731
+ });
1732
+ const data = complete ?? partial;
1733
+ if (!data) {
1734
+ if (fallback) {
1735
+ return /* @__PURE__ */ React25.createElement("div", {
1736
+ className
1737
+ }, fallback);
1738
+ }
1739
+ return /* @__PURE__ */ React25.createElement("div", {
1740
+ className: cn("flex items-center justify-center p-8", className)
1741
+ }, /* @__PURE__ */ React25.createElement(Loader2, {
1742
+ className: "h-6 w-6 animate-spin text-muted-foreground"
1743
+ }));
1744
+ }
1745
+ const streamingClasses = cn(streamingStyle === "opacity" && isStreaming && "opacity-70", streamingStyle === "blur" && isStreaming && "blur-[1px]");
1746
+ return /* @__PURE__ */ React25.createElement("div", {
1747
+ className: cn("relative", className)
1748
+ }, showProgress && isStreaming && /* @__PURE__ */ React25.createElement("div", {
1749
+ className: "absolute top-0 left-0 right-0 z-10"
1750
+ }, externalProgress !== void 0 ? /* @__PURE__ */ React25.createElement(Progress, {
1751
+ value: externalProgress,
1752
+ className: "h-1"
1753
+ }) : /* @__PURE__ */ React25.createElement("div", {
1754
+ className: "h-1 bg-primary/20 overflow-hidden"
1755
+ }, /* @__PURE__ */ React25.createElement("div", {
1756
+ className: "h-full w-1/3 bg-primary animate-[shimmer_1s_infinite]"
1757
+ }))), isStreaming && /* @__PURE__ */ React25.createElement("div", {
1758
+ className: "absolute top-2 right-2 z-10"
1759
+ }, /* @__PURE__ */ React25.createElement("div", {
1760
+ className: "flex items-center gap-1 px-2 py-1 rounded-full bg-muted text-muted-foreground text-xs"
1761
+ }, /* @__PURE__ */ React25.createElement(Loader2, {
1762
+ className: "h-3 w-3 animate-spin"
1763
+ }), /* @__PURE__ */ React25.createElement("span", null, "Streaming..."))), /* @__PURE__ */ React25.createElement("div", {
1764
+ className: cn("transition-all duration-200", streamingClasses)
1765
+ }, children(data, isComplete)));
1766
+ }
1767
+ __name(StreamingContent, "StreamingContent");
1768
+ function Table({ className, ...props }) {
1769
+ return /* @__PURE__ */ React25.createElement("div", {
1770
+ "data-slot": "table-container",
1771
+ className: "relative w-full overflow-x-auto"
1772
+ }, /* @__PURE__ */ React25.createElement("table", {
1773
+ "data-slot": "table",
1774
+ className: cn("w-full caption-bottom text-sm", className),
1775
+ ...props
1776
+ }));
1777
+ }
1778
+ __name(Table, "Table");
1779
+ function TableHeader({ className, ...props }) {
1780
+ return /* @__PURE__ */ React25.createElement("thead", {
1781
+ "data-slot": "table-header",
1782
+ className: cn("[&_tr]:border-b", className),
1783
+ ...props
1784
+ });
1785
+ }
1786
+ __name(TableHeader, "TableHeader");
1787
+ function TableBody({ className, ...props }) {
1788
+ return /* @__PURE__ */ React25.createElement("tbody", {
1789
+ "data-slot": "table-body",
1790
+ className: cn("[&_tr:last-child]:border-0", className),
1791
+ ...props
1792
+ });
1793
+ }
1794
+ __name(TableBody, "TableBody");
1795
+ function TableFooter({ className, ...props }) {
1796
+ return /* @__PURE__ */ React25.createElement("tfoot", {
1797
+ "data-slot": "table-footer",
1798
+ className: cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className),
1799
+ ...props
1800
+ });
1801
+ }
1802
+ __name(TableFooter, "TableFooter");
1803
+ function TableRow({ className, ...props }) {
1804
+ return /* @__PURE__ */ React25.createElement("tr", {
1805
+ "data-slot": "table-row",
1806
+ className: cn("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors", className),
1807
+ ...props
1808
+ });
1809
+ }
1810
+ __name(TableRow, "TableRow");
1811
+ function TableHead({ className, ...props }) {
1812
+ return /* @__PURE__ */ React25.createElement("th", {
1813
+ "data-slot": "table-head",
1814
+ className: cn("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className),
1815
+ ...props
1816
+ });
1817
+ }
1818
+ __name(TableHead, "TableHead");
1819
+ function TableCell({ className, ...props }) {
1820
+ return /* @__PURE__ */ React25.createElement("td", {
1821
+ "data-slot": "table-cell",
1822
+ className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", className),
1823
+ ...props
1824
+ });
1825
+ }
1826
+ __name(TableCell, "TableCell");
1827
+ function TableCaption({ className, ...props }) {
1828
+ return /* @__PURE__ */ React25.createElement("caption", {
1829
+ "data-slot": "table-caption",
1830
+ className: cn("text-muted-foreground mt-4 text-sm", className),
1831
+ ...props
1832
+ });
1833
+ }
1834
+ __name(TableCaption, "TableCaption");
1835
+ function getNestedValue(obj, path) {
1836
+ return path.split(".").reduce((current, key) => {
1837
+ if (current && typeof current === "object" && key in current) {
1838
+ return current[key];
1839
+ }
1840
+ return void 0;
1841
+ }, obj);
1842
+ }
1843
+ __name(getNestedValue, "getNestedValue");
1844
+ function ToolDataGrid({ dataTool, columns, transformData, rowActions = [], pagination = true, pageSizes = [
1845
+ 10,
1846
+ 25,
1847
+ 50,
1848
+ 100
1849
+ ], defaultPageSize = 10, defaultSort, refreshInterval, showRefresh = true, onDataLoaded, onError, onRowClick, getRowKey, emptyContent, loadingContent, className }) {
1850
+ if (!dataTool) {
1851
+ throw new Error("ToolDataGrid: dataTool prop is required");
1852
+ }
1853
+ const toolConfig = typeof dataTool === "string" ? {
1854
+ name: dataTool
1855
+ } : dataTool;
1856
+ const [data, setData] = useState({
1857
+ rows: [],
1858
+ total: 0
1859
+ });
1860
+ const [paginationState, setPaginationState] = useState({
1861
+ page: 1,
1862
+ pageSize: defaultPageSize
1863
+ });
1864
+ const [sortState, setSortState] = useState(defaultSort ?? {
1865
+ column: null,
1866
+ direction: "asc"
1867
+ });
1868
+ const { call, loading, error } = useTool(toolConfig.name, {
1869
+ defaultArgs: toolConfig.args,
1870
+ onSuccess: /* @__PURE__ */ __name((result) => {
1871
+ const gridData = transformData ? transformData(result) : result;
1872
+ setData(gridData);
1873
+ onDataLoaded?.(gridData);
1874
+ }, "onSuccess"),
1875
+ onError
1876
+ });
1877
+ const fetchData = useCallback(() => {
1878
+ const args = {};
1879
+ if (pagination) {
1880
+ args.page = paginationState.page;
1881
+ args.pageSize = paginationState.pageSize;
1882
+ args.offset = (paginationState.page - 1) * paginationState.pageSize;
1883
+ args.limit = paginationState.pageSize;
1884
+ }
1885
+ if (sortState.column) {
1886
+ args.sortBy = sortState.column;
1887
+ args.sortDirection = sortState.direction;
1888
+ args.sort = `${sortState.column}:${sortState.direction}`;
1889
+ }
1890
+ call(args);
1891
+ }, [
1892
+ call,
1893
+ pagination,
1894
+ paginationState,
1895
+ sortState
1896
+ ]);
1897
+ const initialFetchDone = React25.useRef(false);
1898
+ const prevStateRef = React25.useRef({
1899
+ pagination: paginationState,
1900
+ sort: sortState
1901
+ });
1902
+ useEffect(() => {
1903
+ if (!initialFetchDone.current) {
1904
+ initialFetchDone.current = true;
1905
+ fetchData();
1906
+ return;
1907
+ }
1908
+ const prevState = prevStateRef.current;
1909
+ const stateChanged = prevState.pagination.page !== paginationState.page || prevState.pagination.pageSize !== paginationState.pageSize || prevState.sort.column !== sortState.column || prevState.sort.direction !== sortState.direction;
1910
+ if (stateChanged) {
1911
+ prevStateRef.current = {
1912
+ pagination: paginationState,
1913
+ sort: sortState
1914
+ };
1915
+ fetchData();
1916
+ }
1917
+ }, [
1918
+ fetchData,
1919
+ paginationState,
1920
+ sortState
1921
+ ]);
1922
+ useEffect(() => {
1923
+ if (refreshInterval && refreshInterval > 0) {
1924
+ const interval = setInterval(fetchData, refreshInterval);
1925
+ return () => clearInterval(interval);
1926
+ }
1927
+ }, [
1928
+ refreshInterval,
1929
+ fetchData
1930
+ ]);
1931
+ const handleSort = useCallback((column) => {
1932
+ setSortState((prev) => ({
1933
+ column,
1934
+ direction: prev.column === column && prev.direction === "asc" ? "desc" : "asc"
1935
+ }));
1936
+ }, []);
1937
+ const handlePageChange = useCallback((page) => {
1938
+ setPaginationState((prev) => ({
1939
+ ...prev,
1940
+ page
1941
+ }));
1942
+ }, []);
1943
+ const handlePageSizeChange = useCallback((pageSize) => {
1944
+ setPaginationState({
1945
+ page: 1,
1946
+ pageSize: parseInt(pageSize, 10)
1947
+ });
1948
+ }, []);
1949
+ const totalPages = Math.ceil(data.total / paginationState.pageSize);
1950
+ const canPreviousPage = paginationState.page > 1;
1951
+ const canNextPage = paginationState.page < totalPages;
1952
+ const getSortIcon = /* @__PURE__ */ __name((column) => {
1953
+ if (sortState.column !== column) {
1954
+ return /* @__PURE__ */ React25.createElement(ArrowUpDown, {
1955
+ className: "h-4 w-4"
1956
+ });
1957
+ }
1958
+ return sortState.direction === "asc" ? /* @__PURE__ */ React25.createElement(ArrowUp, {
1959
+ className: "h-4 w-4"
1960
+ }) : /* @__PURE__ */ React25.createElement(ArrowDown, {
1961
+ className: "h-4 w-4"
1962
+ });
1963
+ }, "getSortIcon");
1964
+ const renderLoading = /* @__PURE__ */ __name(() => {
1965
+ if (loadingContent) return loadingContent;
1966
+ return /* @__PURE__ */ React25.createElement("div", {
1967
+ className: "space-y-2"
1968
+ }, Array.from({
1969
+ length: 5
1970
+ }).map((_, i) => /* @__PURE__ */ React25.createElement(Skeleton, {
1971
+ key: i,
1972
+ className: "h-12 w-full"
1973
+ })));
1974
+ }, "renderLoading");
1975
+ const renderEmpty = /* @__PURE__ */ __name(() => {
1976
+ if (emptyContent) return emptyContent;
1977
+ return /* @__PURE__ */ React25.createElement("div", {
1978
+ className: "flex flex-col items-center justify-center py-12 text-muted-foreground"
1979
+ }, /* @__PURE__ */ React25.createElement("p", {
1980
+ className: "text-lg"
1981
+ }, "No data found"), /* @__PURE__ */ React25.createElement(Button, {
1982
+ variant: "ghost",
1983
+ size: "sm",
1984
+ onClick: fetchData,
1985
+ className: "mt-2"
1986
+ }, /* @__PURE__ */ React25.createElement(RefreshCw, {
1987
+ className: "h-4 w-4 mr-2"
1988
+ }), "Refresh"));
1989
+ }, "renderEmpty");
1990
+ return /* @__PURE__ */ React25.createElement("div", {
1991
+ className: cn("space-y-4", className)
1992
+ }, showRefresh && /* @__PURE__ */ React25.createElement("div", {
1993
+ className: "flex items-center justify-end gap-2"
1994
+ }, /* @__PURE__ */ React25.createElement(Button, {
1995
+ variant: "outline",
1996
+ size: "sm",
1997
+ onClick: fetchData,
1998
+ disabled: loading
1999
+ }, loading ? /* @__PURE__ */ React25.createElement(Loader2, {
2000
+ className: "h-4 w-4 animate-spin"
2001
+ }) : /* @__PURE__ */ React25.createElement(RefreshCw, {
2002
+ className: "h-4 w-4"
2003
+ }), /* @__PURE__ */ React25.createElement("span", {
2004
+ className: "ml-2"
2005
+ }, "Refresh"))), /* @__PURE__ */ React25.createElement("div", {
2006
+ className: "rounded-md border"
2007
+ }, loading && data.rows.length === 0 ? /* @__PURE__ */ React25.createElement("div", {
2008
+ className: "p-4"
2009
+ }, renderLoading()) : data.rows.length === 0 ? renderEmpty() : /* @__PURE__ */ React25.createElement(Table, null, /* @__PURE__ */ React25.createElement(TableHeader, null, /* @__PURE__ */ React25.createElement(TableRow, null, columns.map((column) => /* @__PURE__ */ React25.createElement(TableHead, {
2010
+ key: column.key,
2011
+ style: {
2012
+ width: column.width
2013
+ },
2014
+ className: cn(column.align === "center" && "text-center", column.align === "right" && "text-right", column.hideMobile && "hidden md:table-cell")
2015
+ }, column.sortable ? /* @__PURE__ */ React25.createElement(Button, {
2016
+ variant: "ghost",
2017
+ size: "sm",
2018
+ onClick: /* @__PURE__ */ __name(() => handleSort(column.key), "onClick"),
2019
+ className: "-ml-3"
2020
+ }, column.header, getSortIcon(column.key)) : column.header)), rowActions.length > 0 && /* @__PURE__ */ React25.createElement(TableHead, {
2021
+ className: "w-[100px]"
2022
+ }, "Actions"))), /* @__PURE__ */ React25.createElement(TableBody, null, data.rows.map((row, index) => {
2023
+ const key = getRowKey?.(row, index) ?? String(index);
2024
+ return /* @__PURE__ */ React25.createElement(TableRow, {
2025
+ key,
2026
+ onClick: /* @__PURE__ */ __name(() => onRowClick?.(row, index), "onClick"),
2027
+ className: onRowClick ? "cursor-pointer" : void 0
2028
+ }, columns.map((column) => {
2029
+ const value = getNestedValue(row, column.key);
2030
+ return /* @__PURE__ */ React25.createElement(TableCell, {
2031
+ key: column.key,
2032
+ className: cn(column.align === "center" && "text-center", column.align === "right" && "text-right", column.hideMobile && "hidden md:table-cell")
2033
+ }, column.render ? column.render(value, row, index) : String(value ?? ""));
2034
+ }), rowActions.length > 0 && /* @__PURE__ */ React25.createElement(TableCell, null, /* @__PURE__ */ React25.createElement("div", {
2035
+ className: "flex items-center gap-1"
2036
+ }, rowActions.filter((action) => !action.hidden?.(row)).map((action, actionIndex) => /* @__PURE__ */ React25.createElement(RowActionButton, {
2037
+ key: actionIndex,
2038
+ action,
2039
+ row,
2040
+ onRefresh: fetchData
2041
+ })))));
2042
+ })))), pagination && data.total > 0 && /* @__PURE__ */ React25.createElement("div", {
2043
+ className: "flex items-center justify-between"
2044
+ }, /* @__PURE__ */ React25.createElement("div", {
2045
+ className: "text-sm text-muted-foreground"
2046
+ }, "Showing ", (paginationState.page - 1) * paginationState.pageSize + 1, " to", " ", Math.min(paginationState.page * paginationState.pageSize, data.total), " of", " ", data.total, " results"), /* @__PURE__ */ React25.createElement("div", {
2047
+ className: "flex items-center gap-4"
2048
+ }, /* @__PURE__ */ React25.createElement("div", {
2049
+ className: "flex items-center gap-2"
2050
+ }, /* @__PURE__ */ React25.createElement("span", {
2051
+ className: "text-sm text-muted-foreground"
2052
+ }, "Rows per page"), /* @__PURE__ */ React25.createElement(Select, {
2053
+ value: String(paginationState.pageSize),
2054
+ onValueChange: handlePageSizeChange
2055
+ }, /* @__PURE__ */ React25.createElement(SelectTrigger, {
2056
+ className: "w-[70px]"
2057
+ }, /* @__PURE__ */ React25.createElement(SelectValue, null)), /* @__PURE__ */ React25.createElement(SelectContent, null, pageSizes.map((size) => /* @__PURE__ */ React25.createElement(SelectItem, {
2058
+ key: size,
2059
+ value: String(size)
2060
+ }, size))))), /* @__PURE__ */ React25.createElement("div", {
2061
+ className: "flex items-center gap-2"
2062
+ }, /* @__PURE__ */ React25.createElement(Button, {
2063
+ variant: "outline",
2064
+ size: "sm",
2065
+ onClick: /* @__PURE__ */ __name(() => handlePageChange(paginationState.page - 1), "onClick"),
2066
+ disabled: !canPreviousPage || loading
2067
+ }, /* @__PURE__ */ React25.createElement(ChevronLeft, {
2068
+ className: "h-4 w-4"
2069
+ })), /* @__PURE__ */ React25.createElement("span", {
2070
+ className: "text-sm"
2071
+ }, "Page ", paginationState.page, " of ", totalPages), /* @__PURE__ */ React25.createElement(Button, {
2072
+ variant: "outline",
2073
+ size: "sm",
2074
+ onClick: /* @__PURE__ */ __name(() => handlePageChange(paginationState.page + 1), "onClick"),
2075
+ disabled: !canNextPage || loading
2076
+ }, /* @__PURE__ */ React25.createElement(ChevronRight, {
2077
+ className: "h-4 w-4"
2078
+ }))))));
2079
+ }
2080
+ __name(ToolDataGrid, "ToolDataGrid");
2081
+ function RowActionButton({ action, row, onRefresh }) {
2082
+ if (!action.tool) {
2083
+ throw new Error("ToolDataGrid: rowAction.tool is required");
2084
+ }
2085
+ const toolConfig = typeof action.tool === "string" ? {
2086
+ name: action.tool
2087
+ } : action.tool;
2088
+ const args = action.getArgs?.(row) ?? {
2089
+ id: row.id
2090
+ };
2091
+ const { call, loading } = useTool(toolConfig.name, {
2092
+ onSuccess: /* @__PURE__ */ __name((result) => {
2093
+ action.onSuccess?.(result, row);
2094
+ toast.success("Action completed");
2095
+ onRefresh();
2096
+ }, "onSuccess"),
2097
+ onError: /* @__PURE__ */ __name((error) => {
2098
+ toast.error(error.message);
2099
+ }, "onError")
2100
+ });
2101
+ const handleClick = useCallback((e) => {
2102
+ e.stopPropagation();
2103
+ call(args);
2104
+ }, [
2105
+ call,
2106
+ args
2107
+ ]);
2108
+ return /* @__PURE__ */ React25.createElement(Button, {
2109
+ variant: action.variant ?? "ghost",
2110
+ size: "sm",
2111
+ onClick: handleClick,
2112
+ disabled: loading
2113
+ }, loading ? /* @__PURE__ */ React25.createElement(Loader2, {
2114
+ className: "h-3 w-3 animate-spin"
2115
+ }) : /* @__PURE__ */ React25.createElement(React25.Fragment, null, action.icon, /* @__PURE__ */ React25.createElement("span", {
2116
+ className: action.icon ? "ml-1" : ""
2117
+ }, action.label)));
2118
+ }
2119
+ __name(RowActionButton, "RowActionButton");
2120
+ var Button2 = /* @__PURE__ */ forwardRef(({ className, variant = "primary", size = "md", loading = false, disabled, asChild = false, leftIcon, rightIcon, children, ...props }, ref) => {
2121
+ const Comp = asChild ? Slot : "button";
2122
+ return /* @__PURE__ */ React25__default.createElement(Comp, {
2123
+ ref,
2124
+ className: clsx("lui-button", `lui-button--${variant}`, `lui-button--${size}`, loading && "lui-button--loading", className),
2125
+ disabled: disabled || loading,
2126
+ ...props
2127
+ }, loading && /* @__PURE__ */ React25__default.createElement("span", {
2128
+ className: "lui-button__spinner",
2129
+ "aria-hidden": "true"
2130
+ }, /* @__PURE__ */ React25__default.createElement("svg", {
2131
+ viewBox: "0 0 24 24",
2132
+ fill: "none",
2133
+ className: "lui-spinner-icon"
2134
+ }, /* @__PURE__ */ React25__default.createElement("circle", {
2135
+ cx: "12",
2136
+ cy: "12",
2137
+ r: "10",
2138
+ stroke: "currentColor",
2139
+ strokeWidth: "3",
2140
+ strokeLinecap: "round",
2141
+ strokeDasharray: "32",
2142
+ strokeDashoffset: "12"
2143
+ }))), leftIcon && !loading && /* @__PURE__ */ React25__default.createElement("span", {
2144
+ className: "lui-button__icon"
2145
+ }, leftIcon), /* @__PURE__ */ React25__default.createElement("span", {
2146
+ className: "lui-button__content"
2147
+ }, children), rightIcon && /* @__PURE__ */ React25__default.createElement("span", {
2148
+ className: "lui-button__icon"
2149
+ }, rightIcon));
2150
+ });
2151
+ Button2.displayName = "Button";
2152
+
2153
+ // src/mcp/ActionButton.tsx
2154
+ function ActionButton({ toolName, toolArgs = {}, onToolSuccess, onToolError, showResult = false, renderResult, children, ...buttonProps }) {
2155
+ const { call, loading, result, error } = useTool(toolName);
2156
+ const [hasResult, setHasResult] = useState(false);
2157
+ const handleClick = /* @__PURE__ */ __name(async () => {
2158
+ try {
2159
+ const res = await call(toolArgs);
2160
+ setHasResult(true);
2161
+ onToolSuccess?.(res);
2162
+ } catch (err) {
2163
+ onToolError?.(err instanceof Error ? err : new Error(String(err)));
2164
+ }
2165
+ }, "handleClick");
2166
+ return /* @__PURE__ */ React25__default.createElement("div", {
2167
+ className: "lui-action-button-wrapper"
2168
+ }, /* @__PURE__ */ React25__default.createElement(Button2, {
2169
+ ...buttonProps,
2170
+ loading,
2171
+ onClick: handleClick
2172
+ }, children), showResult && hasResult && result !== null && /* @__PURE__ */ React25__default.createElement("div", {
2173
+ className: "lui-action-button-result"
2174
+ }, renderResult ? renderResult(result) : /* @__PURE__ */ React25__default.createElement("pre", null, JSON.stringify(result, null, 2))), error && /* @__PURE__ */ React25__default.createElement("div", {
2175
+ className: "lui-action-button-error"
2176
+ }, error.message));
2177
+ }
2178
+ __name(ActionButton, "ActionButton");
2179
+ function DefaultLoading2() {
2180
+ return /* @__PURE__ */ React25.createElement("div", {
2181
+ className: "flex items-center justify-center p-8"
2182
+ }, /* @__PURE__ */ React25.createElement(Loader2, {
2183
+ className: "h-6 w-6 animate-spin text-muted-foreground"
2184
+ }));
2185
+ }
2186
+ __name(DefaultLoading2, "DefaultLoading");
2187
+ function DefaultDisconnected() {
2188
+ return /* @__PURE__ */ React25.createElement(Alert, null, /* @__PURE__ */ React25.createElement(WifiOff, {
2189
+ className: "h-4 w-4"
2190
+ }), /* @__PURE__ */ React25.createElement(AlertDescription, null, "Waiting for connection to MCP host..."));
2191
+ }
2192
+ __name(DefaultDisconnected, "DefaultDisconnected");
2193
+ function DefaultError2({ error }) {
2194
+ return /* @__PURE__ */ React25.createElement(Alert, {
2195
+ variant: "destructive"
2196
+ }, /* @__PURE__ */ React25.createElement(AlertCircle, {
2197
+ className: "h-4 w-4"
2198
+ }), /* @__PURE__ */ React25.createElement(AlertDescription, null, "Connection error: ", error.message));
2199
+ }
2200
+ __name(DefaultError2, "DefaultError");
2201
+ function RequireConnection({ loading: loadingContent, error: errorContent, disconnected: disconnectedContent, children, className }) {
2202
+ const { isConnected, error, app } = useMcpApp();
2203
+ if (!app && !error && !isConnected) {
2204
+ if (loadingContent) {
2205
+ return /* @__PURE__ */ React25.createElement("div", {
2206
+ className
2207
+ }, loadingContent);
2208
+ }
2209
+ return /* @__PURE__ */ React25.createElement("div", {
2210
+ className
2211
+ }, /* @__PURE__ */ React25.createElement(DefaultLoading2, null));
2212
+ }
2213
+ if (error) {
2214
+ if (errorContent) {
2215
+ if (typeof errorContent === "function") {
2216
+ return /* @__PURE__ */ React25.createElement("div", {
2217
+ className
2218
+ }, errorContent(error));
2219
+ }
2220
+ return /* @__PURE__ */ React25.createElement("div", {
2221
+ className
2222
+ }, errorContent);
2223
+ }
2224
+ return /* @__PURE__ */ React25.createElement("div", {
2225
+ className
2226
+ }, /* @__PURE__ */ React25.createElement(DefaultError2, {
2227
+ error
2228
+ }));
2229
+ }
2230
+ if (!isConnected) {
2231
+ if (disconnectedContent) {
2232
+ return /* @__PURE__ */ React25.createElement("div", {
2233
+ className
2234
+ }, disconnectedContent);
2235
+ }
2236
+ if (loadingContent) {
2237
+ return /* @__PURE__ */ React25.createElement("div", {
2238
+ className
2239
+ }, loadingContent);
2240
+ }
2241
+ return /* @__PURE__ */ React25.createElement("div", {
2242
+ className
2243
+ }, /* @__PURE__ */ React25.createElement(DefaultDisconnected, null));
2244
+ }
2245
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, children);
2246
+ }
2247
+ __name(RequireConnection, "RequireConnection");
2248
+ function DefaultFallback({ error, onRetry }) {
2249
+ return /* @__PURE__ */ React25.createElement(Alert, {
2250
+ variant: "destructive"
2251
+ }, /* @__PURE__ */ React25.createElement(AlertCircle, {
2252
+ className: "h-4 w-4"
2253
+ }), /* @__PURE__ */ React25.createElement(AlertTitle, null, "Something went wrong"), /* @__PURE__ */ React25.createElement(AlertDescription, {
2254
+ className: "flex flex-col gap-3"
2255
+ }, /* @__PURE__ */ React25.createElement("p", {
2256
+ className: "text-sm"
2257
+ }, error.message), /* @__PURE__ */ React25.createElement(Button, {
2258
+ variant: "outline",
2259
+ size: "sm",
2260
+ onClick: onRetry,
2261
+ className: "w-fit"
2262
+ }, /* @__PURE__ */ React25.createElement(RefreshCw, {
2263
+ className: "h-4 w-4 mr-2"
2264
+ }), "Try Again")));
2265
+ }
2266
+ __name(DefaultFallback, "DefaultFallback");
2267
+ var ToolErrorBoundary = class extends Component {
2268
+ static {
2269
+ __name(this, "ToolErrorBoundary");
2270
+ }
2271
+ constructor(props) {
2272
+ super(props);
2273
+ this.state = {
2274
+ hasError: false,
2275
+ error: null
2276
+ };
2277
+ }
2278
+ static getDerivedStateFromError(error) {
2279
+ return {
2280
+ hasError: true,
2281
+ error
2282
+ };
2283
+ }
2284
+ componentDidCatch(error, errorInfo) {
2285
+ this.props.onError?.(error, errorInfo);
2286
+ }
2287
+ componentDidUpdate(prevProps) {
2288
+ if (this.state.hasError && this.props.resetKeys && prevProps.resetKeys && this.props.resetKeys.some((key, index) => key !== prevProps.resetKeys?.[index])) {
2289
+ this.reset();
2290
+ }
2291
+ }
2292
+ reset = /* @__PURE__ */ __name(() => {
2293
+ this.setState({
2294
+ hasError: false,
2295
+ error: null
2296
+ });
2297
+ }, "reset");
2298
+ render() {
2299
+ const { hasError, error } = this.state;
2300
+ const { fallback, children } = this.props;
2301
+ if (hasError && error) {
2302
+ if (fallback) {
2303
+ if (typeof fallback === "function") {
2304
+ return fallback(error, this.reset);
2305
+ }
2306
+ return fallback;
2307
+ }
2308
+ return /* @__PURE__ */ React25.createElement(DefaultFallback, {
2309
+ error,
2310
+ onRetry: this.reset
2311
+ });
2312
+ }
2313
+ return children;
2314
+ }
2315
+ };
2316
+ function useMessage() {
2317
+ const { sendMessage: appSendMessage, isConnected } = useMcpApp();
2318
+ const [sending, setSending] = useState(false);
2319
+ const [error, setError] = useState(null);
2320
+ const send = useCallback(async (text) => {
2321
+ if (!isConnected) {
2322
+ console.warn("[useMessage] Not connected to host");
2323
+ return;
2324
+ }
2325
+ setSending(true);
2326
+ setError(null);
2327
+ try {
2328
+ await appSendMessage(text);
2329
+ } catch (err) {
2330
+ const error2 = err instanceof Error ? err : new Error(String(err));
2331
+ setError(error2);
2332
+ throw error2;
2333
+ } finally {
2334
+ setSending(false);
2335
+ }
2336
+ }, [
2337
+ appSendMessage,
2338
+ isConnected
2339
+ ]);
2340
+ const sendContent = useCallback(async (content) => {
2341
+ if (!isConnected) {
2342
+ console.warn("[useMessage] Not connected to host");
2343
+ return;
2344
+ }
2345
+ setSending(true);
2346
+ setError(null);
2347
+ try {
2348
+ const textContent = content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
2349
+ await appSendMessage(textContent);
2350
+ } catch (err) {
2351
+ const error2 = err instanceof Error ? err : new Error(String(err));
2352
+ setError(error2);
2353
+ throw error2;
2354
+ } finally {
2355
+ setSending(false);
2356
+ }
2357
+ }, [
2358
+ appSendMessage,
2359
+ isConnected
2360
+ ]);
2361
+ const requestTool = useCallback(async (toolName, args) => {
2362
+ let message = `Please call the "${toolName}" tool`;
2363
+ if (args && Object.keys(args).length > 0) {
2364
+ message += ` with arguments: ${JSON.stringify(args)}`;
2365
+ }
2366
+ await send(message);
2367
+ }, [
2368
+ send
2369
+ ]);
2370
+ return {
2371
+ send,
2372
+ sendContent,
2373
+ requestTool,
2374
+ sending,
2375
+ error
2376
+ };
2377
+ }
2378
+ __name(useMessage, "useMessage");
2379
+
2380
+ // src/mcp/useHostContext.ts
2381
+ function useHostContext() {
2382
+ const { hostContext } = useMcpApp();
2383
+ return {
2384
+ theme: hostContext.theme ?? "light",
2385
+ displayMode: hostContext.displayMode ?? "inline",
2386
+ availableDisplayModes: hostContext.availableDisplayModes ?? [],
2387
+ viewport: hostContext.viewport ?? null,
2388
+ locale: hostContext.locale ?? null,
2389
+ timeZone: hostContext.timeZone ?? null,
2390
+ platform: hostContext.platform ?? null,
2391
+ userAgent: hostContext.userAgent ?? null,
2392
+ deviceCapabilities: hostContext.deviceCapabilities ?? null,
2393
+ safeAreaInsets: hostContext.safeAreaInsets ?? null,
2394
+ styles: hostContext.styles ?? null,
2395
+ rawContext: hostContext
2396
+ };
2397
+ }
2398
+ __name(useHostContext, "useHostContext");
2399
+
2400
+ // src/mcp/useToolResult.ts
2401
+ function useToolResult() {
2402
+ const { toolResult } = useMcpApp();
2403
+ let result = null;
2404
+ let textContent = null;
2405
+ if (toolResult) {
2406
+ if ("structuredContent" in toolResult && toolResult.structuredContent) {
2407
+ result = toolResult.structuredContent;
2408
+ }
2409
+ if (!result && toolResult.content) {
2410
+ const textItem = toolResult.content.find((c) => c.type === "text");
2411
+ if (textItem) {
2412
+ textContent = textItem.text;
2413
+ try {
2414
+ result = JSON.parse(textItem.text);
2415
+ } catch {
2416
+ }
2417
+ }
2418
+ }
2419
+ }
2420
+ return {
2421
+ result,
2422
+ rawResult: toolResult,
2423
+ hasResult: toolResult !== null,
2424
+ textContent
2425
+ };
2426
+ }
2427
+ __name(useToolResult, "useToolResult");
2428
+
2429
+ // src/mcp/useToolInput.ts
2430
+ function useToolInput() {
2431
+ const { toolInput } = useMcpApp();
2432
+ return {
2433
+ input: toolInput,
2434
+ hasInput: toolInput !== null
2435
+ };
2436
+ }
2437
+ __name(useToolInput, "useToolInput");
2438
+
2439
+ // src/mcp/useToolInputPartial.ts
2440
+ function useToolInputPartial() {
2441
+ const { toolInputPartial } = useMcpApp();
2442
+ return {
2443
+ partialArgs: toolInputPartial,
2444
+ isStreaming: toolInputPartial !== null
2445
+ };
2446
+ }
2447
+ __name(useToolInputPartial, "useToolInputPartial");
2448
+ function useToolSubscription(toolName, options = {}) {
2449
+ const { interval = 1e4, enabled = true, args = {} } = options;
2450
+ const toolHook = useTool(toolName);
2451
+ const intervalRef = useRef(null);
2452
+ const [isPolling, setIsPolling] = useState(false);
2453
+ const stop = useCallback(() => {
2454
+ if (intervalRef.current) {
2455
+ clearInterval(intervalRef.current);
2456
+ intervalRef.current = null;
2457
+ }
2458
+ setIsPolling(false);
2459
+ }, []);
2460
+ const start = useCallback(() => {
2461
+ stop();
2462
+ setIsPolling(true);
2463
+ toolHook.call(args).catch(() => {
2464
+ });
2465
+ intervalRef.current = setInterval(() => {
2466
+ toolHook.call(args).catch(() => {
2467
+ });
2468
+ }, interval);
2469
+ }, [
2470
+ toolHook.call,
2471
+ args,
2472
+ interval,
2473
+ stop
2474
+ ]);
2475
+ const refresh = useCallback(async () => {
2476
+ return toolHook.call(args);
2477
+ }, [
2478
+ toolHook.call,
2479
+ args
2480
+ ]);
2481
+ useEffect(() => {
2482
+ if (enabled) {
2483
+ start();
2484
+ }
2485
+ return () => stop();
2486
+ }, [
2487
+ enabled,
2488
+ start,
2489
+ stop
2490
+ ]);
2491
+ return {
2492
+ result: toolHook.result,
2493
+ loading: toolHook.loading,
2494
+ error: toolHook.error,
2495
+ start,
2496
+ stop,
2497
+ isPolling,
2498
+ refresh
2499
+ };
2500
+ }
2501
+ __name(useToolSubscription, "useToolSubscription");
2502
+
2503
+ // src/types/mcp-types.ts
2504
+ function normalizeToolBinding(tool) {
2505
+ if (typeof tool === "string") {
2506
+ return {
2507
+ name: tool
2508
+ };
2509
+ }
2510
+ return tool;
2511
+ }
2512
+ __name(normalizeToolBinding, "normalizeToolBinding");
2513
+ var DEFAULT_RESULT_CONFIG = {
2514
+ display: "none",
2515
+ autoDismiss: 5e3
2516
+ };
2517
+ var INITIAL_TOOL_STATE = {
2518
+ state: "idle",
2519
+ loading: false,
2520
+ result: null,
2521
+ error: null,
2522
+ hasResult: false
2523
+ };
2524
+ function CardTitle({ className, ...props }) {
2525
+ return /* @__PURE__ */ React25.createElement("div", {
2526
+ "data-slot": "card-title",
2527
+ className: cn("leading-none font-semibold", className),
2528
+ ...props
2529
+ });
2530
+ }
2531
+ __name(CardTitle, "CardTitle");
2532
+ function CardDescription({ className, ...props }) {
2533
+ return /* @__PURE__ */ React25.createElement("div", {
2534
+ "data-slot": "card-description",
2535
+ className: cn("text-muted-foreground text-sm", className),
2536
+ ...props
2537
+ });
2538
+ }
2539
+ __name(CardDescription, "CardDescription");
2540
+ var Form = FormProvider;
2541
+ var FormFieldContext = /* @__PURE__ */ React25.createContext({});
2542
+ var FormField = /* @__PURE__ */ __name(({ ...props }) => {
2543
+ return /* @__PURE__ */ React25.createElement(FormFieldContext.Provider, {
2544
+ value: {
2545
+ name: props.name
2546
+ }
2547
+ }, /* @__PURE__ */ React25.createElement(Controller, props));
2548
+ }, "FormField");
2549
+ var useFormField = /* @__PURE__ */ __name(() => {
2550
+ const fieldContext = React25.useContext(FormFieldContext);
2551
+ const itemContext = React25.useContext(FormItemContext);
2552
+ const { getFieldState } = useFormContext();
2553
+ const formState = useFormState({
2554
+ name: fieldContext.name
2555
+ });
2556
+ const fieldState = getFieldState(fieldContext.name, formState);
2557
+ if (!fieldContext) {
2558
+ throw new Error("useFormField should be used within <FormField>");
2559
+ }
2560
+ const { id } = itemContext;
2561
+ return {
2562
+ id,
2563
+ name: fieldContext.name,
2564
+ formItemId: `${id}-form-item`,
2565
+ formDescriptionId: `${id}-form-item-description`,
2566
+ formMessageId: `${id}-form-item-message`,
2567
+ ...fieldState
2568
+ };
2569
+ }, "useFormField");
2570
+ var FormItemContext = /* @__PURE__ */ React25.createContext({});
2571
+ function FormItem({ className, ...props }) {
2572
+ const id = React25.useId();
2573
+ return /* @__PURE__ */ React25.createElement(FormItemContext.Provider, {
2574
+ value: {
2575
+ id
2576
+ }
2577
+ }, /* @__PURE__ */ React25.createElement("div", {
2578
+ "data-slot": "form-item",
2579
+ className: cn("grid gap-2", className),
2580
+ ...props
2581
+ }));
2582
+ }
2583
+ __name(FormItem, "FormItem");
2584
+ function FormLabel({ className, ...props }) {
2585
+ const { error, formItemId } = useFormField();
2586
+ return /* @__PURE__ */ React25.createElement(Label2, {
2587
+ "data-slot": "form-label",
2588
+ "data-error": !!error,
2589
+ className: cn("data-[error=true]:text-destructive", className),
2590
+ htmlFor: formItemId,
2591
+ ...props
2592
+ });
2593
+ }
2594
+ __name(FormLabel, "FormLabel");
2595
+ function FormControl({ ...props }) {
2596
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
2597
+ return /* @__PURE__ */ React25.createElement(Slot, {
2598
+ "data-slot": "form-control",
2599
+ id: formItemId,
2600
+ "aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`,
2601
+ "aria-invalid": !!error,
2602
+ ...props
2603
+ });
2604
+ }
2605
+ __name(FormControl, "FormControl");
2606
+ function FormDescription({ className, ...props }) {
2607
+ const { formDescriptionId } = useFormField();
2608
+ return /* @__PURE__ */ React25.createElement("p", {
2609
+ "data-slot": "form-description",
2610
+ id: formDescriptionId,
2611
+ className: cn("text-muted-foreground text-sm", className),
2612
+ ...props
2613
+ });
2614
+ }
2615
+ __name(FormDescription, "FormDescription");
2616
+ function FormMessage({ className, ...props }) {
2617
+ const { error, formMessageId } = useFormField();
2618
+ const body = error ? String(error?.message ?? "") : props.children;
2619
+ if (!body) {
2620
+ return null;
2621
+ }
2622
+ return /* @__PURE__ */ React25.createElement("p", {
2623
+ "data-slot": "form-message",
2624
+ id: formMessageId,
2625
+ className: cn("text-destructive text-sm", className),
2626
+ ...props
2627
+ }, body);
2628
+ }
2629
+ __name(FormMessage, "FormMessage");
2630
+ var badgeVariants = cva("inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", {
2631
+ variants: {
2632
+ variant: {
2633
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
2634
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
2635
+ destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
2636
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
2637
+ }
2638
+ },
2639
+ defaultVariants: {
2640
+ variant: "default"
2641
+ }
2642
+ });
2643
+ function Badge({ className, variant, asChild = false, ...props }) {
2644
+ const Comp = asChild ? Slot : "span";
2645
+ return /* @__PURE__ */ React25.createElement(Comp, {
2646
+ "data-slot": "badge",
2647
+ className: cn(badgeVariants({
2648
+ variant
2649
+ }), className),
2650
+ ...props
2651
+ });
2652
+ }
2653
+ __name(Badge, "Badge");
2654
+ function TabsList({ className, ...props }) {
2655
+ return /* @__PURE__ */ React25.createElement(TabsPrimitive2.List, {
2656
+ "data-slot": "tabs-list",
2657
+ className: cn("bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]", className),
2658
+ ...props
2659
+ });
2660
+ }
2661
+ __name(TabsList, "TabsList");
2662
+ function TabsTrigger({ className, ...props }) {
2663
+ return /* @__PURE__ */ React25.createElement(TabsPrimitive2.Trigger, {
2664
+ "data-slot": "tabs-trigger",
2665
+ className: cn("data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
2666
+ ...props
2667
+ });
2668
+ }
2669
+ __name(TabsTrigger, "TabsTrigger");
2670
+ function TabsContent({ className, ...props }) {
2671
+ return /* @__PURE__ */ React25.createElement(TabsPrimitive2.Content, {
2672
+ "data-slot": "tabs-content",
2673
+ className: cn("flex-1 outline-none", className),
2674
+ ...props
2675
+ });
2676
+ }
2677
+ __name(TabsContent, "TabsContent");
2678
+ function Separator2({ className, orientation = "horizontal", decorative = true, ...props }) {
2679
+ return /* @__PURE__ */ React25.createElement(SeparatorPrimitive.Root, {
2680
+ "data-slot": "separator",
2681
+ decorative,
2682
+ orientation,
2683
+ className: cn("bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", className),
2684
+ ...props
2685
+ });
2686
+ }
2687
+ __name(Separator2, "Separator");
2688
+ function ScrollArea({ className, children, ...props }) {
2689
+ return /* @__PURE__ */ React25.createElement(ScrollAreaPrimitive.Root, {
2690
+ "data-slot": "scroll-area",
2691
+ className: cn("relative", className),
2692
+ ...props
2693
+ }, /* @__PURE__ */ React25.createElement(ScrollAreaPrimitive.Viewport, {
2694
+ "data-slot": "scroll-area-viewport",
2695
+ className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
2696
+ }, children), /* @__PURE__ */ React25.createElement(ScrollBar, null), /* @__PURE__ */ React25.createElement(ScrollAreaPrimitive.Corner, null));
2697
+ }
2698
+ __name(ScrollArea, "ScrollArea");
2699
+ function ScrollBar({ className, orientation = "vertical", ...props }) {
2700
+ return /* @__PURE__ */ React25.createElement(ScrollAreaPrimitive.ScrollAreaScrollbar, {
2701
+ "data-slot": "scroll-area-scrollbar",
2702
+ orientation,
2703
+ className: cn("flex touch-none p-px transition-colors select-none", orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent", orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent", className),
2704
+ ...props
2705
+ }, /* @__PURE__ */ React25.createElement(ScrollAreaPrimitive.ScrollAreaThumb, {
2706
+ "data-slot": "scroll-area-thumb",
2707
+ className: "bg-border relative flex-1 rounded-full"
2708
+ }));
2709
+ }
2710
+ __name(ScrollBar, "ScrollBar");
2711
+ function DropdownMenu({ ...props }) {
2712
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Root, {
2713
+ "data-slot": "dropdown-menu",
2714
+ ...props
2715
+ });
2716
+ }
2717
+ __name(DropdownMenu, "DropdownMenu");
2718
+ function DropdownMenuPortal({ ...props }) {
2719
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Portal, {
2720
+ "data-slot": "dropdown-menu-portal",
2721
+ ...props
2722
+ });
2723
+ }
2724
+ __name(DropdownMenuPortal, "DropdownMenuPortal");
2725
+ function DropdownMenuTrigger({ ...props }) {
2726
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Trigger, {
2727
+ "data-slot": "dropdown-menu-trigger",
2728
+ ...props
2729
+ });
252
2730
  }
253
- __name(useTool, "useTool");
254
-
255
- // src/mcp/useToolResult.ts
256
- function useToolResult() {
257
- const { toolResult } = useMcpApp();
258
- let result = null;
259
- let textContent = null;
260
- if (toolResult) {
261
- if ("structuredContent" in toolResult && toolResult.structuredContent) {
262
- result = toolResult.structuredContent;
263
- }
264
- if (!result && toolResult.content) {
265
- const textItem = toolResult.content.find((c) => c.type === "text");
266
- if (textItem) {
267
- textContent = textItem.text;
268
- try {
269
- result = JSON.parse(textItem.text);
270
- } catch {
271
- }
272
- }
273
- }
274
- }
275
- return {
276
- result,
277
- rawResult: toolResult,
278
- hasResult: toolResult !== null,
279
- textContent
280
- };
2731
+ __name(DropdownMenuTrigger, "DropdownMenuTrigger");
2732
+ function DropdownMenuContent({ className, sideOffset = 4, ...props }) {
2733
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Portal, null, /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Content, {
2734
+ "data-slot": "dropdown-menu-content",
2735
+ sideOffset,
2736
+ className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", className),
2737
+ ...props
2738
+ }));
281
2739
  }
282
- __name(useToolResult, "useToolResult");
283
-
284
- // src/mcp/useToolInput.ts
285
- function useToolInput() {
286
- const { toolInput } = useMcpApp();
287
- return {
288
- input: toolInput,
289
- hasInput: toolInput !== null
290
- };
2740
+ __name(DropdownMenuContent, "DropdownMenuContent");
2741
+ function DropdownMenuGroup({ ...props }) {
2742
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Group, {
2743
+ "data-slot": "dropdown-menu-group",
2744
+ ...props
2745
+ });
291
2746
  }
292
- __name(useToolInput, "useToolInput");
293
-
294
- // src/mcp/useToolInputPartial.ts
295
- function useToolInputPartial() {
296
- const { toolInputPartial } = useMcpApp();
297
- return {
298
- partialArgs: toolInputPartial,
299
- isStreaming: toolInputPartial !== null
300
- };
2747
+ __name(DropdownMenuGroup, "DropdownMenuGroup");
2748
+ function DropdownMenuItem({ className, inset, variant = "default", ...props }) {
2749
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Item, {
2750
+ "data-slot": "dropdown-menu-item",
2751
+ "data-inset": inset,
2752
+ "data-variant": variant,
2753
+ className: cn("focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
2754
+ ...props
2755
+ });
301
2756
  }
302
- __name(useToolInputPartial, "useToolInputPartial");
303
-
304
- // src/mcp/useHostContext.ts
305
- function useHostContext() {
306
- const { hostContext } = useMcpApp();
307
- return {
308
- theme: hostContext.theme ?? "light",
309
- displayMode: hostContext.displayMode ?? "inline",
310
- viewport: hostContext.viewport ?? null,
311
- locale: hostContext.locale ?? null,
312
- timeZone: hostContext.timeZone ?? null,
313
- platform: hostContext.platform ?? null,
314
- rawContext: hostContext
315
- };
2757
+ __name(DropdownMenuItem, "DropdownMenuItem");
2758
+ function DropdownMenuCheckboxItem({ className, children, checked, ...props }) {
2759
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.CheckboxItem, {
2760
+ "data-slot": "dropdown-menu-checkbox-item",
2761
+ className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
2762
+ checked,
2763
+ ...props
2764
+ }, /* @__PURE__ */ React25.createElement("span", {
2765
+ className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center"
2766
+ }, /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.ItemIndicator, null, /* @__PURE__ */ React25.createElement(CheckIcon, {
2767
+ className: "size-4"
2768
+ }))), children);
316
2769
  }
317
- __name(useHostContext, "useHostContext");
318
- var Button = /* @__PURE__ */ forwardRef(({ className, variant = "primary", size = "md", loading = false, disabled, asChild = false, leftIcon, rightIcon, children, ...props }, ref) => {
319
- const Comp = asChild ? Slot : "button";
320
- return /* @__PURE__ */ React7.createElement(Comp, {
321
- ref,
322
- className: clsx("lui-button", `lui-button--${variant}`, `lui-button--${size}`, loading && "lui-button--loading", className),
323
- disabled: disabled || loading,
2770
+ __name(DropdownMenuCheckboxItem, "DropdownMenuCheckboxItem");
2771
+ function DropdownMenuRadioGroup({ ...props }) {
2772
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.RadioGroup, {
2773
+ "data-slot": "dropdown-menu-radio-group",
324
2774
  ...props
325
- }, loading && /* @__PURE__ */ React7.createElement("span", {
326
- className: "lui-button__spinner",
327
- "aria-hidden": "true"
328
- }, /* @__PURE__ */ React7.createElement("svg", {
329
- viewBox: "0 0 24 24",
330
- fill: "none",
331
- className: "lui-spinner-icon"
332
- }, /* @__PURE__ */ React7.createElement("circle", {
333
- cx: "12",
334
- cy: "12",
335
- r: "10",
336
- stroke: "currentColor",
337
- strokeWidth: "3",
338
- strokeLinecap: "round",
339
- strokeDasharray: "32",
340
- strokeDashoffset: "12"
341
- }))), leftIcon && !loading && /* @__PURE__ */ React7.createElement("span", {
342
- className: "lui-button__icon"
343
- }, leftIcon), /* @__PURE__ */ React7.createElement("span", {
344
- className: "lui-button__content"
345
- }, children), rightIcon && /* @__PURE__ */ React7.createElement("span", {
346
- className: "lui-button__icon"
347
- }, rightIcon));
348
- });
349
- Button.displayName = "Button";
350
-
351
- // src/mcp/ActionButton.tsx
352
- function ActionButton({ toolName, toolArgs = {}, onToolSuccess, onToolError, showResult = false, renderResult, children, ...buttonProps }) {
353
- const { call, loading, result, error } = useTool(toolName);
354
- const [hasResult, setHasResult] = useState(false);
355
- const handleClick = /* @__PURE__ */ __name(async () => {
356
- try {
357
- const res = await call(toolArgs);
358
- setHasResult(true);
359
- onToolSuccess?.(res);
360
- } catch (err) {
361
- onToolError?.(err instanceof Error ? err : new Error(String(err)));
362
- }
363
- }, "handleClick");
364
- return /* @__PURE__ */ React7.createElement("div", {
365
- className: "lui-action-button-wrapper"
366
- }, /* @__PURE__ */ React7.createElement(Button, {
367
- ...buttonProps,
368
- loading,
369
- onClick: handleClick
370
- }, children), showResult && hasResult && result !== null && /* @__PURE__ */ React7.createElement("div", {
371
- className: "lui-action-button-result"
372
- }, renderResult ? renderResult(result) : /* @__PURE__ */ React7.createElement("pre", null, JSON.stringify(result, null, 2))), error && /* @__PURE__ */ React7.createElement("div", {
373
- className: "lui-action-button-error"
374
- }, error.message));
2775
+ });
375
2776
  }
376
- __name(ActionButton, "ActionButton");
377
- var Input = /* @__PURE__ */ forwardRef(({ className, label, helperText, error, size = "md", leftElement, rightElement, fullWidth = false, id, ...props }, ref) => {
378
- const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
379
- const hasError = Boolean(error);
380
- return /* @__PURE__ */ React7.createElement("div", {
381
- className: clsx("lui-input-wrapper", fullWidth && "lui-input-wrapper--full-width", className)
382
- }, label && /* @__PURE__ */ React7.createElement("label", {
383
- htmlFor: inputId,
384
- className: "lui-input-label"
385
- }, label), /* @__PURE__ */ React7.createElement("div", {
386
- className: clsx("lui-input-container", `lui-input-container--${size}`, hasError && "lui-input-container--error", leftElement && "lui-input-container--has-left", rightElement && "lui-input-container--has-right")
387
- }, leftElement && /* @__PURE__ */ React7.createElement("span", {
388
- className: "lui-input-element lui-input-element--left"
389
- }, leftElement), /* @__PURE__ */ React7.createElement("input", {
390
- ref,
391
- id: inputId,
392
- className: "lui-input",
393
- "aria-invalid": hasError,
394
- "aria-describedby": error ? `${inputId}-error` : helperText ? `${inputId}-helper` : void 0,
2777
+ __name(DropdownMenuRadioGroup, "DropdownMenuRadioGroup");
2778
+ function DropdownMenuRadioItem({ className, children, ...props }) {
2779
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.RadioItem, {
2780
+ "data-slot": "dropdown-menu-radio-item",
2781
+ className: cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
2782
+ ...props
2783
+ }, /* @__PURE__ */ React25.createElement("span", {
2784
+ className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center"
2785
+ }, /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.ItemIndicator, null, /* @__PURE__ */ React25.createElement(CircleIcon, {
2786
+ className: "size-2 fill-current"
2787
+ }))), children);
2788
+ }
2789
+ __name(DropdownMenuRadioItem, "DropdownMenuRadioItem");
2790
+ function DropdownMenuLabel({ className, inset, ...props }) {
2791
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Label, {
2792
+ "data-slot": "dropdown-menu-label",
2793
+ "data-inset": inset,
2794
+ className: cn("px-2 py-1.5 text-sm font-medium data-[inset]:pl-8", className),
395
2795
  ...props
396
- }), rightElement && /* @__PURE__ */ React7.createElement("span", {
397
- className: "lui-input-element lui-input-element--right"
398
- }, rightElement)), (error || helperText) && /* @__PURE__ */ React7.createElement("p", {
399
- id: error ? `${inputId}-error` : `${inputId}-helper`,
400
- className: clsx("lui-input-message", error && "lui-input-message--error")
401
- }, error || helperText));
402
- });
403
- Input.displayName = "Input";
404
- function ToolForm({ toolName, fields, submitText = "Submit", onSuccess, onError, showResult = false, className }) {
405
- const { call, loading, result, error } = useTool(toolName);
406
- const [formData, setFormData] = useState(() => {
407
- const initial = {};
408
- fields.forEach((field) => {
409
- if (field.defaultValue !== void 0) {
410
- initial[field.name] = field.defaultValue;
411
- }
412
- });
413
- return initial;
414
2796
  });
415
- const handleSubmit = /* @__PURE__ */ __name(async (e) => {
416
- e.preventDefault();
417
- const args = {};
418
- fields.forEach((field) => {
419
- const value = formData[field.name];
420
- if (field.type === "number" && value !== void 0) {
421
- args[field.name] = Number(value);
422
- } else {
423
- args[field.name] = value;
424
- }
425
- });
426
- try {
427
- const res = await call(args);
428
- onSuccess?.(res);
429
- } catch (err) {
430
- onError?.(err instanceof Error ? err : new Error(String(err)));
431
- }
432
- }, "handleSubmit");
433
- const handleChange = /* @__PURE__ */ __name((name, value) => {
434
- setFormData((prev) => ({
435
- ...prev,
436
- [name]: value
437
- }));
438
- }, "handleChange");
439
- return /* @__PURE__ */ React7.createElement("form", {
440
- className: clsx("lui-tool-form", className),
441
- onSubmit: handleSubmit
442
- }, /* @__PURE__ */ React7.createElement("div", {
443
- className: "lui-tool-form-fields"
444
- }, fields.map((field) => /* @__PURE__ */ React7.createElement("div", {
445
- key: field.name,
446
- className: "lui-tool-form-field"
447
- }, field.type === "textarea" ? /* @__PURE__ */ React7.createElement("div", {
448
- className: "lui-input-wrapper lui-input-wrapper--full-width"
449
- }, /* @__PURE__ */ React7.createElement("label", {
450
- className: "lui-input-label"
451
- }, field.label), /* @__PURE__ */ React7.createElement("textarea", {
452
- className: "lui-tool-form-textarea",
453
- name: field.name,
454
- placeholder: field.placeholder,
455
- required: field.required,
456
- value: formData[field.name] ?? "",
457
- onChange: /* @__PURE__ */ __name((e) => handleChange(field.name, e.target.value), "onChange")
458
- }), field.helperText && /* @__PURE__ */ React7.createElement("p", {
459
- className: "lui-input-message"
460
- }, field.helperText)) : /* @__PURE__ */ React7.createElement(Input, {
461
- fullWidth: true,
462
- label: field.label,
463
- type: field.type ?? "text",
464
- name: field.name,
465
- placeholder: field.placeholder,
466
- required: field.required,
467
- helperText: field.helperText,
468
- value: formData[field.name] ?? "",
469
- onChange: /* @__PURE__ */ __name((e) => handleChange(field.name, e.target.value), "onChange")
470
- })))), /* @__PURE__ */ React7.createElement("div", {
471
- className: "lui-tool-form-actions"
472
- }, /* @__PURE__ */ React7.createElement(Button, {
473
- type: "submit",
474
- loading
475
- }, submitText)), error && /* @__PURE__ */ React7.createElement("div", {
476
- className: "lui-tool-form-error"
477
- }, error.message), showResult && result !== null && /* @__PURE__ */ React7.createElement("div", {
478
- className: "lui-tool-form-result"
479
- }, /* @__PURE__ */ React7.createElement("pre", null, JSON.stringify(result, null, 2))));
480
2797
  }
481
- __name(ToolForm, "ToolForm");
482
- var Card = /* @__PURE__ */ forwardRef(({ className, variant = "default", padding = "md", interactive = false, children, ...props }, ref) => {
483
- return /* @__PURE__ */ React7.createElement("div", {
484
- ref,
485
- className: clsx("lui-card", `lui-card--${variant}`, `lui-card--padding-${padding}`, interactive && "lui-card--interactive", className),
2798
+ __name(DropdownMenuLabel, "DropdownMenuLabel");
2799
+ function DropdownMenuSeparator({ className, ...props }) {
2800
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Separator, {
2801
+ "data-slot": "dropdown-menu-separator",
2802
+ className: cn("bg-border -mx-1 my-1 h-px", className),
486
2803
  ...props
487
- }, children);
488
- });
489
- Card.displayName = "Card";
490
- var CardHeader = /* @__PURE__ */ forwardRef(({ className, title, description, action, children, ...props }, ref) => {
491
- return /* @__PURE__ */ React7.createElement("div", {
492
- ref,
493
- className: clsx("lui-card-header", className),
2804
+ });
2805
+ }
2806
+ __name(DropdownMenuSeparator, "DropdownMenuSeparator");
2807
+ function DropdownMenuShortcut({ className, ...props }) {
2808
+ return /* @__PURE__ */ React25.createElement("span", {
2809
+ "data-slot": "dropdown-menu-shortcut",
2810
+ className: cn("text-muted-foreground ml-auto text-xs tracking-widest", className),
494
2811
  ...props
495
- }, (title || description) && /* @__PURE__ */ React7.createElement("div", {
496
- className: "lui-card-header__text"
497
- }, title && /* @__PURE__ */ React7.createElement("h3", {
498
- className: "lui-card-header__title"
499
- }, title), description && /* @__PURE__ */ React7.createElement("p", {
500
- className: "lui-card-header__description"
501
- }, description)), action && /* @__PURE__ */ React7.createElement("div", {
502
- className: "lui-card-header__action"
503
- }, action), children);
504
- });
505
- CardHeader.displayName = "CardHeader";
506
- var CardContent = /* @__PURE__ */ forwardRef(({ className, children, ...props }, ref) => {
507
- return /* @__PURE__ */ React7.createElement("div", {
508
- ref,
509
- className: clsx("lui-card-content", className),
2812
+ });
2813
+ }
2814
+ __name(DropdownMenuShortcut, "DropdownMenuShortcut");
2815
+ function DropdownMenuSub({ ...props }) {
2816
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.Sub, {
2817
+ "data-slot": "dropdown-menu-sub",
510
2818
  ...props
511
- }, children);
512
- });
513
- CardContent.displayName = "CardContent";
514
- var CardFooter = /* @__PURE__ */ forwardRef(({ className, children, ...props }, ref) => {
515
- return /* @__PURE__ */ React7.createElement("div", {
516
- ref,
517
- className: clsx("lui-card-footer", className),
2819
+ });
2820
+ }
2821
+ __name(DropdownMenuSub, "DropdownMenuSub");
2822
+ function DropdownMenuSubTrigger({ className, inset, children, ...props }) {
2823
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.SubTrigger, {
2824
+ "data-slot": "dropdown-menu-sub-trigger",
2825
+ "data-inset": inset,
2826
+ className: cn("focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
518
2827
  ...props
519
- }, children);
520
- });
521
- CardFooter.displayName = "CardFooter";
2828
+ }, children, /* @__PURE__ */ React25.createElement(ChevronRightIcon, {
2829
+ className: "ml-auto size-4"
2830
+ }));
2831
+ }
2832
+ __name(DropdownMenuSubTrigger, "DropdownMenuSubTrigger");
2833
+ function DropdownMenuSubContent({ className, ...props }) {
2834
+ return /* @__PURE__ */ React25.createElement(DropdownMenuPrimitive.SubContent, {
2835
+ "data-slot": "dropdown-menu-sub-content",
2836
+ className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg", className),
2837
+ ...props
2838
+ });
2839
+ }
2840
+ __name(DropdownMenuSubContent, "DropdownMenuSubContent");
2841
+ function TooltipProvider({ delayDuration = 0, ...props }) {
2842
+ return /* @__PURE__ */ React25.createElement(TooltipPrimitive.Provider, {
2843
+ "data-slot": "tooltip-provider",
2844
+ delayDuration,
2845
+ ...props
2846
+ });
2847
+ }
2848
+ __name(TooltipProvider, "TooltipProvider");
2849
+ function Tooltip({ ...props }) {
2850
+ return /* @__PURE__ */ React25.createElement(TooltipProvider, null, /* @__PURE__ */ React25.createElement(TooltipPrimitive.Root, {
2851
+ "data-slot": "tooltip",
2852
+ ...props
2853
+ }));
2854
+ }
2855
+ __name(Tooltip, "Tooltip");
2856
+ function TooltipTrigger({ ...props }) {
2857
+ return /* @__PURE__ */ React25.createElement(TooltipPrimitive.Trigger, {
2858
+ "data-slot": "tooltip-trigger",
2859
+ ...props
2860
+ });
2861
+ }
2862
+ __name(TooltipTrigger, "TooltipTrigger");
2863
+ function TooltipContent({ className, sideOffset = 0, children, ...props }) {
2864
+ return /* @__PURE__ */ React25.createElement(TooltipPrimitive.Portal, null, /* @__PURE__ */ React25.createElement(TooltipPrimitive.Content, {
2865
+ "data-slot": "tooltip-content",
2866
+ sideOffset,
2867
+ className: cn("bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", className),
2868
+ ...props
2869
+ }, children, /* @__PURE__ */ React25.createElement(TooltipPrimitive.Arrow, {
2870
+ className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]"
2871
+ })));
2872
+ }
2873
+ __name(TooltipContent, "TooltipContent");
522
2874
  function DataGrid({ data, columns, searchable = false, searchPlaceholder = "Search...", onRowClick, loading = false, emptyMessage = "No data", className }) {
523
2875
  const [sorting, setSorting] = useState([]);
524
2876
  const [globalFilter, setGlobalFilter] = useState("");
@@ -545,50 +2897,50 @@ function DataGrid({ data, columns, searchable = false, searchPlaceholder = "Sear
545
2897
  getSortedRowModel: getSortedRowModel(),
546
2898
  getFilteredRowModel: getFilteredRowModel()
547
2899
  });
548
- return /* @__PURE__ */ React7.createElement("div", {
2900
+ return /* @__PURE__ */ React25__default.createElement("div", {
549
2901
  className: clsx("lui-datagrid", className)
550
- }, searchable && /* @__PURE__ */ React7.createElement("div", {
2902
+ }, searchable && /* @__PURE__ */ React25__default.createElement("div", {
551
2903
  className: "lui-datagrid-search"
552
- }, /* @__PURE__ */ React7.createElement("input", {
2904
+ }, /* @__PURE__ */ React25__default.createElement("input", {
553
2905
  type: "text",
554
2906
  value: globalFilter,
555
2907
  onChange: /* @__PURE__ */ __name((e) => setGlobalFilter(e.target.value), "onChange"),
556
2908
  placeholder: searchPlaceholder,
557
2909
  className: "lui-datagrid-search-input"
558
- })), /* @__PURE__ */ React7.createElement("div", {
2910
+ })), /* @__PURE__ */ React25__default.createElement("div", {
559
2911
  className: "lui-datagrid-container"
560
- }, /* @__PURE__ */ React7.createElement("table", {
2912
+ }, /* @__PURE__ */ React25__default.createElement("table", {
561
2913
  className: "lui-datagrid-table"
562
- }, /* @__PURE__ */ React7.createElement("thead", null, table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ React7.createElement("tr", {
2914
+ }, /* @__PURE__ */ React25__default.createElement("thead", null, table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ React25__default.createElement("tr", {
563
2915
  key: headerGroup.id
564
- }, headerGroup.headers.map((header) => /* @__PURE__ */ React7.createElement("th", {
2916
+ }, headerGroup.headers.map((header) => /* @__PURE__ */ React25__default.createElement("th", {
565
2917
  key: header.id,
566
2918
  className: clsx("lui-datagrid-th", header.column.getCanSort() && "lui-datagrid-th--sortable"),
567
2919
  onClick: header.column.getToggleSortingHandler(),
568
2920
  style: {
569
2921
  width: header.column.getSize()
570
2922
  }
571
- }, /* @__PURE__ */ React7.createElement("div", {
2923
+ }, /* @__PURE__ */ React25__default.createElement("div", {
572
2924
  className: "lui-datagrid-th-content"
573
- }, flexRender(header.column.columnDef.header, header.getContext()), header.column.getIsSorted() && /* @__PURE__ */ React7.createElement("span", {
2925
+ }, flexRender(header.column.columnDef.header, header.getContext()), header.column.getIsSorted() && /* @__PURE__ */ React25__default.createElement("span", {
574
2926
  className: "lui-datagrid-sort-icon"
575
- }, header.column.getIsSorted() === "asc" ? "\u2191" : "\u2193"))))))), /* @__PURE__ */ React7.createElement("tbody", null, loading ? /* @__PURE__ */ React7.createElement("tr", null, /* @__PURE__ */ React7.createElement("td", {
2927
+ }, header.column.getIsSorted() === "asc" ? "\u2191" : "\u2193"))))))), /* @__PURE__ */ React25__default.createElement("tbody", null, loading ? /* @__PURE__ */ React25__default.createElement("tr", null, /* @__PURE__ */ React25__default.createElement("td", {
576
2928
  colSpan: columns.length,
577
2929
  className: "lui-datagrid-loading"
578
- }, "Loading...")) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ React7.createElement("tr", null, /* @__PURE__ */ React7.createElement("td", {
2930
+ }, "Loading...")) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ React25__default.createElement("tr", null, /* @__PURE__ */ React25__default.createElement("td", {
579
2931
  colSpan: columns.length,
580
2932
  className: "lui-datagrid-empty"
581
- }, emptyMessage)) : table.getRowModel().rows.map((row) => /* @__PURE__ */ React7.createElement("tr", {
2933
+ }, emptyMessage)) : table.getRowModel().rows.map((row) => /* @__PURE__ */ React25__default.createElement("tr", {
582
2934
  key: row.id,
583
2935
  className: clsx("lui-datagrid-row", onRowClick && "lui-datagrid-row--clickable"),
584
2936
  onClick: /* @__PURE__ */ __name(() => onRowClick?.(row.original), "onClick")
585
- }, row.getVisibleCells().map((cell) => /* @__PURE__ */ React7.createElement("td", {
2937
+ }, row.getVisibleCells().map((cell) => /* @__PURE__ */ React25__default.createElement("td", {
586
2938
  key: cell.id,
587
2939
  className: "lui-datagrid-td"
588
2940
  }, flexRender(cell.column.columnDef.cell, cell.getContext())))))))));
589
2941
  }
590
2942
  __name(DataGrid, "DataGrid");
591
- Chart$1.register(CategoryScale, LinearScale, PointElement, LineElement, BarElement, ArcElement, Title, Tooltip, Legend);
2943
+ Chart$1.register(CategoryScale, LinearScale, PointElement, LineElement, BarElement, ArcElement, Title, Tooltip$1, Legend);
592
2944
  function Chart({ type, data, options, height = 300, width = "100%", className }) {
593
2945
  const defaultOptions = {
594
2946
  responsive: true,
@@ -641,13 +2993,13 @@ function Chart({ type, data, options, height = 300, width = "100%", className })
641
2993
  ...options?.plugins
642
2994
  }
643
2995
  };
644
- return /* @__PURE__ */ React7.createElement("div", {
2996
+ return /* @__PURE__ */ React25__default.createElement("div", {
645
2997
  className: clsx("lui-chart", className),
646
2998
  style: {
647
2999
  height,
648
3000
  width
649
3001
  }
650
- }, /* @__PURE__ */ React7.createElement(Chart$2, {
3002
+ }, /* @__PURE__ */ React25__default.createElement(Chart$2, {
651
3003
  type,
652
3004
  data,
653
3005
  options: mergedOptions
@@ -656,99 +3008,176 @@ function Chart({ type, data, options, height = 300, width = "100%", className })
656
3008
  __name(Chart, "Chart");
657
3009
  function AppShell({ header, sidebar, footer, sidebarPosition = "left", sidebarWidth = 240, autoResize = true, padding = "md", className, children, ...props }) {
658
3010
  const containerRef = useRef(null);
3011
+ const { app } = useMcpApp();
659
3012
  useEffect(() => {
660
3013
  if (!autoResize || !containerRef.current) return;
661
- const resizeObserver = new ResizeObserver((entries) => {
662
- for (const entry of entries) {
663
- const { height } = entry.contentRect;
664
- window.parent.postMessage({
665
- type: "resize",
666
- height: Math.ceil(height)
667
- }, "*");
668
- }
669
- });
3014
+ if (!app) return;
3015
+ let lastWidth = 0;
3016
+ let lastHeight = 0;
3017
+ let scheduled = false;
3018
+ const sendSizeChanged = /* @__PURE__ */ __name(() => {
3019
+ if (scheduled) return;
3020
+ scheduled = true;
3021
+ requestAnimationFrame(() => {
3022
+ scheduled = false;
3023
+ if (!containerRef.current) return;
3024
+ const rect = containerRef.current.getBoundingClientRect();
3025
+ const width = Math.ceil(rect.width);
3026
+ const height = Math.ceil(rect.height);
3027
+ if (width !== lastWidth || height !== lastHeight) {
3028
+ lastWidth = width;
3029
+ lastHeight = height;
3030
+ app.sendSizeChanged({
3031
+ width,
3032
+ height
3033
+ });
3034
+ }
3035
+ });
3036
+ }, "sendSizeChanged");
3037
+ const resizeObserver = new ResizeObserver(sendSizeChanged);
670
3038
  resizeObserver.observe(containerRef.current);
3039
+ sendSizeChanged();
671
3040
  return () => {
672
3041
  resizeObserver.disconnect();
673
3042
  };
674
3043
  }, [
675
- autoResize
3044
+ autoResize,
3045
+ app
676
3046
  ]);
677
3047
  const sidebarStyle = {
678
3048
  width: typeof sidebarWidth === "number" ? `${sidebarWidth}px` : sidebarWidth,
679
3049
  flexShrink: 0
680
3050
  };
681
- return /* @__PURE__ */ React7.createElement("div", {
3051
+ return /* @__PURE__ */ React25__default.createElement("div", {
682
3052
  ref: containerRef,
683
3053
  className: clsx("lui-app-shell", `lui-app-shell--padding-${padding}`, className),
684
3054
  ...props
685
- }, header && /* @__PURE__ */ React7.createElement("header", {
3055
+ }, header && /* @__PURE__ */ React25__default.createElement("header", {
686
3056
  className: "lui-app-shell-header"
687
- }, header), /* @__PURE__ */ React7.createElement("div", {
3057
+ }, header), /* @__PURE__ */ React25__default.createElement("div", {
688
3058
  className: "lui-app-shell-body"
689
- }, sidebar && sidebarPosition === "left" && /* @__PURE__ */ React7.createElement("aside", {
3059
+ }, sidebar && sidebarPosition === "left" && /* @__PURE__ */ React25__default.createElement("aside", {
690
3060
  className: "lui-app-shell-sidebar",
691
3061
  style: sidebarStyle
692
- }, sidebar), /* @__PURE__ */ React7.createElement("main", {
3062
+ }, sidebar), /* @__PURE__ */ React25__default.createElement("main", {
693
3063
  className: "lui-app-shell-main"
694
- }, children), sidebar && sidebarPosition === "right" && /* @__PURE__ */ React7.createElement("aside", {
3064
+ }, children), sidebar && sidebarPosition === "right" && /* @__PURE__ */ React25__default.createElement("aside", {
695
3065
  className: "lui-app-shell-sidebar",
696
3066
  style: sidebarStyle
697
- }, sidebar)), footer && /* @__PURE__ */ React7.createElement("footer", {
3067
+ }, sidebar)), footer && /* @__PURE__ */ React25__default.createElement("footer", {
698
3068
  className: "lui-app-shell-footer"
699
3069
  }, footer));
700
3070
  }
701
3071
  __name(AppShell, "AppShell");
3072
+ function Tabs2({ tabs, defaultValue, value, onValueChange, children, className }) {
3073
+ const defaultTab = defaultValue || tabs[0]?.value;
3074
+ return /* @__PURE__ */ React25__default.createElement(TabsPrimitive2.Root, {
3075
+ className: clsx("lui-tabs", className),
3076
+ defaultValue: defaultTab,
3077
+ value,
3078
+ onValueChange
3079
+ }, /* @__PURE__ */ React25__default.createElement(TabsPrimitive2.List, {
3080
+ className: "lui-tabs-list"
3081
+ }, tabs.map((tab) => /* @__PURE__ */ React25__default.createElement(TabsPrimitive2.Trigger, {
3082
+ key: tab.value,
3083
+ value: tab.value,
3084
+ disabled: tab.disabled,
3085
+ className: "lui-tabs-trigger"
3086
+ }, tab.label))), children);
3087
+ }
3088
+ __name(Tabs2, "Tabs");
3089
+ function TabContent({ value, children, className }) {
3090
+ return /* @__PURE__ */ React25__default.createElement(TabsPrimitive2.Content, {
3091
+ value,
3092
+ className: clsx("lui-tabs-content", className)
3093
+ }, children);
3094
+ }
3095
+ __name(TabContent, "TabContent");
3096
+ function Modal({ open, defaultOpen, onOpenChange, title, description, children, className, trigger }) {
3097
+ return /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Root, {
3098
+ open,
3099
+ defaultOpen,
3100
+ onOpenChange
3101
+ }, trigger && /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Trigger, {
3102
+ asChild: true
3103
+ }, trigger), /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Portal, null, /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Overlay, {
3104
+ className: "lui-modal-overlay"
3105
+ }), /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Content, {
3106
+ className: clsx("lui-modal-content", className)
3107
+ }, title && /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Title, {
3108
+ className: "lui-modal-title"
3109
+ }, title), description && /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Description, {
3110
+ className: "lui-modal-description"
3111
+ }, description), children, /* @__PURE__ */ React25__default.createElement(DialogPrimitive.Close, {
3112
+ className: "lui-modal-close",
3113
+ "aria-label": "Close"
3114
+ }, /* @__PURE__ */ React25__default.createElement(CloseIcon, null)))));
3115
+ }
3116
+ __name(Modal, "Modal");
3117
+ function CloseIcon() {
3118
+ return /* @__PURE__ */ React25__default.createElement("svg", {
3119
+ width: "14",
3120
+ height: "14",
3121
+ viewBox: "0 0 14 14",
3122
+ fill: "none"
3123
+ }, /* @__PURE__ */ React25__default.createElement("path", {
3124
+ d: "M3.5 3.5L10.5 10.5M10.5 3.5L3.5 10.5",
3125
+ stroke: "currentColor",
3126
+ strokeWidth: "1.5",
3127
+ strokeLinecap: "round"
3128
+ }));
3129
+ }
3130
+ __name(CloseIcon, "CloseIcon");
702
3131
  function CodeBlock({ code, language = "text", showLineNumbers = false, copyable = true, className }) {
703
- const [copied, setCopied] = React7.useState(false);
3132
+ const [copied, setCopied] = React25__default.useState(false);
704
3133
  const handleCopy = /* @__PURE__ */ __name(async () => {
705
3134
  await navigator.clipboard.writeText(code);
706
3135
  setCopied(true);
707
3136
  setTimeout(() => setCopied(false), 2e3);
708
3137
  }, "handleCopy");
709
- return /* @__PURE__ */ React7.createElement("div", {
3138
+ return /* @__PURE__ */ React25__default.createElement("div", {
710
3139
  className: clsx("lui-code-block", className)
711
- }, copyable && /* @__PURE__ */ React7.createElement("button", {
3140
+ }, copyable && /* @__PURE__ */ React25__default.createElement("button", {
712
3141
  type: "button",
713
3142
  className: "lui-code-block-copy",
714
3143
  onClick: handleCopy,
715
3144
  "aria-label": copied ? "Copied!" : "Copy code"
716
- }, copied ? /* @__PURE__ */ React7.createElement("svg", {
3145
+ }, copied ? /* @__PURE__ */ React25__default.createElement("svg", {
717
3146
  viewBox: "0 0 24 24",
718
3147
  fill: "none",
719
3148
  stroke: "currentColor",
720
3149
  strokeWidth: "2"
721
- }, /* @__PURE__ */ React7.createElement("polyline", {
3150
+ }, /* @__PURE__ */ React25__default.createElement("polyline", {
722
3151
  points: "20,6 9,17 4,12"
723
- })) : /* @__PURE__ */ React7.createElement("svg", {
3152
+ })) : /* @__PURE__ */ React25__default.createElement("svg", {
724
3153
  viewBox: "0 0 24 24",
725
3154
  fill: "none",
726
3155
  stroke: "currentColor",
727
3156
  strokeWidth: "2"
728
- }, /* @__PURE__ */ React7.createElement("rect", {
3157
+ }, /* @__PURE__ */ React25__default.createElement("rect", {
729
3158
  x: "9",
730
3159
  y: "9",
731
3160
  width: "13",
732
3161
  height: "13",
733
3162
  rx: "2",
734
3163
  ry: "2"
735
- }), /* @__PURE__ */ React7.createElement("path", {
3164
+ }), /* @__PURE__ */ React25__default.createElement("path", {
736
3165
  d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
737
- }))), /* @__PURE__ */ React7.createElement(Highlight, {
3166
+ }))), /* @__PURE__ */ React25__default.createElement(Highlight, {
738
3167
  theme: themes.nightOwl,
739
3168
  code: code.trim(),
740
3169
  language
741
- }, ({ className: hlClassName, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ React7.createElement("pre", {
3170
+ }, ({ className: hlClassName, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ React25__default.createElement("pre", {
742
3171
  className: clsx("lui-code-block-pre", hlClassName),
743
3172
  style
744
- }, tokens.map((line, i) => /* @__PURE__ */ React7.createElement("div", {
3173
+ }, tokens.map((line, i) => /* @__PURE__ */ React25__default.createElement("div", {
745
3174
  key: i,
746
3175
  ...getLineProps({
747
3176
  line
748
3177
  })
749
- }, showLineNumbers && /* @__PURE__ */ React7.createElement("span", {
3178
+ }, showLineNumbers && /* @__PURE__ */ React25__default.createElement("span", {
750
3179
  className: "lui-code-block-line-number"
751
- }, i + 1), line.map((token, key) => /* @__PURE__ */ React7.createElement("span", {
3180
+ }, i + 1), line.map((token, key) => /* @__PURE__ */ React25__default.createElement("span", {
752
3181
  key,
753
3182
  ...getTokenProps({
754
3183
  token
@@ -756,7 +3185,74 @@ function CodeBlock({ code, language = "text", showLineNumbers = false, copyable
756
3185
  })))))));
757
3186
  }
758
3187
  __name(CodeBlock, "CodeBlock");
3188
+ var Card2 = /* @__PURE__ */ forwardRef(({ className, variant = "default", padding = "md", interactive = false, children, ...props }, ref) => {
3189
+ return /* @__PURE__ */ React25__default.createElement("div", {
3190
+ ref,
3191
+ className: clsx("lui-card", `lui-card--${variant}`, `lui-card--padding-${padding}`, interactive && "lui-card--interactive", className),
3192
+ ...props
3193
+ }, children);
3194
+ });
3195
+ Card2.displayName = "Card";
3196
+ var CardHeader2 = /* @__PURE__ */ forwardRef(({ className, title, description, action, children, ...props }, ref) => {
3197
+ return /* @__PURE__ */ React25__default.createElement("div", {
3198
+ ref,
3199
+ className: clsx("lui-card-header", className),
3200
+ ...props
3201
+ }, (title || description) && /* @__PURE__ */ React25__default.createElement("div", {
3202
+ className: "lui-card-header__text"
3203
+ }, title && /* @__PURE__ */ React25__default.createElement("h3", {
3204
+ className: "lui-card-header__title"
3205
+ }, title), description && /* @__PURE__ */ React25__default.createElement("p", {
3206
+ className: "lui-card-header__description"
3207
+ }, description)), action && /* @__PURE__ */ React25__default.createElement("div", {
3208
+ className: "lui-card-header__action"
3209
+ }, action), children);
3210
+ });
3211
+ CardHeader2.displayName = "CardHeader";
3212
+ var CardContent2 = /* @__PURE__ */ forwardRef(({ className, children, ...props }, ref) => {
3213
+ return /* @__PURE__ */ React25__default.createElement("div", {
3214
+ ref,
3215
+ className: clsx("lui-card-content", className),
3216
+ ...props
3217
+ }, children);
3218
+ });
3219
+ CardContent2.displayName = "CardContent";
3220
+ var CardFooter2 = /* @__PURE__ */ forwardRef(({ className, children, ...props }, ref) => {
3221
+ return /* @__PURE__ */ React25__default.createElement("div", {
3222
+ ref,
3223
+ className: clsx("lui-card-footer", className),
3224
+ ...props
3225
+ }, children);
3226
+ });
3227
+ CardFooter2.displayName = "CardFooter";
3228
+ var Input2 = /* @__PURE__ */ forwardRef(({ className, label, helperText, error, size = "md", leftElement, rightElement, fullWidth = false, id, ...props }, ref) => {
3229
+ const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
3230
+ const hasError = Boolean(error);
3231
+ return /* @__PURE__ */ React25__default.createElement("div", {
3232
+ className: clsx("lui-input-wrapper", fullWidth && "lui-input-wrapper--full-width", className)
3233
+ }, label && /* @__PURE__ */ React25__default.createElement("label", {
3234
+ htmlFor: inputId,
3235
+ className: "lui-input-label"
3236
+ }, label), /* @__PURE__ */ React25__default.createElement("div", {
3237
+ className: clsx("lui-input-container", `lui-input-container--${size}`, hasError && "lui-input-container--error", leftElement && "lui-input-container--has-left", rightElement && "lui-input-container--has-right")
3238
+ }, leftElement && /* @__PURE__ */ React25__default.createElement("span", {
3239
+ className: "lui-input-element lui-input-element--left"
3240
+ }, leftElement), /* @__PURE__ */ React25__default.createElement("input", {
3241
+ ref,
3242
+ id: inputId,
3243
+ className: "lui-input",
3244
+ "aria-invalid": hasError,
3245
+ "aria-describedby": error ? `${inputId}-error` : helperText ? `${inputId}-helper` : void 0,
3246
+ ...props
3247
+ }), rightElement && /* @__PURE__ */ React25__default.createElement("span", {
3248
+ className: "lui-input-element lui-input-element--right"
3249
+ }, rightElement)), (error || helperText) && /* @__PURE__ */ React25__default.createElement("p", {
3250
+ id: error ? `${inputId}-error` : `${inputId}-helper`,
3251
+ className: clsx("lui-input-message", error && "lui-input-message--error")
3252
+ }, error || helperText));
3253
+ });
3254
+ Input2.displayName = "Input";
759
3255
 
760
- export { ActionButton, AppProvider, AppShell, Button, Card, CardContent, CardFooter, CardHeader, Chart, CodeBlock, DataGrid, Input, ToolForm, UIApp, getUIAppMetadata, getUIAppUri, useHostContext, useMcpApp, useTool, useToolInput, useToolInputPartial, useToolResult };
3256
+ export { ActionButton, Alert, AlertDescription, AlertTitle, AppProvider, AppShell, Badge, Button2 as Button, Card2 as Card, CardContent2 as CardContent, CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle, Chart, Checkbox, CodeBlock, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, DEFAULT_RESULT_CONFIG, DataGrid, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, INITIAL_TOOL_STATE, Input2 as Input, Label2 as Label, Modal, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Progress, RequireConnection, ResourceView, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, Skeleton, Slider, StreamingContent, Switch, TabContent, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs2 as Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toaster, ToolButton, ToolDataGrid, ToolErrorBoundary, ToolForm, ToolInput, ToolProvider, ToolSelect, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, badgeVariants, buttonVariants, cn, normalizeToolBinding, useFormField, useHostContext, useMcpApp, useMessage, useResource, useTool, useToolContext, useToolInput, useToolInputPartial, useToolResult, useToolStream, useToolSubscription };
761
3257
  //# sourceMappingURL=index.mjs.map
762
3258
  //# sourceMappingURL=index.mjs.map