@iloveagents/foundry-web-ui 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -9,6 +9,7 @@ import { userAttachmentComponents, composerAttachmentComponents } from "./chat-a
|
|
|
9
9
|
import { SentContextBadges, ComposerContextBadges } from "./context-badges.js";
|
|
10
10
|
import { ContextPins } from "./context-bar.js";
|
|
11
11
|
import { ComposerSubmitBridge } from "./composer-submit-bridge.js";
|
|
12
|
+
import { ChatComposerBannerSlot } from "./chat-slots.js";
|
|
12
13
|
import { useChatBubbleStore } from "../lib/chat-bubble-store.js";
|
|
13
14
|
import { MarkdownText } from "./markdown-text.js";
|
|
14
15
|
import { ToolFallback } from "./tool-fallback.js";
|
|
@@ -90,5 +91,5 @@ export function ChatContent({ starterSuggestions = DEFAULT_STARTER_SUGGESTIONS,
|
|
|
90
91
|
UserMessage,
|
|
91
92
|
EditComposer,
|
|
92
93
|
AssistantMessage,
|
|
93
|
-
} }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingIndicator, {}) })] }) })] }), _jsx(ThreadPrimitive.If, { empty: false, children: _jsx(ScrollToBottomButton, {}) })] }), _jsxs("div", { className: "shrink-0 bg-background", children: [_jsx(ThreadPrimitive.If, { running: false, children: _jsx("div", { className: "border-t border-border" }) }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingBar, {}) }), _jsx("div", { className: "mx-auto max-w-3xl px-4 py-4", children: _jsxs(ComposerPrimitive.Root, { className: cn("flex flex-col gap-2", "rounded-3xl border border-input", "bg-background shadow-sm", "px-4 py-2", "focus-within:border-primary/50 focus-within:shadow-md", "transition-all duration-300"), children: [_jsx(ComposerSubmitBridge, {}), _jsx(ComposerContextBadges, {}), _jsx(ComposerPrimitive.Attachments, { components: composerAttachmentComponents }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "flex items-center -space-x-1 shrink-0", children: [_jsx(ComposerPrimitive.AddAttachment, { asChild: true, children: _jsx(TooltipIconButton, { tooltip: "Attach file", variant: "ghost", className: "shrink-0", children: _jsx(Paperclip, { className: "size-5" }) }) }), _jsx(ContextPins, { showPinButton: showPinButton })] }), _jsx(ComposerPrimitive.Input, { autoFocus: true, placeholder: "Message Assistant...", rows: 1, className: cn("flex-1 bg-transparent", "py-2 text-base", "text-foreground outline-none", "placeholder:text-muted-foreground", "resize-none max-h-32") }), _jsx(ComposerActionButton, {})] })] }) })] })] })] }));
|
|
94
|
+
} }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingIndicator, {}) })] }) })] }), _jsx(ThreadPrimitive.If, { empty: false, children: _jsx(ScrollToBottomButton, {}) })] }), _jsxs("div", { className: "shrink-0 bg-background", children: [_jsx(ChatComposerBannerSlot, {}), _jsx(ThreadPrimitive.If, { running: false, children: _jsx("div", { className: "border-t border-border" }) }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingBar, {}) }), _jsx("div", { className: "mx-auto max-w-3xl px-4 py-4", children: _jsxs(ComposerPrimitive.Root, { className: cn("flex flex-col gap-2", "rounded-3xl border border-input", "bg-background shadow-sm", "px-4 py-2", "focus-within:border-primary/50 focus-within:shadow-md", "transition-all duration-300"), children: [_jsx(ComposerSubmitBridge, {}), _jsx(ComposerContextBadges, {}), _jsx(ComposerPrimitive.Attachments, { components: composerAttachmentComponents }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "flex items-center -space-x-1 shrink-0", children: [_jsx(ComposerPrimitive.AddAttachment, { asChild: true, children: _jsx(TooltipIconButton, { tooltip: "Attach file", variant: "ghost", className: "shrink-0", children: _jsx(Paperclip, { className: "size-5" }) }) }), _jsx(ContextPins, { showPinButton: showPinButton })] }), _jsx(ComposerPrimitive.Input, { autoFocus: true, placeholder: "Message Assistant...", rows: 1, className: cn("flex-1 bg-transparent", "py-2 text-base", "text-foreground outline-none", "placeholder:text-muted-foreground", "resize-none max-h-32") }), _jsx(ComposerActionButton, {})] })] }) })] })] })] }));
|
|
94
95
|
}
|
|
@@ -8,6 +8,7 @@ import { TooltipIconButton } from "./tooltip-icon-button.js";
|
|
|
8
8
|
import { ContextPins } from "./context-bar.js";
|
|
9
9
|
import { ComposerContextBadges, SentContextBadges } from "./context-badges.js";
|
|
10
10
|
import { ComposerSubmitBridge } from "./composer-submit-bridge.js";
|
|
11
|
+
import { ChatComposerBannerSlot, ChatLauncherBadgeSlot } from "./chat-slots.js";
|
|
11
12
|
import { MarkdownText } from "./markdown-text.js";
|
|
12
13
|
import { LoadingIndicator } from "./loading-indicator.js";
|
|
13
14
|
import { MessageTimestamp } from "./message-timestamp.js";
|
|
@@ -96,10 +97,10 @@ export function ChatBubble() {
|
|
|
96
97
|
return (_jsxs(_Fragment, { children: [!isOpen && (_jsx("div", { "aria-hidden": "true", className: cn("pointer-events-none fixed bottom-0 left-0 z-40 hidden md:block", "border-r border-sidebar-border", "bg-gradient-to-b from-sidebar/0 via-sidebar/88 to-sidebar/96", "supports-[backdrop-filter]:backdrop-blur"), style: {
|
|
97
98
|
width: isSidebarOpen ? sidebarWidth : RAIL_WIDTH,
|
|
98
99
|
height: 64,
|
|
99
|
-
} })), !isOpen && (_jsx("button", { type: "button", onClick: openBubble, className: cn("
|
|
100
|
+
} })), !isOpen && (_jsxs("div", { className: "fixed z-50 group", style: { left: CHAT_BUBBLE_INSET, bottom: CHAT_BUBBLE_INSET }, children: [_jsx("button", { type: "button", onClick: openBubble, className: cn("size-10 rounded-full", "bg-primary text-primary-foreground shadow-lg", "flex items-center justify-center", "hover:bg-primary/90 transition-all duration-200", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"), "aria-label": "Open chat", children: _jsx(MessageSquare, { className: "size-4" }) }), _jsx(ChatLauncherBadgeSlot, {})] })), isOpen && (_jsxs("div", { ref: panelRef, className: cn("fixed z-50", "rounded-2xl border border-border", "bg-background shadow-2xl", "flex flex-col overflow-hidden", "w-95 h-150"), style: dragPos
|
|
100
101
|
? { left: dragPos.x, top: dragPos.y }
|
|
101
102
|
: { left: CHAT_BUBBLE_INSET, bottom: CHAT_BUBBLE_INSET }, children: [_jsxs("div", { className: cn("flex items-center justify-between px-4 py-2.5 border-b border-border shrink-0", "cursor-grab active:cursor-grabbing select-none"), style: { touchAction: "none" }, onPointerDown: onHeaderPointerDown, onPointerMove: onHeaderPointerMove, onPointerUp: onHeaderPointerUp, onLostPointerCapture: onHeaderLostPointerCapture, children: [_jsxs("div", { className: "flex flex-col min-w-0", children: [_jsxs("div", { className: "flex items-center gap-1.5 text-sm", children: [_jsx(MessageSquare, { className: "size-3.5 text-primary shrink-0" }), _jsx("span", { className: "font-semibold text-foreground truncate", children: pageLabel })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: threadActive ? "Active thread" : "New conversation" })] }), _jsxs("div", { className: "flex items-center gap-0.5", children: [_jsx(TooltipIconButton, { tooltip: "New Thread", size: "icon", className: "size-7", onClick: startNewThread, children: _jsx(SquarePen, { className: "size-3.5" }) }), _jsx(TooltipIconButton, { tooltip: "Expand chat", size: "icon", className: "size-7", onClick: expandChat, children: _jsx(Maximize2, { className: "size-3.5" }) }), _jsx(TooltipIconButton, { tooltip: "Close", size: "icon", className: "size-7", onClick: handleClose, children: _jsx(X, { className: "size-4" }) })] })] }), _jsxs(ThreadPrimitive.Root, { className: "flex flex-col flex-1 overflow-hidden", children: [_jsxs("div", { className: "relative flex-1 overflow-hidden", children: [_jsxs(ThreadPrimitive.Viewport, { className: "absolute inset-0 overflow-y-auto", children: [_jsx(ThreadPrimitive.Empty, { children: _jsx("div", { className: "flex h-full items-center justify-center p-4", children: _jsx("p", { className: "text-sm text-muted-foreground text-center", children: "Ask the agent about this page" }) }) }), _jsx(ThreadPrimitive.If, { empty: false, children: _jsxs("div", { className: "px-4 pt-4", children: [_jsx(ThreadPrimitive.Messages, { components: {
|
|
102
103
|
UserMessage: BubbleUserMessage,
|
|
103
104
|
AssistantMessage: BubbleAssistantMessage,
|
|
104
|
-
} }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingIndicator, {}) })] }) })] }), _jsx(ThreadPrimitive.If, { empty: false, children: _jsx(BubbleScrollToBottomButton, {}) })] }),
|
|
105
|
+
} }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(LoadingIndicator, {}) })] }) })] }), _jsx(ThreadPrimitive.If, { empty: false, children: _jsx(BubbleScrollToBottomButton, {}) })] }), _jsxs("div", { className: "shrink-0 border-t border-border", children: [_jsx(ChatComposerBannerSlot, {}), _jsx("div", { className: "px-3 py-3", children: _jsxs(ComposerPrimitive.Root, { className: cn("flex flex-col gap-1", "rounded-2xl border border-input", "bg-background shadow-sm", "px-3 py-2", "focus-within:border-primary/50", "transition-all duration-200"), children: [_jsx(ComposerSubmitBridge, {}), _jsx(ComposerContextBadges, {}), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("div", { className: "flex items-center -space-x-1 shrink-0", children: [_jsx(ComposerPrimitive.AddAttachment, { asChild: true, children: _jsx(TooltipIconButton, { tooltip: "Attach file", size: "icon", className: "size-7 shrink-0", children: _jsx(Paperclip, { className: "size-3.5" }) }) }), _jsx(ContextPins, { compact: true })] }), _jsx(ComposerPrimitive.Input, { autoFocus: true, placeholder: "Message...", rows: 1, className: cn("flex-1 bg-transparent", "py-1 text-sm", "text-foreground outline-none", "placeholder:text-muted-foreground", "resize-none max-h-20") }), _jsx(ThreadPrimitive.If, { running: true, children: _jsx(ComposerPrimitive.Cancel, { asChild: true, children: _jsx(Button, { variant: "secondary", size: "icon", className: "rounded-full size-8 shrink-0", "aria-label": "Stop", children: _jsx(Square, { className: "size-3" }) }) }) }), _jsx(ThreadPrimitive.If, { running: false, children: _jsx(ComposerPrimitive.Send, { asChild: true, children: _jsx(Button, { size: "icon", className: "rounded-full size-8 shrink-0", "aria-label": "Send", children: _jsx(ArrowUp, { className: "size-4" }) }) }) })] })] }) })] })] })] }))] }));
|
|
105
106
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat extension slots — module-injectable UI anchored to the chat chrome.
|
|
3
|
+
*
|
|
4
|
+
* Modules (via ``bootstrapShell``) sometimes need to render inside the
|
|
5
|
+
* chat surfaces the shell owns — e.g. a background-task progress strip
|
|
6
|
+
* pinned above the composer, or an activity badge on the collapsed chat
|
|
7
|
+
* launcher. Threading those through props would couple the shell to
|
|
8
|
+
* feature modules, so this is a tiny registry instead: a module calls
|
|
9
|
+
* :func:`registerChatSlots` once (import time or ``useInit``) and the
|
|
10
|
+
* shell's chat components render the slots wherever they belong.
|
|
11
|
+
*
|
|
12
|
+
* Render points:
|
|
13
|
+
* - ``composerBanner`` — directly above the composer in BOTH the full
|
|
14
|
+
* chat (``ChatContent``) and the floating bubble panel. It renders
|
|
15
|
+
* inside a fixed (non-scrolling) footer, so it never scrolls away
|
|
16
|
+
* with the thread.
|
|
17
|
+
* - ``launcherBadge`` — inside the collapsed chat-bubble launcher's
|
|
18
|
+
* wrapper (a positioned ``group`` container around the round button),
|
|
19
|
+
* so a badge can position itself absolutely over the button and use
|
|
20
|
+
* ``group-hover:`` styles for a hover flyout.
|
|
21
|
+
*/
|
|
22
|
+
import type { ComponentType } from "react";
|
|
23
|
+
interface ChatSlotsState {
|
|
24
|
+
composerBanner: ComponentType | null;
|
|
25
|
+
launcherBadge: ComponentType | null;
|
|
26
|
+
}
|
|
27
|
+
export declare const useChatSlotsStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ChatSlotsState>>;
|
|
28
|
+
/**
|
|
29
|
+
* Register chat slot components. Later calls overwrite only the keys
|
|
30
|
+
* they pass, so independent modules can each claim a different slot.
|
|
31
|
+
* Explicit ``null`` clears a slot; ``undefined`` values are ignored so
|
|
32
|
+
* an optional-spread caller can't corrupt the state shape.
|
|
33
|
+
*/
|
|
34
|
+
export declare function registerChatSlots(slots: Partial<ChatSlotsState>): void;
|
|
35
|
+
export declare function ChatComposerBannerSlot(): import("react/jsx-runtime").JSX.Element | null;
|
|
36
|
+
export declare function ChatLauncherBadgeSlot(): import("react/jsx-runtime").JSX.Element | null;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { create } from "zustand";
|
|
3
|
+
export const useChatSlotsStore = create(() => ({
|
|
4
|
+
composerBanner: null,
|
|
5
|
+
launcherBadge: null,
|
|
6
|
+
}));
|
|
7
|
+
/**
|
|
8
|
+
* Register chat slot components. Later calls overwrite only the keys
|
|
9
|
+
* they pass, so independent modules can each claim a different slot.
|
|
10
|
+
* Explicit ``null`` clears a slot; ``undefined`` values are ignored so
|
|
11
|
+
* an optional-spread caller can't corrupt the state shape.
|
|
12
|
+
*/
|
|
13
|
+
export function registerChatSlots(slots) {
|
|
14
|
+
const next = {};
|
|
15
|
+
if (slots.composerBanner !== undefined)
|
|
16
|
+
next.composerBanner = slots.composerBanner;
|
|
17
|
+
if (slots.launcherBadge !== undefined)
|
|
18
|
+
next.launcherBadge = slots.launcherBadge;
|
|
19
|
+
useChatSlotsStore.setState(next);
|
|
20
|
+
}
|
|
21
|
+
export function ChatComposerBannerSlot() {
|
|
22
|
+
const Banner = useChatSlotsStore((s) => s.composerBanner);
|
|
23
|
+
return Banner ? _jsx(Banner, {}) : null;
|
|
24
|
+
}
|
|
25
|
+
export function ChatLauncherBadgeSlot() {
|
|
26
|
+
const Badge = useChatSlotsStore((s) => s.launcherBadge);
|
|
27
|
+
return Badge ? _jsx(Badge, {}) : null;
|
|
28
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type { AGUIChatConversationFactoryArgs, AGUIHistoryAdapterFactory, } from
|
|
|
8
8
|
export { ChatContent, DEFAULT_STARTER_SUGGESTIONS } from "./components/assistant-chat.js";
|
|
9
9
|
export type { ChatContentProps } from "./components/assistant-chat.js";
|
|
10
10
|
export { ChatBubble } from "./components/chat-bubble.js";
|
|
11
|
+
export { registerChatSlots, useChatSlotsStore, ChatComposerBannerSlot, ChatLauncherBadgeSlot, } from "./components/chat-slots.js";
|
|
11
12
|
export { ChatHeader } from "./components/chat-header.js";
|
|
12
13
|
export { ComposerAttachment, UserMessageAttachment, userAttachmentComponents, composerAttachmentComponents, } from "./components/chat-attachments.js";
|
|
13
14
|
export { ShowDocumentToolUI } from "./components/show-document-tool-ui.js";
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { ClientToolExecutor } from "./components/client-tool-executor.js";
|
|
|
7
7
|
export { AGUIRuntimeProvider, useAGUIAdapter } from "./components/ag-ui-runtime-provider.js";
|
|
8
8
|
export { ChatContent, DEFAULT_STARTER_SUGGESTIONS } from "./components/assistant-chat.js";
|
|
9
9
|
export { ChatBubble } from "./components/chat-bubble.js";
|
|
10
|
+
export { registerChatSlots, useChatSlotsStore, ChatComposerBannerSlot, ChatLauncherBadgeSlot, } from "./components/chat-slots.js";
|
|
10
11
|
export { ChatHeader } from "./components/chat-header.js";
|
|
11
12
|
export { ComposerAttachment, UserMessageAttachment, userAttachmentComponents, composerAttachmentComponents, } from "./components/chat-attachments.js";
|
|
12
13
|
export { ShowDocumentToolUI } from "./components/show-document-tool-ui.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iloveagents/foundry-web-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"tailwind-merge": "^3.5.0",
|
|
54
54
|
"react-markdown": "^10.0.0",
|
|
55
55
|
"remark-gfm": "^4.0.0",
|
|
56
|
-
"@iloveagents/foundry-agent": "^0.
|
|
57
|
-
"@iloveagents/foundry-web-primitives": "^0.
|
|
56
|
+
"@iloveagents/foundry-agent": "^0.6.0",
|
|
57
|
+
"@iloveagents/foundry-web-primitives": "^0.6.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@ag-ui/client": "^0.0.52",
|