@ash-cloud/ash-ui 0.0.1 → 0.0.3

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.js CHANGED
@@ -1924,6 +1924,203 @@ function TodoPanel({
1924
1924
  }
1925
1925
  );
1926
1926
  }
1927
+ function EnvVarsPanel({
1928
+ envVars,
1929
+ onChange,
1930
+ defaultCollapsed = true,
1931
+ className,
1932
+ label = "Environment Variables",
1933
+ helperText = "These environment variables will be available in the sandbox for new sessions."
1934
+ }) {
1935
+ const [expanded, setExpanded] = useState(!defaultCollapsed);
1936
+ const [newEnvKey, setNewEnvKey] = useState("");
1937
+ const [newEnvValue, setNewEnvValue] = useState("");
1938
+ const hasEnvVars = Object.keys(envVars).length > 0;
1939
+ const handleAddEnvVar = useCallback(() => {
1940
+ const key = newEnvKey.trim();
1941
+ const val = newEnvValue.trim();
1942
+ if (key) {
1943
+ onChange({ ...envVars, [key]: val });
1944
+ setNewEnvKey("");
1945
+ setNewEnvValue("");
1946
+ }
1947
+ }, [envVars, newEnvKey, newEnvValue, onChange]);
1948
+ const handleRemoveEnvVar = useCallback(
1949
+ (key) => {
1950
+ const newEnvVars = { ...envVars };
1951
+ delete newEnvVars[key];
1952
+ onChange(newEnvVars);
1953
+ },
1954
+ [envVars, onChange]
1955
+ );
1956
+ const handleEnvKeyDown = useCallback(
1957
+ (e) => {
1958
+ if (e.key === "Enter") {
1959
+ e.preventDefault();
1960
+ handleAddEnvVar();
1961
+ }
1962
+ },
1963
+ [handleAddEnvVar]
1964
+ );
1965
+ return /* @__PURE__ */ jsxs("div", { className: cn("ash-env-vars-panel", className), children: [
1966
+ /* @__PURE__ */ jsxs(
1967
+ "button",
1968
+ {
1969
+ type: "button",
1970
+ onClick: () => setExpanded(!expanded),
1971
+ className: "ash-env-vars-header",
1972
+ children: [
1973
+ /* @__PURE__ */ jsx(
1974
+ "svg",
1975
+ {
1976
+ xmlns: "http://www.w3.org/2000/svg",
1977
+ className: cn("ash-env-vars-chevron", expanded && "ash-env-vars-chevron-expanded"),
1978
+ viewBox: "0 0 20 20",
1979
+ fill: "currentColor",
1980
+ children: /* @__PURE__ */ jsx(
1981
+ "path",
1982
+ {
1983
+ fillRule: "evenodd",
1984
+ d: "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z",
1985
+ clipRule: "evenodd"
1986
+ }
1987
+ )
1988
+ }
1989
+ ),
1990
+ /* @__PURE__ */ jsx("span", { className: "ash-env-vars-label", children: label }),
1991
+ hasEnvVars && !expanded && /* @__PURE__ */ jsx("span", { className: "ash-env-vars-badge", children: Object.keys(envVars).length })
1992
+ ]
1993
+ }
1994
+ ),
1995
+ expanded && /* @__PURE__ */ jsxs("div", { className: "ash-env-vars-content", children: [
1996
+ Object.entries(envVars).map(([key, val]) => /* @__PURE__ */ jsxs("div", { className: "ash-env-vars-item", children: [
1997
+ /* @__PURE__ */ jsx("span", { className: "ash-env-vars-key", children: key }),
1998
+ /* @__PURE__ */ jsx("span", { className: "ash-env-vars-equals", children: "=" }),
1999
+ /* @__PURE__ */ jsx("span", { className: "ash-env-vars-value", children: val || "(empty)" }),
2000
+ /* @__PURE__ */ jsx(
2001
+ "button",
2002
+ {
2003
+ type: "button",
2004
+ onClick: () => handleRemoveEnvVar(key),
2005
+ className: "ash-env-vars-remove",
2006
+ title: "Remove variable",
2007
+ children: /* @__PURE__ */ jsx(
2008
+ "svg",
2009
+ {
2010
+ xmlns: "http://www.w3.org/2000/svg",
2011
+ className: "w-4 h-4",
2012
+ viewBox: "0 0 20 20",
2013
+ fill: "currentColor",
2014
+ children: /* @__PURE__ */ jsx(
2015
+ "path",
2016
+ {
2017
+ fillRule: "evenodd",
2018
+ d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
2019
+ clipRule: "evenodd"
2020
+ }
2021
+ )
2022
+ }
2023
+ )
2024
+ }
2025
+ )
2026
+ ] }, key)),
2027
+ /* @__PURE__ */ jsxs("div", { className: "ash-env-vars-add", children: [
2028
+ /* @__PURE__ */ jsx(
2029
+ "input",
2030
+ {
2031
+ type: "text",
2032
+ value: newEnvKey,
2033
+ onChange: (e) => setNewEnvKey(e.target.value.toUpperCase().replace(/[^A-Z0-9_]/g, "")),
2034
+ onKeyDown: handleEnvKeyDown,
2035
+ placeholder: "KEY",
2036
+ className: "ash-env-vars-input ash-env-vars-input-key"
2037
+ }
2038
+ ),
2039
+ /* @__PURE__ */ jsx("span", { className: "ash-env-vars-equals", children: "=" }),
2040
+ /* @__PURE__ */ jsx(
2041
+ "input",
2042
+ {
2043
+ type: "text",
2044
+ value: newEnvValue,
2045
+ onChange: (e) => setNewEnvValue(e.target.value),
2046
+ onKeyDown: handleEnvKeyDown,
2047
+ placeholder: "value",
2048
+ className: "ash-env-vars-input ash-env-vars-input-value"
2049
+ }
2050
+ ),
2051
+ /* @__PURE__ */ jsx(
2052
+ "button",
2053
+ {
2054
+ type: "button",
2055
+ onClick: handleAddEnvVar,
2056
+ disabled: !newEnvKey.trim(),
2057
+ className: "ash-env-vars-add-button",
2058
+ children: "Add"
2059
+ }
2060
+ )
2061
+ ] }),
2062
+ helperText && /* @__PURE__ */ jsx("p", { className: "ash-env-vars-helper", children: helperText })
2063
+ ] })
2064
+ ] });
2065
+ }
2066
+ function DisplayModeToggle({
2067
+ className,
2068
+ showLabel = true,
2069
+ labels = { inline: "Inline", compact: "Compact" }
2070
+ }) {
2071
+ const { config, toggleMode } = useDisplayMode();
2072
+ const isInline = config.mode === "inline";
2073
+ return /* @__PURE__ */ jsx(
2074
+ "button",
2075
+ {
2076
+ type: "button",
2077
+ onClick: toggleMode,
2078
+ className: cn("ash-display-mode-toggle", className),
2079
+ title: isInline ? "Switch to compact mode" : "Switch to inline mode",
2080
+ children: isInline ? /* @__PURE__ */ jsxs(Fragment, { children: [
2081
+ /* @__PURE__ */ jsx(
2082
+ "svg",
2083
+ {
2084
+ className: "ash-display-mode-icon",
2085
+ viewBox: "0 0 24 24",
2086
+ fill: "none",
2087
+ stroke: "currentColor",
2088
+ strokeWidth: "1.5",
2089
+ children: /* @__PURE__ */ jsx(
2090
+ "path",
2091
+ {
2092
+ strokeLinecap: "round",
2093
+ strokeLinejoin: "round",
2094
+ d: "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
2095
+ }
2096
+ )
2097
+ }
2098
+ ),
2099
+ showLabel && /* @__PURE__ */ jsx("span", { className: "ash-display-mode-label", children: labels.inline })
2100
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2101
+ /* @__PURE__ */ jsx(
2102
+ "svg",
2103
+ {
2104
+ className: "ash-display-mode-icon",
2105
+ viewBox: "0 0 24 24",
2106
+ fill: "none",
2107
+ stroke: "currentColor",
2108
+ strokeWidth: "1.5",
2109
+ children: /* @__PURE__ */ jsx(
2110
+ "path",
2111
+ {
2112
+ strokeLinecap: "round",
2113
+ strokeLinejoin: "round",
2114
+ d: "M3.75 6.75h16.5M3.75 12h16.5M12 17.25h8.25"
2115
+ }
2116
+ )
2117
+ }
2118
+ ),
2119
+ showLabel && /* @__PURE__ */ jsx("span", { className: "ash-display-mode-label", children: labels.compact })
2120
+ ] })
2121
+ }
2122
+ );
2123
+ }
1927
2124
  var DEFAULT_WORDS = [
1928
2125
  "Thinking",
1929
2126
  "Reasoning",
@@ -2312,7 +2509,226 @@ var inlineStyles = {
2312
2509
  borderRadius: borderRadius.lg
2313
2510
  }
2314
2511
  };
