@copilotz/chat-ui 0.9.6 → 0.9.8

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.cjs CHANGED
@@ -3363,7 +3363,8 @@ var TargetAgentSelector = (0, import_react5.memo)(({
3363
3363
  onTargetChange,
3364
3364
  label = "Target",
3365
3365
  placeholder = "Select agent",
3366
- disabled = false
3366
+ disabled = false,
3367
+ compact = false
3367
3368
  }) => {
3368
3369
  const agentsWithColors = (0, import_react5.useMemo)(() => assignAgentColors(agents), [agents]);
3369
3370
  const selectedAgent = (0, import_react5.useMemo)(
@@ -3375,7 +3376,7 @@ var TargetAgentSelector = (0, import_react5.memo)(({
3375
3376
  Button,
3376
3377
  {
3377
3378
  variant: "ghost",
3378
- className: "h-9 px-3 gap-1.5 font-medium text-base hover:bg-accent/50",
3379
+ className: `gap-1.5 font-medium hover:bg-accent/50 ${compact ? "h-9 rounded-full px-2 text-sm text-muted-foreground hover:text-foreground" : "h-9 px-3 text-base"}`,
3379
3380
  disabled,
3380
3381
  children: [
3381
3382
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react9.AtSign, { className: "h-4 w-4 text-muted-foreground" }),
@@ -4538,6 +4539,9 @@ var ChatInput = (0, import_react8.memo)(function ChatInput2({
4538
4539
  className = "",
4539
4540
  config,
4540
4541
  mentionAgents = [],
4542
+ targetAgentId = null,
4543
+ showTargetAgentSelector = false,
4544
+ targetAgentSelectorPlaceholder,
4541
4545
  onTargetAgentChange
4542
4546
  }) {
4543
4547
  const voiceDefaultMode = config?.voiceCompose?.defaultMode ?? "text";
@@ -4586,6 +4590,18 @@ var ChatInput = (0, import_react8.memo)(function ChatInput2({
4586
4590
  }).slice(0, 6);
4587
4591
  }, [activeMention, mentionAgents]);
4588
4592
  const isMentionMenuOpen = filteredMentionAgents.length > 0;
4593
+ const resizeTextarea = (0, import_react8.useCallback)(() => {
4594
+ const textarea = textareaRef.current;
4595
+ if (!textarea) return;
4596
+ const viewportWidth = typeof window === "undefined" ? 1024 : window.innerWidth;
4597
+ const maxHeight = viewportWidth > 768 ? 240 : 190;
4598
+ textarea.style.height = "auto";
4599
+ textarea.style.height = `${Math.min(textarea.scrollHeight, maxHeight)}px`;
4600
+ textarea.style.overflowY = textarea.scrollHeight > maxHeight ? "auto" : "hidden";
4601
+ }, []);
4602
+ (0, import_react8.useEffect)(() => {
4603
+ resizeTextarea();
4604
+ }, [resizeTextarea, value]);
4589
4605
  const syncMentionState = (0, import_react8.useCallback)((nextValue, nextCaret) => {
4590
4606
  const caret = typeof nextCaret === "number" ? nextCaret : textareaRef.current?.selectionStart ?? nextValue.length;
4591
4607
  const nextMatch = getActiveMentionMatch(nextValue, caret);
@@ -5056,7 +5072,7 @@ var ChatInput = (0, import_react8.memo)(function ChatInput2({
5056
5072
  };
5057
5073
  const canAddMoreAttachments = attachments.length < maxAttachments;
5058
5074
  const showVoiceComposer = enableAudioRecording && isVoiceComposerOpen;
5059
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: `border-t py-0 bg-transparent ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "px-0 md:p-2 pb-1 space-y-4 bg-transparent", children: [
5075
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: `bg-transparent py-0 ${className}`, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "mx-auto w-full max-w-3xl space-y-3 px-3 md:px-2", children: [
5060
5076
  uploadProgress.size > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "space-y-2", children: Array.from(uploadProgress.entries()).map(([id, progress]) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5061
5077
  FileUploadItem,
5062
5078
  {
@@ -5120,46 +5136,14 @@ var ChatInput = (0, import_react8.memo)(function ChatInput2({
5120
5136
  void closeVoiceComposer();
5121
5137
  }
5122
5138
  }
5123
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("form", { onSubmit: handleSubmit, className: "mb-1 flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5139
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("form", { onSubmit: handleSubmit, className: "mb-1", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
5124
5140
  "div",
5125
5141
  {
5126
- className: "flex items-end gap-2 p-3 border rounded-lg bg-background w-full md:min-w-3xl max-w-3xl",
5142
+ className: "group/composer flex w-full flex-col gap-2 rounded-3xl border border-border/80 bg-card/95 p-2.5 shadow-sm transition-[border-color,box-shadow,background-color] focus-within:border-ring/60 focus-within:bg-card focus-within:shadow-md focus-within:ring-2 focus-within:ring-ring/15",
5127
5143
  onDrop: handleDrop,
5128
5144
  onDragOver: handleDragOver,
5129
5145
  children: [
5130
- enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5131
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5132
- "input",
5133
- {
5134
- ref: fileInputRef,
5135
- type: "file",
5136
- multiple: true,
5137
- accept: acceptedFileTypes.length > 0 ? acceptedFileTypes.join(",") : void 0,
5138
- onChange: handleFileSelect,
5139
- className: "hidden"
5140
- }
5141
- ),
5142
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5143
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5144
- Button,
5145
- {
5146
- type: "button",
5147
- variant: "outline",
5148
- size: "icon",
5149
- className: "h-10 w-10",
5150
- onClick: (e) => {
5151
- e.preventDefault();
5152
- e.stopPropagation();
5153
- fileInputRef.current?.click();
5154
- },
5155
- disabled,
5156
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Paperclip, { className: "h-4 w-4" })
5157
- }
5158
- ) }),
5159
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.attachFileTooltip })
5160
- ] })
5161
- ] }),
5162
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative flex-1", children: [
5146
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "relative min-w-0", children: [
5163
5147
  /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5164
5148
  Textarea,
5165
5149
  {
@@ -5168,6 +5152,7 @@ var ChatInput = (0, import_react8.memo)(function ChatInput2({
5168
5152
  onChange: (e) => {
5169
5153
  onChange(e.target.value);
5170
5154
  syncMentionState(e.target.value, e.target.selectionStart ?? e.target.value.length);
5155
+ requestAnimationFrame(resizeTextarea);
5171
5156
  },
5172
5157
  onSelect: (e) => {
5173
5158
  const target = e.target;
@@ -5180,7 +5165,7 @@ var ChatInput = (0, import_react8.memo)(function ChatInput2({
5180
5165
  onKeyDown: handleKeyDown,
5181
5166
  placeholder,
5182
5167
  disabled,
5183
- className: "max-h-[120px] resize-none border-0 bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0",
5168
+ className: "min-h-11 resize-none overflow-hidden rounded-2xl border-0 bg-transparent px-3 py-2.5 text-base leading-6 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0 md:text-sm",
5184
5169
  rows: 1
5185
5170
  }
5186
5171
  ),
@@ -5201,48 +5186,97 @@ var ChatInput = (0, import_react8.memo)(function ChatInput2({
5201
5186
  agent.id
5202
5187
  )) }) })
5203
5188
  ] }),
5204
- enableAudioRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5205
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5206
- Button,
5207
- {
5208
- type: "button",
5209
- variant: "outline",
5210
- size: "icon",
5211
- className: "h-10 w-10",
5212
- onClick: () => {
5213
- void startVoiceCapture();
5214
- },
5215
- disabled: disabled || isGenerating,
5216
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Mic, { className: "h-4 w-4" })
5217
- }
5218
- ) }),
5219
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.voiceEnter })
5220
- ] }),
5221
- isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5222
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5223
- Button,
5224
- {
5225
- type: "button",
5226
- variant: "outline",
5227
- size: "icon",
5228
- className: "h-10 w-10",
5229
- onClick: onStopGeneration,
5230
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Square, { className: "h-4 w-4" })
5231
- }
5232
- ) }),
5233
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.stopGenerationTooltip })
5234
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5235
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5236
- Button,
5237
- {
5238
- type: "submit",
5239
- size: "icon",
5240
- className: "h-10 w-10",
5241
- disabled: disabled || !value.trim() && attachments.length === 0,
5242
- children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Send, { className: "h-4 w-4" })
5243
- }
5244
- ) }),
5245
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.sendMessageTooltip })
5189
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-h-10 items-center justify-between gap-2", children: [
5190
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex min-w-0 items-center gap-1", children: [
5191
+ enableFileUpload && canAddMoreAttachments && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
5192
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5193
+ "input",
5194
+ {
5195
+ ref: fileInputRef,
5196
+ type: "file",
5197
+ multiple: true,
5198
+ accept: acceptedFileTypes.length > 0 ? acceptedFileTypes.join(",") : void 0,
5199
+ onChange: handleFileSelect,
5200
+ className: "hidden"
5201
+ }
5202
+ ),
5203
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5204
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5205
+ Button,
5206
+ {
5207
+ type: "button",
5208
+ variant: "ghost",
5209
+ size: "icon",
5210
+ className: "h-9 w-9 rounded-full text-muted-foreground hover:text-foreground",
5211
+ onClick: (e) => {
5212
+ e.preventDefault();
5213
+ e.stopPropagation();
5214
+ fileInputRef.current?.click();
5215
+ },
5216
+ disabled,
5217
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Paperclip, { className: "h-4 w-4" })
5218
+ }
5219
+ ) }),
5220
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.attachFileTooltip })
5221
+ ] })
5222
+ ] }),
5223
+ showTargetAgentSelector && onTargetAgentChange && mentionAgents.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5224
+ TargetAgentSelector,
5225
+ {
5226
+ agents: mentionAgents,
5227
+ targetAgentId,
5228
+ onTargetChange: onTargetAgentChange,
5229
+ placeholder: targetAgentSelectorPlaceholder || "Select agent",
5230
+ disabled: disabled || isGenerating,
5231
+ compact: true
5232
+ }
5233
+ )
5234
+ ] }),
5235
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex shrink-0 items-center gap-1", children: [
5236
+ enableAudioRecording && canAddMoreAttachments && !value.trim() && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5237
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5238
+ Button,
5239
+ {
5240
+ type: "button",
5241
+ variant: "ghost",
5242
+ size: "icon",
5243
+ className: "h-9 w-9 rounded-full text-muted-foreground hover:text-foreground",
5244
+ onClick: () => {
5245
+ void startVoiceCapture();
5246
+ },
5247
+ disabled: disabled || isGenerating,
5248
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Mic, { className: "h-4 w-4" })
5249
+ }
5250
+ ) }),
5251
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.voiceEnter })
5252
+ ] }),
5253
+ isGenerating ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5254
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5255
+ Button,
5256
+ {
5257
+ type: "button",
5258
+ variant: "secondary",
5259
+ size: "icon",
5260
+ className: "h-9 w-9 rounded-full",
5261
+ onClick: onStopGeneration,
5262
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Square, { className: "h-4 w-4" })
5263
+ }
5264
+ ) }),
5265
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.stopGenerationTooltip })
5266
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
5267
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
5268
+ Button,
5269
+ {
5270
+ type: "submit",
5271
+ size: "icon",
5272
+ className: "h-9 w-9 rounded-full",
5273
+ disabled: disabled || !value.trim() && attachments.length === 0,
5274
+ children: disabled ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.Send, { className: "h-4 w-4" })
5275
+ }
5276
+ ) }),
5277
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipContent, { children: config?.labels?.sendMessageTooltip })
5278
+ ] })
5279
+ ] })
5246
5280
  ] })
5247
5281
  ]
5248
5282
  }
@@ -6459,50 +6493,41 @@ var ChatUI = ({
6459
6493
  ] })
6460
6494
  }
6461
6495
  ),
6462
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "bg-background pb-[env(safe-area-inset-bottom)]", children: [
6463
- isMultiAgentMode && shouldShowAgentSelector && onTargetAgentChange && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "px-4 pt-1", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6464
- TargetAgentSelector,
6465
- {
6466
- agents: participantIds && participantIds.length > 0 ? agentOptions.filter(
6467
- (a) => participantIds.includes(a.id)
6468
- ) : agentOptions,
6469
- targetAgentId,
6470
- onTargetChange: onTargetAgentChange,
6471
- placeholder: config.agentSelector?.label || "Select agent",
6472
- disabled: isGenerating
6473
- }
6474
- ) }),
6475
- /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6476
- ChatInput,
6477
- {
6478
- value: inputValue,
6479
- onChange: (value) => {
6480
- setInputValue(value);
6481
- if (initialInputApplied.current && !initialInputConsumedRef.current) {
6482
- initialInputConsumedRef.current = true;
6483
- onInitialInputConsumed?.();
6484
- }
6485
- },
6486
- onSubmit: handleSendMessage,
6487
- attachments,
6488
- onAttachmentsChange: setAttachments,
6489
- placeholder: config.labels.inputPlaceholder,
6490
- disabled: false,
6491
- isGenerating,
6492
- onStopGeneration: callbacks.onStopGeneration,
6493
- enableFileUpload: config.features.enableFileUpload,
6494
- enableAudioRecording: config.features.enableAudioRecording,
6495
- maxAttachments: config.features.maxAttachments,
6496
- maxFileSize: config.features.maxFileSize,
6497
- acceptedFileTypes: config.features.acceptedFileTypes,
6498
- config,
6499
- mentionAgents: participantIds && participantIds.length > 0 ? agentOptions.filter(
6500
- (a) => participantIds.includes(a.id)
6501
- ) : agentOptions,
6502
- onTargetAgentChange
6503
- }
6504
- )
6505
- ] })
6496
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "-mt-8 bg-gradient-to-t from-background via-background/95 to-transparent px-0 pb-[env(safe-area-inset-bottom)] pt-10", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6497
+ ChatInput,
6498
+ {
6499
+ value: inputValue,
6500
+ onChange: (value) => {
6501
+ setInputValue(value);
6502
+ if (initialInputApplied.current && !initialInputConsumedRef.current) {
6503
+ initialInputConsumedRef.current = true;
6504
+ onInitialInputConsumed?.();
6505
+ }
6506
+ },
6507
+ onSubmit: handleSendMessage,
6508
+ attachments,
6509
+ onAttachmentsChange: setAttachments,
6510
+ placeholder: config.labels.inputPlaceholder,
6511
+ disabled: false,
6512
+ isGenerating,
6513
+ onStopGeneration: callbacks.onStopGeneration,
6514
+ enableFileUpload: config.features.enableFileUpload,
6515
+ enableAudioRecording: config.features.enableAudioRecording,
6516
+ maxAttachments: config.features.maxAttachments,
6517
+ maxFileSize: config.features.maxFileSize,
6518
+ acceptedFileTypes: config.features.acceptedFileTypes,
6519
+ config,
6520
+ mentionAgents: participantIds && participantIds.length > 0 ? agentOptions.filter(
6521
+ (a) => participantIds.includes(a.id)
6522
+ ) : agentOptions,
6523
+ targetAgentId,
6524
+ showTargetAgentSelector: Boolean(
6525
+ isMultiAgentMode && shouldShowAgentSelector && onTargetAgentChange
6526
+ ),
6527
+ targetAgentSelectorPlaceholder: config.agentSelector?.label || "Select agent",
6528
+ onTargetAgentChange
6529
+ }
6530
+ ) })
6506
6531
  ] }),
6507
6532
  config?.customComponent?.component && !isMobile && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
6508
6533
  "div",