@meshagent/meshagent-tailwind 0.38.2 → 0.38.4

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/Chat.d.ts +11 -3
  3. package/dist/cjs/Chat.js +376 -29
  4. package/dist/cjs/ChatBotView.d.ts +29 -0
  5. package/dist/cjs/ChatBotView.js +491 -0
  6. package/dist/cjs/ChatInput.d.ts +12 -3
  7. package/dist/cjs/ChatInput.js +143 -44
  8. package/dist/cjs/ChatThread.d.ts +17 -3
  9. package/dist/cjs/ChatThread.js +646 -90
  10. package/dist/cjs/ChatTypingIndicator.d.ts +12 -5
  11. package/dist/cjs/ChatTypingIndicator.js +104 -13
  12. package/dist/cjs/FileUploader.d.ts +3 -2
  13. package/dist/cjs/FileUploader.js +35 -11
  14. package/dist/cjs/UploadPill.d.ts +2 -2
  15. package/dist/cjs/UploadPill.js +70 -32
  16. package/dist/cjs/chat-hooks.d.ts +38 -0
  17. package/dist/cjs/chat-hooks.js +390 -0
  18. package/dist/cjs/chat-message.d.ts +11 -0
  19. package/dist/cjs/chat-message.js +33 -0
  20. package/dist/cjs/components/ui/button.d.ts +1 -1
  21. package/dist/cjs/conversation-descriptor.d.ts +59 -0
  22. package/dist/cjs/conversation-descriptor.js +300 -0
  23. package/dist/cjs/file-attachment.d.ts +45 -0
  24. package/dist/cjs/file-attachment.js +171 -0
  25. package/dist/cjs/index.d.ts +5 -0
  26. package/dist/cjs/index.js +5 -0
  27. package/dist/cjs/multi-thread-view.d.ts +18 -0
  28. package/dist/cjs/multi-thread-view.js +88 -0
  29. package/dist/cjs/tools/ui-toolkit.d.ts +1 -1
  30. package/dist/cjs/tools/ui-toolkit.js +2 -1
  31. package/dist/esm/Chat.d.ts +11 -3
  32. package/dist/esm/Chat.js +378 -31
  33. package/dist/esm/ChatBotView.d.ts +29 -0
  34. package/dist/esm/ChatBotView.js +486 -0
  35. package/dist/esm/ChatInput.d.ts +12 -3
  36. package/dist/esm/ChatInput.js +143 -34
  37. package/dist/esm/ChatThread.d.ts +17 -3
  38. package/dist/esm/ChatThread.js +648 -92
  39. package/dist/esm/ChatTypingIndicator.d.ts +12 -5
  40. package/dist/esm/ChatTypingIndicator.js +94 -13
  41. package/dist/esm/FileUploader.d.ts +3 -2
  42. package/dist/esm/FileUploader.js +26 -12
  43. package/dist/esm/UploadPill.d.ts +2 -2
  44. package/dist/esm/UploadPill.js +60 -32
  45. package/dist/esm/chat-hooks.d.ts +38 -0
  46. package/dist/esm/chat-hooks.js +372 -0
  47. package/dist/esm/chat-message.d.ts +11 -0
  48. package/dist/esm/chat-message.js +13 -0
  49. package/dist/esm/components/ui/button.d.ts +1 -1
  50. package/dist/esm/conversation-descriptor.d.ts +59 -0
  51. package/dist/esm/conversation-descriptor.js +280 -0
  52. package/dist/esm/file-attachment.d.ts +45 -0
  53. package/dist/esm/file-attachment.js +151 -0
  54. package/dist/esm/index.d.ts +5 -0
  55. package/dist/esm/index.js +5 -0
  56. package/dist/esm/multi-thread-view.d.ts +18 -0
  57. package/dist/esm/multi-thread-view.js +68 -0
  58. package/dist/esm/tools/ui-toolkit.d.ts +1 -1
  59. package/dist/esm/tools/ui-toolkit.js +2 -1
  60. package/dist/index.css +1 -1
  61. package/package.json +3 -3
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
  var ChatInput_exports = {};