2512
+ function useMessageQueue({
2513
+ onProcessMessage,
2514
+ canProcess = true
2515
+ }) {
2516
+ const [queue, setQueue] = useState([]);
2517
+ const [isProcessing, setIsProcessing] = useState(false);
2518
+ const isProcessingRef = useRef(false);
2519
+ const onProcessMessageRef = useRef(onProcessMessage);
2520
+ useEffect(() => {
2521
+ onProcessMessageRef.current = onProcessMessage;
2522
+ }, [onProcessMessage]);
2523
+ const processQueue = useCallback(async () => {
2524
+ if (isProcessingRef.current || !canProcess) return;
2525
+ isProcessingRef.current = true;
2526
+ setIsProcessing(true);
2527
+ while (true) {
2528
+ let nextMessage;
2529
+ setQueue((prev) => {
2530
+ if (prev.length === 0) return prev;
2531
+ nextMessage = prev[0];
2532
+ return prev.slice(1);
2533
+ });
2534
+ await new Promise((resolve) => setTimeout(resolve, 0));
2535
+ if (!nextMessage) break;
2536
+ try {
2537
+ await onProcessMessageRef.current(nextMessage);
2538
+ } catch (error) {
2539
+ console.error("Error processing queued message:", error);
2540
+ }
2541
+ }
2542
+ isProcessingRef.current = false;
2543
+ setIsProcessing(false);
2544
+ }, [canProcess]);
2545
+ useEffect(() => {
2546
+ if (queue.length > 0 && !isProcessingRef.current && canProcess) {
2547
+ processQueue();
2548
+ }
2549
+ }, [queue, processQueue, canProcess]);
2550
+ const enqueue = useCallback((text, files) => {
2551
+ const message = {
2552
+ id: `queue-${Date.now()}-${Math.random().toString(36).slice(2)}`,
2553
+ text,
2554
+ files,
2555
+ queuedAt: Date.now()
2556
+ };
2557
+ setQueue((prev) => [...prev, message]);
2558
+ }, []);
2559
+ const cancel = useCallback((id) => {
2560
+ setQueue((prev) => prev.filter((m) => m.id !== id));
2561
+ }, []);
2562
+ const clearQueue = useCallback(() => {
2563
+ setQueue([]);
2564
+ }, []);
2565
+ return {
2566
+ queue,
2567
+ isProcessing,
2568
+ enqueue,
2569
+ cancel,
2570
+ clearQueue,
2571
+ queueLength: queue.length
2572
+ };
2573
+ }
2574
+ function useStopExecution({
2575
+ onServerStop
2576
+ } = {}) {
2577
+ const [canStop, setCanStop] = useState(false);
2578
+ const abortControllerRef = useRef(null);
2579
+ const sessionIdRef = useRef(null);
2580
+ const onServerStopRef = useRef(onServerStop);
2581
+ onServerStopRef.current = onServerStop;
2582
+ const startExecution = useCallback(() => {
2583
+ abortControllerRef.current = new AbortController();
2584
+ setCanStop(true);
2585
+ }, []);
2586
+ const endExecution = useCallback(() => {
2587
+ abortControllerRef.current = null;
2588
+ sessionIdRef.current = null;
2589
+ setCanStop(false);
2590
+ }, []);
2591
+ const setSessionId = useCallback((sessionId) => {
2592
+ sessionIdRef.current = sessionId;
2593
+ }, []);
2594
+ const stop = useCallback(async (explicitSessionId) => {
2595
+ if (abortControllerRef.current) {
2596
+ abortControllerRef.current.abort();
2597
+ }
2598
+ const sessionId = explicitSessionId || sessionIdRef.current;
2599
+ if (sessionId && onServerStopRef.current) {
2600
+ try {
2601
+ await onServerStopRef.current(sessionId);
2602
+ } catch (err) {
2603
+ console.warn("Server stop failed:", err);
2604
+ }
2605
+ }
2606
+ setCanStop(false);
2607
+ }, []);
2608
+ return {
2609
+ canStop,
2610
+ signal: abortControllerRef.current?.signal,
2611
+ startExecution,
2612
+ endExecution,
2613
+ stop,
2614
+ setSessionId
2615
+ };
2616
+ }
2617
+ function formatFileSize2(bytes) {
2618
+ if (bytes < 1024) return `${bytes} B`;
2619
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
2620
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
2621
+ }
2622
+ async function readFileAsBase64(file) {
2623
+ return new Promise((resolve, reject) => {
2624
+ const reader = new FileReader();
2625
+ reader.onload = () => {
2626
+ const result = reader.result;
2627
+ const base64 = result.split(",")[1];
2628
+ resolve(base64 || "");
2629
+ };
2630
+ reader.onerror = () => reject(reader.error);
2631
+ reader.readAsDataURL(file);
2632
+ });
2633
+ }
2634
+ function useFileUpload({
2635
+ maxFileSize = 100 * 1024 * 1024,
2636
+ // 100MB
2637
+ maxFiles = 10,
2638
+ onValidationError
2639
+ } = {}) {
2640
+ const [files, setFiles] = useState([]);
2641
+ const [isDragOver, setIsDragOver] = useState(false);
2642
+ const fileInputRef = useRef(null);
2643
+ const addFiles = useCallback(
2644
+ async (fileList) => {
2645
+ if (!fileList) return;
2646
+ const newFiles = [];
2647
+ const currentCount = files.length;
2648
+ for (let i = 0; i < fileList.length && currentCount + newFiles.length < maxFiles; i++) {
2649
+ const file = fileList.item(i);
2650
+ if (!file) continue;
2651
+ if (file.size > maxFileSize) {
2652
+ onValidationError?.(
2653
+ file.name,
2654
+ `Exceeds maximum size of ${formatFileSize2(maxFileSize)}`
2655
+ );
2656
+ continue;
2657
+ }
2658
+ try {
2659
+ const content = await readFileAsBase64(file);
2660
+ newFiles.push({
2661
+ filename: file.name,
2662
+ content,
2663
+ mimeType: file.type || "application/octet-stream",
2664
+ size: file.size
2665
+ });
2666
+ } catch (error) {
2667
+ console.error(`Failed to read file ${file.name}:`, error);
2668
+ onValidationError?.(file.name, "Failed to read file");
2669
+ }
2670
+ }
2671
+ if (fileList.length > maxFiles - currentCount && currentCount + newFiles.length >= maxFiles) {
2672
+ onValidationError?.("", `Maximum ${maxFiles} files allowed`);
2673
+ }
2674
+ if (newFiles.length > 0) {
2675
+ setFiles((prev) => [...prev, ...newFiles]);
2676
+ }
2677
+ },
2678
+ [files.length, maxFiles, maxFileSize, onValidationError]
2679
+ );
2680
+ const removeFile = useCallback((index) => {
2681
+ setFiles((prev) => prev.filter((_, i) => i !== index));
2682
+ }, []);
2683
+ const clearFiles = useCallback(() => {
2684
+ setFiles([]);
2685
+ }, []);
2686
+ const handleDragOver = useCallback((e) => {
2687
+ e.preventDefault();
2688
+ setIsDragOver(true);
2689
+ }, []);
2690
+ const handleDragLeave = useCallback((e) => {
2691
+ e.preventDefault();
2692
+ setIsDragOver(false);
2693
+ }, []);
2694
+ const handleDrop = useCallback(
2695
+ (e) => {
2696
+ e.preventDefault();
2697
+ setIsDragOver(false);
2698
+ addFiles(e.dataTransfer.files);
2699
+ },
2700
+ [addFiles]
2701
+ );
2702
+ const handleFileInputChange = useCallback(
2703
+ (e) => {
2704
+ addFiles(e.target.files);
2705
+ if (fileInputRef.current) {
2706
+ fileInputRef.current.value = "";
2707
+ }
2708
+ },
2709
+ [addFiles]
2710
+ );
2711
+ const openFilePicker = useCallback(() => {
2712
+ fileInputRef.current?.click();
2713
+ }, []);
2714
+ return {
2715
+ files,
2716
+ isDragOver,
2717
+ addFiles,
2718
+ removeFile,
2719
+ clearFiles,
2720
+ canAddMore: files.length < maxFiles,
2721
+ dropZoneProps: {
2722
+ onDragOver: handleDragOver,
2723
+ onDragLeave: handleDragLeave,
2724
+ onDrop: handleDrop
2725
+ },
2726
+ handleFileInputChange,
2727
+ fileInputRef,
2728
+ openFilePicker
2729
+ };
2730
+ }
2315
2731
 
