@tangle-network/sandbox-ui 0.3.5 → 0.3.7

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.
@@ -3,6 +3,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { S as SessionMessage, a as SessionPart } from './parts-CyGkM6Fp.js';
4
4
  import { A as AgentBranding } from './branding-DCi5VEik.js';
5
5
  import { C as CustomToolRenderer } from './tool-display-Ct9nFAzJ.js';
6
+ import { OpenUIAction } from './openui.js';
6
7
 
7
8
  /**
8
9
  * ChatInput — message input bar with file attach, send/cancel, model selector.
@@ -57,11 +58,15 @@ interface ChatContainerProps {
57
58
  onRemoveFile?: (id: string) => void;
58
59
  onAttach?: (files: FileList) => void;
59
60
  disabled?: boolean;
61
+ /** Callback when an OpenUI action button is pressed within inline OpenUI blocks. */
62
+ onOpenUIAction?: (action: OpenUIAction) => void;
63
+ /** Enable rendering OpenUI schemas inline in the chat timeline. Defaults to true. */
64
+ enableOpenUI?: boolean;
60
65
  }
61
66
  /**
62
67
  * Full chat container: message list + auto-scroll + input area.
63
68
  * Orchestrates useRunGroups, useRunCollapseState, and useAutoScroll.
64
69
  */
65
- declare const ChatContainer: React.MemoExoticComponent<({ messages, partMap, isStreaming, onSend, onCancel, branding, placeholder, className, hideInput, renderToolDetail, presentation, modelLabel, onModelClick, pendingFiles, onRemoveFile, onAttach, disabled, }: ChatContainerProps) => react_jsx_runtime.JSX.Element>;
70
+ declare const ChatContainer: React.MemoExoticComponent<({ messages, partMap, isStreaming, onSend, onCancel, branding, placeholder, className, hideInput, renderToolDetail, presentation, modelLabel, onModelClick, pendingFiles, onRemoveFile, onAttach, disabled, onOpenUIAction, enableOpenUI, }: ChatContainerProps) => react_jsx_runtime.JSX.Element>;
66
71
 
67
72
  export { ChatContainer as C, type PendingFile as P, ChatInput as a, type ChatInputProps as b, type ChatContainerProps as c };
package/dist/chat.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { C as ChatContainer, c as ChatContainerProps, a as ChatInput, b as ChatInputProps, P as PendingFile } from './chat-container-C8eHLw8z.js';
1
+ export { C as ChatContainer, c as ChatContainerProps, a as ChatInput, b as ChatInputProps, P as PendingFile } from './chat-container-B34uj-J1.js';
2
2
  import * as React from 'react';
3
3
  import { ReactNode } from 'react';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -7,6 +7,7 @@ import { a as SessionPart, S as SessionMessage } from './parts-CyGkM6Fp.js';
7
7
  import { A as AgentBranding } from './branding-DCi5VEik.js';
8
8
  import { C as CustomToolRenderer } from './tool-display-Ct9nFAzJ.js';
9
9
  import { T as ToolCallData } from './tool-call-feed-D5Ume-Pt.js';
10
+ import './openui.js';
10
11
 
11
12
  type MessageRole = "user" | "assistant" | "system";
12
13
  interface ChatMessageProps {
package/dist/chat.js CHANGED
@@ -6,13 +6,17 @@ import {
6
6
  MessageList,
7
7
  ThinkingIndicator,
8
8
  UserMessage
9
- } from "./chunk-4F2GJRGU.js";
9
+ } from "./chunk-PXRPYAMM.js";
10
10
  import "./chunk-CNWVHQFY.js";
11
11
  import "./chunk-WUR652Y3.js";
12
12
  import "./chunk-HRMUF35V.js";
13
13
  import "./chunk-CJ2RYVZH.js";
14
14
  import "./chunk-BX6AQMUS.js";
15
+ import "./chunk-YDBXQQLC.js";
16
+ import "./chunk-TQN3VR4F.js";
15
17
  import "./chunk-LTFK464G.js";
18
+ import "./chunk-MXCSSOGH.js";
19
+ import "./chunk-HWLX5NME.js";
16
20
  import "./chunk-RQHJBTEU.js";