30
20
  __export(ChatInput_exports, {
@@ -32,13 +22,83 @@ __export(ChatInput_exports, {
32
22
  });
33
23
  module.exports = __toCommonJS(ChatInput_exports);
34
24
  var import_jsx_runtime = require("react/jsx-runtime");
35
- var import_react = __toESM(require("react"));
25
+ var import_react = require("react");
26
+ var import_lucide_react = require("lucide-react");
36
27
  var import_uuid = require("uuid");
37
- var import_meshagent_react = require("@meshagent/meshagent-react");
28
+ var import_chat_message = require("./chat-message");
38
29
  var import_button = require("./components/ui/button");
39
30
  var import_textarea = require("./components/ui/textarea");
40
31
  var import_FileUploader = require("./FileUploader");
41
32
  var import_UploadPill = require("./UploadPill");
33
+ var import_file_attachment = require("./file-attachment");
34
+ var import_utils = require("./lib/utils");
35
+ function useAttachmentStatusVersion(attachments) {
36
+ const [version, setVersion] = (0, import_react.useState)(0);
37
+ (0, import_react.useEffect)(() => {
38
+ const handleChange = () => {
39
+ setVersion((currentVersion) => currentVersion + 1);
40
+ };
41
+ for (const attachment of attachments) {
42
+ attachment.on("change", handleChange);
43
+ }
44
+ return () => {
45
+ for (const attachment of attachments) {
46
+ attachment.off("change", handleChange);
47
+ }
48
+ };
49
+ }, [attachments]);
50
+ return version;
51
+ }
52
+ function useAutoResizingTextarea(textareaRef, value) {
53
+ (0, import_react.useEffect)(() => {
54
+ const element = textareaRef.current;
55
+ if (!element) {
56
+ return;
57
+ }
58
+ if (value === "") {
59
+ element.style.height = "20px";
60
+ } else {
61
+ element.style.height = "0px";
62
+ element.style.height = `${Math.max(20, Math.min(element.scrollHeight, 160))}px`;
63
+ }
64
+ }, [textareaRef, value]);
65
+ }
66
+ function ComposerActionButton({
67
+ onClick,
68
+ disabled = false,
69
+ showCancelButton = false
70
+ }) {
71
+ if (showCancelButton) {
72
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
73
+ import_button.Button,
74
+ {
75
+ type: "button",
76
+ size: "icon",
77
+ variant: "ghost",
78
+ className: (0, import_utils.cn)("relative size-9 rounded-full", disabled && "opacity-55"),
79
+ disabled,
80
+ onClick,
81
+ title: disabled ? "Cancelling" : "Stop",
82
+ children: [
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.LoaderCircle, { className: "absolute h-9 w-9 animate-spin text-muted-foreground" }),
84
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "relative inline-flex h-5 w-5 items-center justify-center rounded-full bg-foreground text-background", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.X, { className: "h-3 w-3" }) })
85
+ ]
86
+ }
87
+ );
88
+ }
89
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
90
+ import_button.Button,
91
+ {
92
+ type: "button",
93
+ size: "icon",
94
+ className: "size-9 rounded-full shadow-xs",
95
+ disabled,
96
+ onClick,
97
+ title: "Send",
98
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ArrowUp, { className: "h-4 w-4" })
99
+ }
100
+ );
101
+ }
42
102
  function ChatInput({
43
103
  onSubmit,
44
104
  onFilesSelected,
@@ -46,59 +106,98 @@ function ChatInput({
46
106
  setAttachments,
47
107
  onTextChange,
48
108
  onCancelRequest,
49
- showCancelButton
109
+ showCancelButton = false,
110
+ placeholder = "Message the room",
111
+ disabled = false,
112
+ clearOnSubmit = true,
113
+ autoFocus = true,
114
+ value: controlledValue,
115
+ defaultValue = "",
116
+ onValueChange
50
117
  }) {
51
- const [value, setValue] = import_react.default.useState("");
118
+ const [uncontrolledValue, setUncontrolledValue] = (0, import_react.useState)(defaultValue);
119
+ const textareaRef = (0, import_react.useRef)(null);
120
+ const value = controlledValue ?? uncontrolledValue;
121
+ const attachmentStatusVersion = useAttachmentStatusVersion(attachments);
122
+ const setValue = (0, import_react.useCallback)((nextValue) => {
123
+ if (controlledValue === void 0) {
124
+ setUncontrolledValue(nextValue);
125
+ }
126
+ onValueChange?.(nextValue);
127
+ onTextChange?.(nextValue);
128
+ }, [controlledValue, onTextChange, onValueChange]);
129
+ useAutoResizingTextarea(textareaRef, value);
130
+ const allAttachmentsUploaded = (0, import_react.useMemo)(
131
+ () => attachments.every((attachment) => attachment.status === import_file_attachment.UploadStatus.Completed),
132
+ [attachmentStatusVersion, attachments]
133
+ );
134
+ const hasDraft = value.trim() !== "" || attachments.length > 0;
135
+ const canSend = !disabled && hasDraft && allAttachmentsUploaded;
52
136
  const handleSend = (0, import_react.useCallback)(() => {
53
- const trimmed2 = value.trim();
54
- if (attachments.length === 0 && !trimmed2) {
137
+ const trimmed = value.trim();
138
+ if (!canSend) {
55
139
  return;
56
140
  }
57
- onSubmit(new import_meshagent_react.ChatMessage({
141
+ void onSubmit(new import_chat_message.ChatMessage({
58
142
  id: (0, import_uuid.v4)(),
59
- text: trimmed2,
60
- attachments: attachments.map((file) => file.path)
143
+ text: trimmed,
144
+ attachments: attachments.map((attachment) => attachment.path)
61
145
  }));
146
+ if (!clearOnSubmit) {
147
+ return;
148
+ }
62
149
  setValue("");
63
150
  setAttachments([]);
64
- }, [value, onSubmit, attachments]);
65
- const onKeyDown = (e) => {
66
- if (e.key === "Enter" && !e.shiftKey) {
67
- e.preventDefault();
151
+ }, [attachments, canSend, clearOnSubmit, onSubmit, setAttachments, setValue, value]);
152
+ const handleKeyDown = (0, import_react.useCallback)((event) => {
153
+ if (disabled) {
154
+ return;
155
+ }
156
+ if (event.key === "Enter" && !event.shiftKey) {
157
+ event.preventDefault();
158
+ if (showCancelButton) {
159
+ onCancelRequest?.();
160
+ return;
161
+ }
68
162
  handleSend();
69
163
  }
70
- };
164
+ }, [disabled, handleSend, onCancelRequest, showCancelButton]);
165
+ const handleChange = (0, import_react.useCallback)((event) => {
166
+ const nextValue = event.currentTarget.value;
167
+ setValue(nextValue);
168
+ }, [setValue]);
71
169
  const cancelAttachment = (0, import_react.useCallback)((attachment) => {
72
- setAttachments(attachments.filter((f) => f.path !== attachment.path));
73
- }, [attachments, setAttachments]);
74
- const _onChange = (0, import_react.useCallback)((e) => {
75
- setValue(e.currentTarget.value);
76
- onTextChange?.(e.currentTarget.value);
77
- }, [onTextChange]);
78
- const trimmed = value.trim();
79
- const disabled = !trimmed && attachments.length === 0;
80
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "border-t py-3 gap-3 flex flex-col", children: [
81
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-0 gap-2 flex-wrap", children: attachments.map((attachment) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
170
+ if (disabled) {
171
+ return;
172
+ }
173
+ setAttachments(attachments.filter((currentAttachment) => currentAttachment !== attachment));
174
+ }, [attachments, disabled, setAttachments]);
175
+ const trailingButton = showCancelButton ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComposerActionButton, { onClick: onCancelRequest, showCancelButton: true }) : hasDraft ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComposerActionButton, { onClick: handleSend, disabled: !canSend }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "h-9 w-9 shrink-0" });
176
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-4 pt-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mx-auto flex w-full max-w-4xl flex-col gap-2 rounded-md border border-input/70 bg-background px-2 py-1 shadow-xs focus-within:border-primary focus-within:[outline:1px_solid_var(--color-primary)]", children: [
177
+ attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex max-w-full flex-wrap gap-2 px-1 pt-1", children: attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
82
178
  import_UploadPill.UploadPill,
83
179
  {
84
180
  attachment,
85
181
  onCancel: cancelAttachment
86
182
  },
87
- attachment.path
88
- )) }),
89
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-0 gap-3", children: [
90
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FileUploader.FileUploader, { onFilesSelected }),
183
+ `${attachment.path}-${index}`
184
+ )) }) : null,
185
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
186
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FileUploader.FileUploader, { onFilesSelected, disabled }),
91
187
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
92
188
  import_textarea.Textarea,
