@meshagent/meshagent-tailwind 0.38.1 → 0.38.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/CHANGELOG.md +12 -0
- package/dist/cjs/Chat.d.ts +11 -3
- package/dist/cjs/Chat.js +376 -29
- package/dist/cjs/ChatBotView.d.ts +29 -0
- package/dist/cjs/ChatBotView.js +491 -0
- package/dist/cjs/ChatInput.d.ts +12 -3
- package/dist/cjs/ChatInput.js +143 -44
- package/dist/cjs/ChatThread.d.ts +17 -3
- package/dist/cjs/ChatThread.js +646 -90
- package/dist/cjs/ChatTypingIndicator.d.ts +12 -5
- package/dist/cjs/ChatTypingIndicator.js +104 -13
- package/dist/cjs/FileUploader.d.ts +3 -2
- package/dist/cjs/FileUploader.js +35 -11
- package/dist/cjs/UploadPill.d.ts +2 -2
- package/dist/cjs/UploadPill.js +70 -32
- package/dist/cjs/chat-hooks.d.ts +38 -0
- package/dist/cjs/chat-hooks.js +390 -0
- package/dist/cjs/chat-message.d.ts +11 -0
- package/dist/cjs/chat-message.js +33 -0
- package/dist/cjs/components/ui/button.d.ts +1 -1
- package/dist/cjs/conversation-descriptor.d.ts +59 -0
- package/dist/cjs/conversation-descriptor.js +300 -0
- package/dist/cjs/file-attachment.d.ts +45 -0
- package/dist/cjs/file-attachment.js +171 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/multi-thread-view.d.ts +18 -0
- package/dist/cjs/multi-thread-view.js +88 -0
- package/dist/cjs/tools/ui-toolkit.d.ts +1 -1
- package/dist/cjs/tools/ui-toolkit.js +2 -1
- package/dist/esm/Chat.d.ts +11 -3
- package/dist/esm/Chat.js +378 -31
- package/dist/esm/ChatBotView.d.ts +29 -0
- package/dist/esm/ChatBotView.js +486 -0
- package/dist/esm/ChatInput.d.ts +12 -3
- package/dist/esm/ChatInput.js +143 -34
- package/dist/esm/ChatThread.d.ts +17 -3
- package/dist/esm/ChatThread.js +648 -92
- package/dist/esm/ChatTypingIndicator.d.ts +12 -5
- package/dist/esm/ChatTypingIndicator.js +94 -13
- package/dist/esm/FileUploader.d.ts +3 -2
- package/dist/esm/FileUploader.js +26 -12
- package/dist/esm/UploadPill.d.ts +2 -2
- package/dist/esm/UploadPill.js +60 -32
- package/dist/esm/chat-hooks.d.ts +38 -0
- package/dist/esm/chat-hooks.js +372 -0
- package/dist/esm/chat-message.d.ts +11 -0
- package/dist/esm/chat-message.js +13 -0
- package/dist/esm/components/ui/button.d.ts +1 -1
- package/dist/esm/conversation-descriptor.d.ts +59 -0
- package/dist/esm/conversation-descriptor.js +280 -0
- package/dist/esm/file-attachment.d.ts +45 -0
- package/dist/esm/file-attachment.js +151 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/multi-thread-view.d.ts +18 -0
- package/dist/esm/multi-thread-view.js +68 -0
- package/dist/esm/tools/ui-toolkit.d.ts +1 -1
- package/dist/esm/tools/ui-toolkit.js +2 -1
- package/dist/index.css +1 -1
- package/package.json +3 -3
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { RoomClient } from
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { RoomClient } from "@meshagent/meshagent";
|
|
3
3
|
export interface ChatTypingIndicatorProps {
|
|
4
|
-
room
|
|
5
|
-
path
|
|
4
|
+
room?: RoomClient | null;
|
|
5
|
+
path?: string;
|
|
6
|
+
typing?: boolean;
|
|
7
|
+
thinking?: boolean;
|
|
8
|
+
statusText?: string | null;
|
|
9
|
+
startedAt?: Date | null;
|
|
10
|
+
onCancel?: () => void;
|
|
11
|
+
showCancelButton?: boolean;
|
|
12
|
+
cancelEnabled?: boolean;
|
|
6
13
|
}
|
|
7
|
-
export declare function ChatTypingIndicator({ room, path }: ChatTypingIndicatorProps): React.ReactElement | null;
|
|
14
|
+
export declare function ChatTypingIndicator({ room, path, typing, thinking, statusText, startedAt, onCancel, showCancelButton, cancelEnabled, }: ChatTypingIndicatorProps): React.ReactElement | null;
|
|
@@ -1,28 +1,109 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
2
3
|
import { useRoomIndicators } from "@meshagent/meshagent-react";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { LoaderCircle, X } from "lucide-react";
|
|
5
|
+
import { formatThreadStatusText } from "./chat-hooks";
|
|
6
|
+
import { cn } from "./lib/utils";
|
|
7
|
+
function useStatusLabel(text, startedAt) {
|
|
8
|
+
const normalizedText = text?.trim() ?? "";
|
|
9
|
+
const [tick, setTick] = React.useState(0);
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
if (normalizedText === "" || !(startedAt instanceof Date) || Number.isNaN(startedAt.getTime())) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const timer = window.setInterval(() => {
|
|
15
|
+
setTick((current) => current + 1);
|
|
16
|
+
}, 1e3);
|
|
17
|
+
return () => {
|
|
18
|
+
window.clearInterval(timer);
|
|
19
|
+
};
|
|
20
|
+
}, [normalizedText, startedAt]);
|
|
21
|
+
if (normalizedText === "") {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
void tick;
|
|
25
|
+
return formatThreadStatusText(normalizedText, startedAt);
|
|
26
|
+
}
|
|
27
|
+
function ProcessingStatusRow({
|
|
28
|
+
text,
|
|
29
|
+
onCancel,
|
|
30
|
+
showCancelButton = false,
|
|
31
|
+
cancelEnabled = true
|
|
32
|
+
}) {
|
|
33
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-full border border-border/70 bg-background/90 px-3 py-2 shadow-sm backdrop-blur", children: [
|
|
34
|
+
showCancelButton ? /* @__PURE__ */ jsxs(
|
|
35
|
+
"button",
|
|
36
|
+
{
|
|
37
|
+
type: "button",
|
|
38
|
+
onClick: cancelEnabled ? onCancel : void 0,
|
|
39
|
+
disabled: !cancelEnabled,
|
|
40
|
+
title: cancelEnabled ? "Stop" : "Cancelling",
|
|
41
|
+
className: cn(
|
|
42
|
+
"relative inline-flex h-6 w-6 items-center justify-center rounded-full transition-opacity",
|
|
43
|
+
cancelEnabled ? "cursor-pointer" : "cursor-default opacity-55"
|
|
44
|
+
),
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ jsx(LoaderCircle, { className: "absolute h-6 w-6 animate-spin text-muted-foreground" }),
|
|
47
|
+
/* @__PURE__ */ jsx("span", { className: "relative inline-flex h-4 w-4 items-center justify-center rounded-full bg-foreground text-background", children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3" }) })
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
) : /* @__PURE__ */ jsx(LoaderCircle, { className: "h-4 w-4 animate-spin text-muted-foreground" }),
|
|
51
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: text })
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
function ChatTypingIndicator({
|
|
55
|
+
room = null,
|
|
56
|
+
path = "",
|
|
57
|
+
typing,
|
|
58
|
+
thinking,
|
|
59
|
+
statusText,
|
|
60
|
+
startedAt,
|
|
61
|
+
onCancel,
|
|
62
|
+
showCancelButton = false,
|
|
63
|
+
cancelEnabled = true
|
|
64
|
+
}) {
|
|
65
|
+
const roomIndicators = useRoomIndicators({ room, path });
|
|
66
|
+
const resolvedTyping = typing ?? roomIndicators.typing;
|
|
67
|
+
const resolvedThinking = thinking ?? roomIndicators.thinking;
|
|
68
|
+
const resolvedStatusText = useStatusLabel(
|
|
69
|
+
statusText?.trim() ? statusText : resolvedThinking ? "Thinking" : null,
|
|
70
|
+
startedAt
|
|
71
|
+
);
|
|
72
|
+
if (resolvedStatusText) {
|
|
73
|
+
return /* @__PURE__ */ jsx(
|
|
74
|
+
ProcessingStatusRow,
|
|
75
|
+
{
|
|
76
|
+
text: resolvedStatusText,
|
|
77
|
+
onCancel,
|
|
78
|
+
showCancelButton,
|
|
79
|
+
cancelEnabled
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
if (!resolvedTyping) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-full border border-border/70 bg-background/90 px-3 py-2 shadow-sm backdrop-blur", children: [
|
|
87
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-end gap-1", children: [0, 1, 2].map((index) => /* @__PURE__ */ jsx(
|
|
7
88
|
"span",
|
|
8
89
|
{
|
|
9
|
-
className:
|
|
90
|
+
className: "inline-block h-2 w-2 rounded-full bg-muted-foreground",
|
|
10
91
|
style: {
|
|
11
|
-
animation: "
|
|
92
|
+
animation: "chatTypingBounce 0.6s ease-in-out infinite",
|
|
12
93
|
animationDelay: `${index * 0.2}s`
|
|
13
94
|
}
|
|
14
95
|
},
|
|
15
96
|
index
|
|
16
|
-
)),
|
|
97
|
+
)) }),
|
|
98
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "Typing" }),
|
|
17
99
|
/* @__PURE__ */ jsx("style", { children: `
|
|
18
|
-
@keyframes
|
|
19
|
-
0%, 100% { transform: translateY(0); }
|
|
20
|
-
50% { transform: translateY(-4px); }
|
|
100
|
+
@keyframes chatTypingBounce {
|
|
101
|
+
0%, 100% { transform: translateY(0); opacity: 0.55; }
|
|
102
|
+
50% { transform: translateY(-4px); opacity: 1; }
|
|
21
103
|
}
|
|
22
|
-
|
|
23
|
-
] })
|
|
104
|
+
` })
|
|
105
|
+
] });
|
|
24
106
|
}
|
|
25
|
-
;
|
|
26
107
|
export {
|
|
27
108
|
ChatTypingIndicator
|
|
28
109
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import * as React from "react";
|
|
2
2
|
export interface FileUploaderProps {
|
|
3
3
|
onFilesSelected?: (files: File[]) => void;
|
|
4
4
|
accept?: string;
|
|
5
|
+
disabled?: boolean;
|
|
5
6
|
}
|
|
6
|
-
export declare function FileUploader({ onFilesSelected, accept }: FileUploaderProps): React.ReactElement;
|
|
7
|
+
export declare function FileUploader({ onFilesSelected, accept, disabled, }: FileUploaderProps): React.ReactElement;
|
package/dist/esm/FileUploader.js
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { Paperclip } from "lucide-react";
|
|
4
4
|
import { Button } from "./components/ui/button";
|
|
5
|
-
function FileUploader({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
function FileUploader({
|
|
6
|
+
onFilesSelected,
|
|
7
|
+
accept = "",
|
|
8
|
+
disabled = false
|
|
9
|
+
}) {
|
|
10
|
+
const inputRef = React.useRef(null);
|
|
11
|
+
const handleButtonClick = React.useCallback(() => {
|
|
12
|
+
if (disabled) {
|
|
10
13
|
return;
|
|
11
14
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
inputRef.current?.click();
|
|
16
|
+
}, [disabled]);
|
|
17
|
+
const handleFileChange = React.useCallback((event) => {
|
|
18
|
+
if (!event.target.files) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const files = Array.from(event.target.files);
|
|
22
|
+
onFilesSelected?.(files);
|
|
23
|
+
event.target.value = "";
|
|
24
|
+
}, [onFilesSelected]);
|
|
25
|
+
return /* @__PURE__ */ jsxs("div", { className: "shrink-0", children: [
|
|
16
26
|
/* @__PURE__ */ jsx(
|
|
17
27
|
"input",
|
|
18
28
|
{
|
|
@@ -20,6 +30,7 @@ function FileUploader({ onFilesSelected, accept = "" }) {
|
|
|
20
30
|
type: "file",
|
|
21
31
|
multiple: true,
|
|
22
32
|
accept,
|
|
33
|
+
disabled,
|
|
23
34
|
className: "hidden",
|
|
24
35
|
onChange: handleFileChange
|
|
25
36
|
}
|
|
@@ -27,11 +38,14 @@ function FileUploader({ onFilesSelected, accept = "" }) {
|
|
|
27
38
|
/* @__PURE__ */ jsx(
|
|
28
39
|
Button,
|
|
29
40
|
{
|
|
41
|
+
type: "button",
|
|
30
42
|
variant: "ghost",
|
|
31
43
|
size: "icon",
|
|
32
44
|
"aria-label": "Attach file",
|
|
45
|
+
className: "h-9 w-9 rounded-md",
|
|
46
|
+
disabled,
|
|
33
47
|
onClick: handleButtonClick,
|
|
34
|
-
children: /* @__PURE__ */ jsx(
|
|
48
|
+
children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
|
|
35
49
|
}
|
|
36
50
|
)
|
|
37
51
|
] });
|
package/dist/esm/UploadPill.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { FileUpload } from "
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type FileUpload } from "./file-attachment";
|
|
3
3
|
export interface UploadPillProps {
|
|
4
4
|
attachment: FileUpload;
|
|
5
5
|
onCancel: (attachment: FileUpload) => void;
|
package/dist/esm/UploadPill.js
CHANGED
|
@@ -1,39 +1,67 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { FileUp, LoaderCircle, TriangleAlert, X } from "lucide-react";
|
|
3
4
|
import { Progress } from "./components/ui/progress";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
import { UploadStatus } from "./file-attachment";
|
|
6
|
+
import { cn } from "./lib/utils";
|
|
7
|
+
function measureUploadProgress(attachment) {
|
|
8
|
+
if (attachment.size <= 0) {
|
|
9
|
+
return attachment.status === UploadStatus.Completed ? 100 : 0;
|
|
10
|
+
}
|
|
11
|
+
return Math.max(0, Math.min(100, Math.round(attachment.bytesUploaded * 100 / attachment.size)));
|
|
12
|
+
}
|
|
13
|
+
function useUploadState(attachment) {
|
|
14
|
+
const [progress, setProgress] = React.useState(() => measureUploadProgress(attachment));
|
|
15
|
+
const [status, setStatus] = React.useState(attachment.status);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
const updateState = () => {
|
|
18
|
+
setStatus(attachment.status);
|
|
19
|
+
setProgress(measureUploadProgress(attachment));
|
|
20
|
+
};
|
|
21
|
+
updateState();
|
|
22
|
+
attachment.on("change", updateState);
|
|
23
|
+
return () => {
|
|
24
|
+
attachment.off("change", updateState);
|
|
25
|
+
};
|
|
14
26
|
}, [attachment]);
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
className: "
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
return { progress, status };
|
|
28
|
+
}
|
|
29
|
+
function UploadPill({ attachment, onCancel }) {
|
|
30
|
+
const { progress, status } = useUploadState(attachment);
|
|
31
|
+
const handleCancel = React.useCallback(() => {
|
|
32
|
+
onCancel(attachment);
|
|
33
|
+
}, [attachment, onCancel]);
|
|
34
|
+
return /* @__PURE__ */ jsxs(
|
|
35
|
+
"div",
|
|
36
|
+
{
|
|
37
|
+
className: cn(
|
|
38
|
+
"relative inline-flex max-w-full items-center gap-2 overflow-hidden rounded-md border bg-muted/60 pl-3 pr-2 py-2 text-sm",
|
|
39
|
+
status === UploadStatus.Failed && "border-destructive/40 bg-destructive/5 text-destructive"
|
|
40
|
+
),
|
|
41
|
+
children: [
|
|
42
|
+
status === UploadStatus.Failed ? /* @__PURE__ */ jsx(TriangleAlert, { className: "h-4 w-4 shrink-0" }) : status === UploadStatus.Completed ? /* @__PURE__ */ jsx(FileUp, { className: "h-4 w-4 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ jsx(LoaderCircle, { className: "h-4 w-4 shrink-0 animate-spin text-muted-foreground" }),
|
|
43
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium leading-none", children: attachment.filename }),
|
|
44
|
+
/* @__PURE__ */ jsx(
|
|
45
|
+
"button",
|
|
46
|
+
{
|
|
47
|
+
type: "button",
|
|
48
|
+
onClick: handleCancel,
|
|
49
|
+
"aria-label": "Remove attachment",
|
|
50
|
+
className: "rounded-md p-1 transition-colors hover:bg-foreground/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
51
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
52
|
+
}
|
|
53
|
+
),
|
|
54
|
+
/* @__PURE__ */ jsx(
|
|
55
|
+
Progress,
|
|
56
|
+
{
|
|
57
|
+
value: status === UploadStatus.Completed ? 100 : progress,
|
|
58
|
+
className: "absolute inset-x-0 bottom-0 h-0.5 rounded-none bg-border/60"
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
);
|
|
35
64
|
}
|
|
36
|
-
;
|
|
37
65
|
export {
|
|
38
66
|
UploadPill
|
|
39
67
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Element, MeshDocument, Participant, RemoteParticipant, RoomClient } from "@meshagent/meshagent";
|
|
2
|
+
import { ChatMessage } from "./chat-message";
|
|
3
|
+
import { type FileUpload } from "./file-attachment";
|
|
4
|
+
export interface UseChatThreadProps {
|
|
5
|
+
room: RoomClient;
|
|
6
|
+
path: string;
|
|
7
|
+
participants?: Participant[];
|
|
8
|
+
participantNames?: string[];
|
|
9
|
+
includeLocalParticipant?: boolean;
|
|
10
|
+
initialMessage?: ChatMessage;
|
|
11
|
+
agentName?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface UseChatThreadResult {
|
|
14
|
+
document: MeshDocument | null;
|
|
15
|
+
messages: Element[];
|
|
16
|
+
sendMessage: (message: ChatMessage) => void;
|
|
17
|
+
selectAttachments: (files: File[]) => void;
|
|
18
|
+
attachments: FileUpload[];
|
|
19
|
+
setAttachments: (attachments: FileUpload[]) => void;
|
|
20
|
+
schemaFileExists: boolean;
|
|
21
|
+
onlineParticipants: RemoteParticipant[];
|
|
22
|
+
localParticipantName: string;
|
|
23
|
+
cancelRequest?: () => void;
|
|
24
|
+
}
|
|
25
|
+
export interface ThreadStatus {
|
|
26
|
+
text: string | null;
|
|
27
|
+
mode: string | null;
|
|
28
|
+
startedAt: Date | null;
|
|
29
|
+
supportsAgentMessages: boolean;
|
|
30
|
+
}
|
|
31
|
+
export interface UseThreadStatusProps {
|
|
32
|
+
room: RoomClient;
|
|
33
|
+
path: string;
|
|
34
|
+
agentName?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function formatThreadStatusText(text: string, startedAt?: Date | null): string;
|
|
37
|
+
export declare function useChatThread({ room, path, participants, participantNames, initialMessage, includeLocalParticipant, agentName, }: UseChatThreadProps): UseChatThreadResult;
|
|
38
|
+
export declare function useThreadStatus({ room, path, agentName }: UseThreadStatusProps): ThreadStatus;
|