17
21
  export {
18
22
  AgentTimeline,
@@ -530,6 +530,155 @@ var TerminalInput = React6.forwardRef(
530
530
  );
531
531
  TerminalInput.displayName = "TerminalInput";
532
532
 
533
+ // src/primitives/drop-zone.tsx
534
+ import { useCallback as useCallback2, useRef as useRef2, useState as useState3 } from "react";
535
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
536
+ function DropZone({
537
+ onDrop,
538
+ accept,
539
+ disabled,
540
+ overlay,
541
+ title = "Drop files to upload",
542
+ description = "Your files will be securely stored in the workspace.",
543
+ icon = "cloud_upload",
544
+ children,
545
+ className
546
+ }) {
547
+ const [dragOver, setDragOver] = useState3(false);
548
+ const counter = useRef2(0);
549
+ const isAccepted = useCallback2(
550
+ (file) => {
551
+ if (!accept) return true;
552
+ const extensions = accept.split(",").map((ext) => ext.trim().toLowerCase());
553
+ const fileName = file.name.toLowerCase();
554
+ return extensions.some((ext) => fileName.endsWith(ext));
555
+ },
556
+ [accept]
557
+ );
558
+ const handleDragEnter = useCallback2(
559
+ (e) => {
560
+ e.preventDefault();
561
+ if (disabled) return;
562
+ counter.current++;
563
+ if (e.dataTransfer?.types.includes("Files")) setDragOver(true);
564
+ },
565
+ [disabled]
566
+ );
567
+ const handleDragLeave = useCallback2((e) => {
568
+ e.preventDefault();
569
+ counter.current--;
570
+ if (counter.current === 0) setDragOver(false);
571
+ }, []);
572
+ const handleDragOver = useCallback2(
573
+ (e) => {
574
+ e.preventDefault();
575
+ if (!disabled) e.dataTransfer.dropEffect = "copy";
576
+ },
577
+ [disabled]
578
+ );
579
+ const handleDrop = useCallback2(
580
+ (e) => {
581
+ e.preventDefault();
582
+ counter.current = 0;
583
+ setDragOver(false);
584
+ if (disabled) return;
585
+ const allFiles = Array.from(e.dataTransfer?.files || []);
586
+ const accepted = accept ? allFiles.filter(isAccepted) : allFiles;
587
+ if (accepted.length > 0) onDrop(accepted);
588
+ },
589
+ [disabled, accept, isAccepted, onDrop]
590
+ );
591
+ return /* @__PURE__ */ jsxs5(
592
+ "div",
593
+ {
594
+ onDragEnter: handleDragEnter,
595
+ onDragLeave: handleDragLeave,
596
+ onDragOver: handleDragOver,
597
+ onDrop: handleDrop,
598
+ className: cn("relative", className),
599
+ children: [
600
+ dragOver && (overlay || /* @__PURE__ */ jsx7("div", { className: "fixed inset-0 z-[100] flex items-center justify-center pointer-events-none bg-black/20 backdrop-blur-sm", children: /* @__PURE__ */ jsxs5("div", { className: "rounded-3xl border-2 border-dashed border-[hsl(var(--ring))] bg-[hsl(var(--card))] p-16 text-center shadow-2xl max-w-lg mx-auto", children: [
601
+ /* @__PURE__ */ jsx7("div", { className: "mx-auto mb-6 flex h-20 w-20 items-center justify-center rounded-2xl bg-[hsl(var(--primary))]/10", children: typeof icon === "string" ? /* @__PURE__ */ jsx7("span", { className: "material-symbols-outlined text-5xl text-[hsl(var(--primary))]", children: icon }) : icon }),
602
+ /* @__PURE__ */ jsx7("h2", { className: "text-2xl font-extrabold text-[hsl(var(--foreground))]", children: title }),
603
+ /* @__PURE__ */ jsx7("p", { className: "mt-2 text-[hsl(var(--muted-foreground))]", children: description })
604
+ ] }) })),
605
+ children
606
+ ]
607
+ }
608
+ );
609
+ }
610
+
611
+ // src/primitives/upload-progress.tsx
612
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
613
+ function formatSize(bytes) {
614
+ if (bytes < 1024) return `${bytes}B`;
615
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)}KB`;
616
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
617
+ }
618
+ function UploadProgress({ files, onRemove, onRetry, className }) {
619
+ if (files.length === 0) return null;
620
+ return /* @__PURE__ */ jsx8("div", { className: cn("space-y-2", className), children: files.map((file) => /* @__PURE__ */ jsxs6(
621
+ "div",
622
+ {
623
+ className: cn(
624
+ "flex items-center gap-3 rounded-lg border px-3 py-2 text-sm",
625
+ file.status === "error" ? "border-[hsl(var(--destructive))]/20 bg-[hsl(var(--destructive))]/5" : file.status === "complete" ? "border-[hsl(var(--success))]/20 bg-[hsl(var(--success))]/5" : "border-[hsl(var(--border))] bg-[hsl(var(--card))]"
626
+ ),
627
+ children: [
628
+ /* @__PURE__ */ jsx8(
629
+ "span",
630
+ {
631
+ className: cn(
632
+ "material-symbols-outlined text-base shrink-0",
633
+ file.status === "complete" && "text-[hsl(var(--success))]",
634
+ file.status === "error" && "text-[hsl(var(--destructive))]",
635
+ file.status === "uploading" && "text-[hsl(var(--primary))] animate-pulse",
636
+ file.status === "pending" && "text-[hsl(var(--muted-foreground))]"
637
+ ),
638
+ style: file.status === "complete" ? { fontVariationSettings: "'FILL' 1" } : void 0,
639
+ children: file.status === "complete" ? "check_circle" : file.status === "error" ? "error" : file.status === "uploading" ? "progress_activity" : "description"
640
+ }
641
+ ),
642
+ /* @__PURE__ */ jsxs6("div", { className: "flex-1 min-w-0", children: [
643
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
644
+ /* @__PURE__ */ jsx8("span", { className: "truncate font-medium text-[hsl(var(--foreground))]", children: file.name }),
645
+ /* @__PURE__ */ jsx8("span", { className: "shrink-0 text-xs text-[hsl(var(--muted-foreground))]", children: formatSize(file.size) })
646
+ ] }),
647
+ file.status === "uploading" && file.progress !== void 0 && /* @__PURE__ */ jsx8("div", { className: "mt-1 h-1 w-full rounded-full bg-[hsl(var(--muted))] overflow-hidden", children: /* @__PURE__ */ jsx8(
648
+ "div",
649
+ {
650
+ className: "h-full rounded-full bg-[hsl(var(--primary))] transition-all",
651
+ style: { width: `${file.progress}%` }
652
+ }
653
+ ) }),
654
+ file.status === "error" && file.error && /* @__PURE__ */ jsx8("p", { className: "mt-0.5 text-xs text-[hsl(var(--destructive))]", children: file.error })
655
+ ] }),
656
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 shrink-0", children: [
657
+ file.status === "error" && onRetry && /* @__PURE__ */ jsx8(
658
+ "button",
659
+ {
660
+ type: "button",
661
+ onClick: () => onRetry(file.id),
662
+ className: "rounded p-1 text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] transition-colors",
663
+ children: /* @__PURE__ */ jsx8("span", { className: "material-symbols-outlined text-sm", children: "refresh" })
664
+ }
665
+ ),
666
+ onRemove && /* @__PURE__ */ jsx8(
667
+ "button",
668
+ {
669
+ type: "button",
670
+ onClick: () => onRemove(file.id),
671
+ className: "rounded p-1 text-[hsl(var(--muted-foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--foreground))] transition-colors",
672
+ children: /* @__PURE__ */ jsx8("span", { className: "material-symbols-outlined text-sm", children: "close" })
673
+ }
674
+ )
675
+ ] })
676
+ ]
677
+ },
678
+ file.id
679
+ )) });
680
+ }
681
+
533
682
  export {
534
683
  Select,
535
684
  SelectGroup,
@@ -550,5 +699,7 @@ export {
550
699
  TerminalDisplay,
551
700
  TerminalLine,
552
701
  TerminalCursor,
553
- TerminalInput
702
+ TerminalInput,
703
+ DropZone,
704
+ UploadProgress
554
705
  };