93
189
  {
94
- placeholder: "Type a message and press Enter",
95
- className: "flex-1 resize-none h-20",
190
+ ref: textareaRef,
191
+ autoFocus,
192
+ placeholder,
193
+ className: "min-h-5 max-h-40 flex-1 resize-none border-0 bg-transparent p-0 leading-5 shadow-none focus-visible:border-transparent focus-visible:ring-0",
194
+ readOnly: disabled,
96
195
  value,
97
- onChange: _onChange,
98
- onKeyDown
196
+ onChange: handleChange,
197
+ onKeyDown: handleKeyDown
99
198
  }
100
199
  ),
101
- showCancelButton === true ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { onClick: onCancelRequest, children: "Cancel" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_button.Button, { onClick: handleSend, disabled, children: "Send" })
200
+ trailingButton
102
201
  ] })
103
- ] });
202
+ ] }) });
104
203
  }
@@ -1,7 +1,21 @@
1
+ import type { ReactElement } from "react";
1
2
  import { Element, RoomClient } from "@meshagent/meshagent";
2
- export declare function timeAgo(iso: string): string;
3
- export declare function ChatThread({ room, messages, localParticipantName }: {
3
+ export interface ChatThreadProps {
4
4
  room: RoomClient;
5
5
  messages: Element[];
6
+ isLoading?: boolean;
6
7
  localParticipantName: string;
7
- }): import("react/jsx-runtime").JSX.Element;
8
+ path?: string;
9
+ showCompletedToolCalls?: boolean;
10
+ onShowCompletedToolCallsChanged?: (value: boolean) => void;
11
+ typing?: boolean;
12
+ thinking?: boolean;
13
+ threadStatusText?: string | null;
14
+ threadStatusStartedAt?: Date | null;
15
+ threadStatusMode?: string | null;
16
+ onCancelRequest?: () => void;
17
+ emptyStateTitle?: string;
18
+ emptyStateDescription?: string;
19
+ }
20
+ export declare function timeAgo(iso: string): string;
21
+ export declare function ChatThread({ room, messages, isLoading, localParticipantName, path, showCompletedToolCalls, onShowCompletedToolCallsChanged, typing, thinking, threadStatusText, threadStatusStartedAt, threadStatusMode, onCancelRequest, emptyStateTitle, emptyStateDescription, }: ChatThreadProps): ReactElement;