2316
- export { ActionIcon, AlertCircleIcon, AlertTriangleIcon, AssistantMessage, BotIcon, BrainIcon, BugIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, ClipboardListIcon, CodeBlock, CodeIcon, CompactToolStatusLine, CopyIcon, DEFAULT_DISPLAY_CONFIG, DisplayModeProvider, EditIcon, ErrorMessage, FileIcon, FilePlusIcon, FolderSearchIcon, GlobeIcon, InfoIcon, JsonDisplay, ListChecksIcon, LoaderIcon, LoadingIndicator, LogsPanel, MessageEntry, MessageList, MessageSquareIcon, MoonIcon, OptionCards, PaperclipIcon, PlugIcon, SearchIcon, SendIcon, SparklesIcon, StatusIndicator, StopCircleIcon, StreamingText, SunIcon, TerminalIcon, ThemeProvider, ThinkingMessage, TodoPanel, ToolCallCard, ToolCallMessage, ToolExecutionGroup, ToolIcon, TypewriterText, UserIcon, UserMessage, XCircleIcon, XIcon, allKeyframesCss, borderRadius, cn, colors, createToolCall, extractTextContent, extractToolCallsFromGroup, formatFileSize, formatTimestamp, formatToolName, generateToolSummary, getActionIcon, getActionLabel, groupEntriesForCompactMode, inlineStyles, isCommandRunAction, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isMcpToolAction, isSearchAction, isTodoWriteAction, isToolCallEntry, isWebFetchAction, isWebSearchAction, keyframes, keyframesCss, mapToolToActionType, normalizeToolResult, parseCommandResult, parseMcpToolName, parseOptionsFromContent, shadows, spacing, tokensToCssVariables, transitions, truncate, typography, updateToolCallWithResult, useDisplayConfig, useDisplayMode, useTheme, widget, zIndex };
2732
+ export { ActionIcon, AlertCircleIcon, AlertTriangleIcon, AssistantMessage, BotIcon, BrainIcon, BugIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CircleIcon, ClipboardListIcon, CodeBlock, CodeIcon, CompactToolStatusLine, CopyIcon, DEFAULT_DISPLAY_CONFIG, DisplayModeProvider, DisplayModeToggle, EditIcon, EnvVarsPanel, ErrorMessage, FileIcon, FilePlusIcon, FolderSearchIcon, GlobeIcon, InfoIcon, JsonDisplay, ListChecksIcon, LoaderIcon, LoadingIndicator, LogsPanel, MessageEntry, MessageList, MessageSquareIcon, MoonIcon, OptionCards, PaperclipIcon, PlugIcon, SearchIcon, SendIcon, SparklesIcon, StatusIndicator, StopCircleIcon, StreamingText, SunIcon, TerminalIcon, ThemeProvider, ThinkingMessage, TodoPanel, ToolCallCard, ToolCallMessage, ToolExecutionGroup, ToolIcon, TypewriterText, UserIcon, UserMessage, XCircleIcon, XIcon, allKeyframesCss, borderRadius, cn, colors, createToolCall, extractTextContent, extractToolCallsFromGroup, formatFileSize, formatTimestamp, formatToolName, generateToolSummary, getActionIcon, getActionLabel, groupEntriesForCompactMode, inlineStyles, isCommandRunAction, isErrorEntry, isFileEditAction, isFileReadAction, isFileWriteAction, isGenericToolAction, isGlobAction, isMcpToolAction, isSearchAction, isTodoWriteAction, isToolCallEntry, isWebFetchAction, isWebSearchAction, keyframes, keyframesCss, mapToolToActionType, normalizeToolResult, parseCommandResult, parseMcpToolName, parseOptionsFromContent, shadows, spacing, tokensToCssVariables, transitions, truncate, typography, updateToolCallWithResult, useDisplayConfig, useDisplayMode, useFileUpload, useMessageQueue, useStopExecution, useTheme, widget, zIndex };
2317
2733
  //# sourceMappingURL=index.js.map
2318
2734
  //# sourceMappingURL=index.js.map