@mieweb/ui 0.8.0-dev.23 → 0.8.0-dev.24

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.d.cts CHANGED
@@ -607,6 +607,25 @@ interface AIMessageDisplayProps {
607
607
  */
608
608
  declare function AIMessageDisplay({ message, userName, showAvatar, showTimestamp, onLinkClick, renderTextContent, renderMessageFooter, className, }: AIMessageDisplayProps): react_jsx_runtime.JSX.Element;
609
609
 
610
+ /**
611
+ * A candidate for the composer's `@mention` autocomplete. Generic so any
612
+ * surface (multi-party chat, agent picker, …) can supply its own list.
613
+ */
614
+ interface MentionOption {
615
+ /** Stable unique key for the suggestion list. */
616
+ id: string;
617
+ /** Display name shown in the suggestion list. */
618
+ label: string;
619
+ /** Text inserted after `@` on selection. Defaults to the first word of `label`. */
620
+ value?: string;
621
+ /** Optional secondary text shown after the label. */
622
+ description?: string;
623
+ /** Optional leading node (e.g. an avatar). */
624
+ icon?: React$1.ReactNode;
625
+ /** Optional trailing meta text (e.g. a kind tag). */
626
+ meta?: string;
627
+ }
628
+
610
629
  /**
611
630
  * Messaging Component Types
612
631
  *
@@ -869,24 +888,6 @@ interface MessageGroup {
869
888
  messages: Message[];
870
889
  }
871
890
 
872
- /**
873
- * A candidate for the composer's `@mention` autocomplete. Generic so any
874
- * surface (multi-party chat, agent picker, …) can supply its own list.
875
- */
876
- interface MentionOption {
877
- /** Stable id (returned to the host so it can map a selection back). */
878
- id: string;
879
- /** Display name shown in the suggestion list. */
880
- label: string;
881
- /** Text inserted after `@` on selection. Defaults to the first word of `label`. */
882
- value?: string;
883
- /** Optional secondary text shown after the label. */
884
- description?: string;
885
- /** Optional leading node (e.g. an avatar). */
886
- icon?: React$1.ReactNode;
887
- /** Optional trailing meta text (e.g. a kind tag). */
888
- meta?: string;
889
- }
890
891
  interface CharacterCounterProps {
891
892
  current: number;
892
893
  max: number;
@@ -3309,7 +3310,7 @@ interface ChatComposerProps {
3309
3310
  textareaProps?: Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'defaultValue'>;
3310
3311
  /** Extra entries for the `+` menu, rendered after the built-in items. */
3311
3312
  addMenuItems?: ChatComposerMenuItem[];
3312
- /** Enable file attachments (built-in "Attach files" menu item, paste-to-attach, chips). @default true */
3313
+ /** Enable file attachments (built-in "Attach files" menu item, paste-to-attach, drag-and-drop, chips). @default true */
3313
3314
  allowAttachments?: boolean;
3314
3315
  /** Accepted file types for the picker/paste validation (native `accept` tokens). */
3315
3316
  acceptedFileTypes?: string[];
@@ -3317,6 +3318,12 @@ interface ChatComposerProps {
3317
3318
  maxFileSize?: number;
3318
3319
  /** Maximum number of staged attachments. @default 10 */
3319
3320
  maxAttachments?: number;
3321
+ /**
3322
+ * Candidates for `@mention` autocomplete. When provided (non-empty), typing
3323
+ * `@` opens a suggestion listbox (same behavior as `MessageComposer`).
3324
+ * Omit to disable mentions entirely (default).
3325
+ */
3326
+ mentionOptions?: MentionOption[];
3320
3327
  /** Show the built-in mic button. @default false */
3321
3328
  showMic?: boolean;
3322
3329
  /** Called when the built-in mic button is clicked. */
@@ -3376,6 +3383,10 @@ interface ChatComposerProps {
3376
3383
  stopLabel?: string;
3377
3384
  /** Accessible label / empty-state text for the agent selector. @default 'Select agent' */
3378
3385
  agentSelectorLabel?: string;
3386
+ /** Accessible label for the `@mention` suggestion listbox. @default 'Mention' */
3387
+ mentionListLabel?: string;
3388
+ /** Overlay text shown while dragging files over the composer. @default 'Drop files here' */
3389
+ dropFilesLabel?: string;
3379
3390
  className?: string;
3380
3391
  }
3381
3392
  /**
@@ -7076,6 +7087,8 @@ interface DragDropZoneProps {
7076
7087
  disabled?: boolean;
7077
7088
  /** Called when an error occurs */
7078
7089
  onError?: (error: string) => void;
7090
+ /** Overlay text shown while dragging files over the zone. @default 'Drop files here' */
7091
+ overlayLabel?: string;
7079
7092
  /** Children to render inside the zone */
7080
7093
  children: React$1.ReactNode;
7081
7094
  className?: string;
@@ -7083,7 +7096,7 @@ interface DragDropZoneProps {
7083
7096
  /**
7084
7097
  * A wrapper component that accepts drag-and-drop files.
7085
7098
  */
7086
- declare function DragDropZone({ onFilesDropped, acceptedTypes, maxFileSize, maxFiles, disabled, onError, children, className, }: DragDropZoneProps): react_jsx_runtime.JSX.Element;
7099
+ declare function DragDropZone({ onFilesDropped, acceptedTypes, maxFileSize, maxFiles, disabled, onError, overlayLabel, children, className, }: DragDropZoneProps): react_jsx_runtime.JSX.Element;
7087
7100
  declare namespace DragDropZone {
7088
7101
  var displayName: string;
7089
7102
  }
package/dist/index.d.ts CHANGED
@@ -607,6 +607,25 @@ interface AIMessageDisplayProps {
607
607
  */
608
608
  declare function AIMessageDisplay({ message, userName, showAvatar, showTimestamp, onLinkClick, renderTextContent, renderMessageFooter, className, }: AIMessageDisplayProps): react_jsx_runtime.JSX.Element;
609
609
 
610
+ /**
611
+ * A candidate for the composer's `@mention` autocomplete. Generic so any
612
+ * surface (multi-party chat, agent picker, …) can supply its own list.
613
+ */
614
+ interface MentionOption {
615
+ /** Stable unique key for the suggestion list. */
616
+ id: string;
617
+ /** Display name shown in the suggestion list. */
618
+ label: string;
619
+ /** Text inserted after `@` on selection. Defaults to the first word of `label`. */
620
+ value?: string;
621
+ /** Optional secondary text shown after the label. */
622
+ description?: string;
623
+ /** Optional leading node (e.g. an avatar). */
624
+ icon?: React$1.ReactNode;
625
+ /** Optional trailing meta text (e.g. a kind tag). */
626
+ meta?: string;
627
+ }
628
+
610
629
  /**
611
630
  * Messaging Component Types
612
631
  *
@@ -869,24 +888,6 @@ interface MessageGroup {
869
888
  messages: Message[];
870
889
  }
871
890
 
872
- /**
873
- * A candidate for the composer's `@mention` autocomplete. Generic so any
874
- * surface (multi-party chat, agent picker, …) can supply its own list.
875
- */
876
- interface MentionOption {
877
- /** Stable id (returned to the host so it can map a selection back). */
878
- id: string;
879
- /** Display name shown in the suggestion list. */
880
- label: string;
881
- /** Text inserted after `@` on selection. Defaults to the first word of `label`. */
882
- value?: string;
883
- /** Optional secondary text shown after the label. */
884
- description?: string;
885
- /** Optional leading node (e.g. an avatar). */
886
- icon?: React$1.ReactNode;
887
- /** Optional trailing meta text (e.g. a kind tag). */
888
- meta?: string;
889
- }
890
891
  interface CharacterCounterProps {
891
892
  current: number;
892
893
  max: number;
@@ -3309,7 +3310,7 @@ interface ChatComposerProps {
3309
3310
  textareaProps?: Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'defaultValue'>;
3310
3311
  /** Extra entries for the `+` menu, rendered after the built-in items. */
3311
3312
  addMenuItems?: ChatComposerMenuItem[];
3312
- /** Enable file attachments (built-in "Attach files" menu item, paste-to-attach, chips). @default true */
3313
+ /** Enable file attachments (built-in "Attach files" menu item, paste-to-attach, drag-and-drop, chips). @default true */
3313
3314
  allowAttachments?: boolean;
3314
3315
  /** Accepted file types for the picker/paste validation (native `accept` tokens). */
3315
3316
  acceptedFileTypes?: string[];
@@ -3317,6 +3318,12 @@ interface ChatComposerProps {
3317
3318
  maxFileSize?: number;
3318
3319
  /** Maximum number of staged attachments. @default 10 */
3319
3320
  maxAttachments?: number;
3321
+ /**
3322
+ * Candidates for `@mention` autocomplete. When provided (non-empty), typing
3323
+ * `@` opens a suggestion listbox (same behavior as `MessageComposer`).
3324
+ * Omit to disable mentions entirely (default).
3325
+ */
3326
+ mentionOptions?: MentionOption[];
3320
3327
  /** Show the built-in mic button. @default false */
3321
3328
  showMic?: boolean;
3322
3329
  /** Called when the built-in mic button is clicked. */
@@ -3376,6 +3383,10 @@ interface ChatComposerProps {
3376
3383
  stopLabel?: string;
3377
3384
  /** Accessible label / empty-state text for the agent selector. @default 'Select agent' */
3378
3385
  agentSelectorLabel?: string;
3386
+ /** Accessible label for the `@mention` suggestion listbox. @default 'Mention' */
3387
+ mentionListLabel?: string;
3388
+ /** Overlay text shown while dragging files over the composer. @default 'Drop files here' */
3389
+ dropFilesLabel?: string;
3379
3390
  className?: string;
3380
3391
  }
3381
3392
  /**
@@ -7076,6 +7087,8 @@ interface DragDropZoneProps {
7076
7087
  disabled?: boolean;
7077
7088
  /** Called when an error occurs */
7078
7089
  onError?: (error: string) => void;
7090
+ /** Overlay text shown while dragging files over the zone. @default 'Drop files here' */
7091
+ overlayLabel?: string;
7079
7092
  /** Children to render inside the zone */
7080
7093
  children: React$1.ReactNode;
7081
7094
  className?: string;
@@ -7083,7 +7096,7 @@ interface DragDropZoneProps {
7083
7096
  /**
7084
7097
  * A wrapper component that accepts drag-and-drop files.
7085
7098
  */
7086
- declare function DragDropZone({ onFilesDropped, acceptedTypes, maxFileSize, maxFiles, disabled, onError, children, className, }: DragDropZoneProps): react_jsx_runtime.JSX.Element;
7099
+ declare function DragDropZone({ onFilesDropped, acceptedTypes, maxFileSize, maxFiles, disabled, onError, overlayLabel, children, className, }: DragDropZoneProps): react_jsx_runtime.JSX.Element;
7087
7100
  declare namespace DragDropZone {
7088
7101
  var displayName: string;
7089
7102
  }
package/dist/index.js CHANGED
@@ -27,10 +27,10 @@ import { Spinner, SpinnerWithLabel } from './chunk-UA7E7PDS.js';
27
27
  export { FullPageSpinner, Spinner, SpinnerWithLabel, spinnerVariants } from './chunk-UA7E7PDS.js';
28
28
  import { SparklesIcon, RefreshIcon, CloseIcon, AIMessageDisplay } from './chunk-22CYDCXA.js';
29
29
  export { AILogoIcon, AIMessageDisplay, AITypingIndicator, ChatBubble, ChevronIcon, CloseIcon, CollapsiblePill, MCPToolCallDisplay, MessageAvatar, RefreshIcon, ResourceLink, SendIcon, SparklesIcon, SpinnerIcon, ToolStatusIcon, getToolIcon } from './chunk-22CYDCXA.js';
30
- import { EmptyState } from './chunk-5KJYGLVU.js';
31
- export { AttachmentPreview, ConversationHeader, ConversationListItem, ConversationListSkeleton, DateSeparator, EmptyState, LightboxModal, LoadMoreButton, MessageBubble, MessageList, MessageStatusIcon, MessageThread, MessagingSplitView, ReadReceiptIndicator, SkeletonMessage, TypingIndicator, bubbleVariants, formatDateLabel, formatFileSize, formatLastSeen, getConversationSubtitle, getConversationTitle, groupMessagesByDate, headerVariants, isSameSenderGroup, useMessageScroll, useMessages, useReadReceipts, useTypingIndicator } from './chunk-5KJYGLVU.js';
32
- import { validateFile, getFileType, generateAttachmentId, AttachmentPreviewItem, MessageComposer } from './chunk-AZLDTPYK.js';
33
- export { AttachmentPicker, AttachmentPreviewItem, CameraButton, CharacterCounter, DragDropZone, MessageComposer, SendButton, generateAttachmentId, getFileType, sendButtonVariants, validateFile } from './chunk-AZLDTPYK.js';
30
+ import { EmptyState } from './chunk-MXQ7J4BB.js';
31
+ export { AttachmentPreview, ConversationHeader, ConversationListItem, ConversationListSkeleton, DateSeparator, EmptyState, LightboxModal, LoadMoreButton, MessageBubble, MessageList, MessageStatusIcon, MessageThread, MessagingSplitView, ReadReceiptIndicator, SkeletonMessage, TypingIndicator, bubbleVariants, formatDateLabel, formatFileSize, formatLastSeen, getConversationSubtitle, getConversationTitle, groupMessagesByDate, headerVariants, isSameSenderGroup, useMessageScroll, useMessages, useReadReceipts, useTypingIndicator } from './chunk-MXQ7J4BB.js';
32
+ import { useMentionAutocomplete, validateFile, getFileType, generateAttachmentId, AttachmentPreviewItem, MentionMenu, DragDropZone, MessageComposer } from './chunk-O6GJ4IYS.js';
33
+ export { AttachmentPicker, AttachmentPreviewItem, CameraButton, CharacterCounter, DragDropZone, MessageComposer, SendButton, generateAttachmentId, getFileType, sendButtonVariants, validateFile } from './chunk-O6GJ4IYS.js';
34
34
  import { RecordButton } from './chunk-VNWJTCBQ.js';
35
35
  export { RecordButton, formatDuration, recordButtonVariants } from './chunk-VNWJTCBQ.js';
36
36
  export { RichTextEditor, convertAngleBracketsToMustache, processDictation } from './chunk-5H7SAEQO.js';
@@ -12534,6 +12534,7 @@ var ChatComposer = React13.forwardRef(function ChatComposer2({
12534
12534
  acceptedFileTypes,
12535
12535
  maxFileSize,
12536
12536
  maxAttachments = 10,
12537
+ mentionOptions,
12537
12538
  showMic = false,
12538
12539
  onMicClick,
12539
12540
  micSlot,
@@ -12559,6 +12560,8 @@ var ChatComposer = React13.forwardRef(function ChatComposer2({
12559
12560
  sendLabel = "Send message",
12560
12561
  stopLabel = "Stop generating",
12561
12562
  agentSelectorLabel = "Select agent",
12563
+ mentionListLabel = "Mention",
12564
+ dropFilesLabel = "Drop files here",
12562
12565
  className
12563
12566
  }, ref) {
12564
12567
  const [internalValue, setInternalValue] = React13.useState("");
@@ -12582,6 +12585,12 @@ var ChatComposer = React13.forwardRef(function ChatComposer2({
12582
12585
  },
12583
12586
  [isControlled, onValueChange]
12584
12587
  );
12588
+ const mention = useMentionAutocomplete({
12589
+ options: mentionOptions,
12590
+ value,
12591
+ setValue,
12592
+ textareaRef
12593
+ });
12585
12594
  const resizeTextarea = React13.useCallback(() => {
12586
12595
  const textarea = textareaRef.current;
12587
12596
  if (!textarea) return;
@@ -12716,6 +12725,7 @@ var ChatComposer = React13.forwardRef(function ChatComposer2({
12716
12725
  textareaRef.current?.focus();
12717
12726
  };
12718
12727
  const handleKeyDown = (event) => {
12728
+ if (mention.handleKeyDown(event)) return;
12719
12729
  if (event.key === "Enter" && !event.shiftKey) {
12720
12730
  event.preventDefault();
12721
12731
  handleSend();
@@ -12768,48 +12778,69 @@ var ChatComposer = React13.forwardRef(function ChatComposer2({
12768
12778
  }
12769
12779
  ),
12770
12780
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[auto_minmax(0,1fr)_auto]", children: [
12771
- /* @__PURE__ */ jsx("div", { className: cells.input, children: /* @__PURE__ */ jsx(
12772
- "textarea",
12773
- {
12774
- ...textareaProps,
12775
- ref: textareaRef,
12776
- "data-slot": "chat-composer-input",
12777
- value,
12778
- onChange: (event) => {
12779
- textareaProps?.onChange?.(event);
12780
- setValue(event.target.value);
12781
- },
12782
- onKeyDown: (event) => {
12783
- textareaProps?.onKeyDown?.(event);
12784
- if (event.defaultPrevented) return;
12785
- handleKeyDown(event);
12786
- },
12787
- onPaste: (event) => {
12788
- textareaProps?.onPaste?.(event);
12789
- if (event.defaultPrevented) return;
12790
- handlePaste(event);
12791
- },
12792
- placeholder,
12793
- disabled,
12794
- autoFocus,
12795
- rows: 1,
12796
- "aria-label": inputLabel,
12797
- style: {
12798
- ...textareaProps?.style,
12799
- maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight
12800
- },
12801
- className: cn(
12802
- "block w-full resize-none bg-transparent",
12803
- "rounded-lg text-sm",
12804
- cells.textarea,
12805
- "text-neutral-900 placeholder:text-neutral-400 dark:text-white dark:placeholder:text-neutral-500",
12806
- // Ring the input itself on focus rather than the whole shell.
12807
- "focus:ring-primary-500 focus:ring-1 focus:outline-none",
12808
- "disabled:cursor-not-allowed",
12809
- textareaProps?.className
12810
- )
12811
- }
12812
- ) }),
12781
+ /* @__PURE__ */ jsxs("div", { className: cells.input, ref: mention.anchorRef, children: [
12782
+ /* @__PURE__ */ jsx(
12783
+ MentionMenu,
12784
+ {
12785
+ mention,
12786
+ label: mentionListLabel,
12787
+ dataSlot: "chat-composer-mention-list"
12788
+ }
12789
+ ),
12790
+ /* @__PURE__ */ jsx(
12791
+ "textarea",
12792
+ {
12793
+ ...textareaProps,
12794
+ ref: textareaRef,
12795
+ "data-slot": "chat-composer-input",
12796
+ value,
12797
+ onChange: (event) => {
12798
+ textareaProps?.onChange?.(event);
12799
+ setValue(event.target.value);
12800
+ mention.sync(
12801
+ event.target.value,
12802
+ event.target.selectionStart ?? event.target.value.length
12803
+ );
12804
+ },
12805
+ onKeyDown: (event) => {
12806
+ textareaProps?.onKeyDown?.(event);
12807
+ if (event.defaultPrevented) return;
12808
+ handleKeyDown(event);
12809
+ },
12810
+ onClick: (event) => {
12811
+ textareaProps?.onClick?.(event);
12812
+ if (event.defaultPrevented) return;
12813
+ const el = event.currentTarget;
12814
+ mention.sync(el.value, el.selectionStart ?? el.value.length);
12815
+ },
12816
+ onPaste: (event) => {
12817
+ textareaProps?.onPaste?.(event);
12818
+ if (event.defaultPrevented) return;
12819
+ handlePaste(event);
12820
+ },
12821
+ placeholder,
12822
+ disabled,
12823
+ autoFocus,
12824
+ rows: 1,
12825
+ "aria-label": inputLabel,
12826
+ ...mention.inputProps,
12827
+ style: {
12828
+ ...textareaProps?.style,
12829
+ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight
12830
+ },
12831
+ className: cn(
12832
+ "block w-full resize-none bg-transparent",
12833
+ "rounded-lg text-sm",
12834
+ cells.textarea,
12835
+ "text-neutral-900 placeholder:text-neutral-400 dark:text-white dark:placeholder:text-neutral-500",
12836
+ // Ring the input itself on focus rather than the whole shell.
12837
+ "focus:ring-primary-500 focus:ring-1 focus:outline-none",
12838
+ "disabled:cursor-not-allowed",
12839
+ textareaProps?.className
12840
+ )
12841
+ }
12842
+ )
12843
+ ] }),
12813
12844
  showAddMenu && /* @__PURE__ */ jsx("div", { className: cells.add, children: /* @__PURE__ */ jsxs(
12814
12845
  Dropdown,
12815
12846
  {
@@ -13024,6 +13055,17 @@ var ChatComposer = React13.forwardRef(function ChatComposer2({
13024
13055
  ]
13025
13056
  }
13026
13057
  );
13058
+ const card = /* @__PURE__ */ jsx(
13059
+ "div",
13060
+ {
13061
+ "data-slot": "chat-composer-card",
13062
+ className: cn(
13063
+ "rounded-2xl border border-neutral-200 bg-white shadow-sm",
13064
+ "dark:border-[#2e2e30] dark:bg-[#1c1c1e]"
13065
+ ),
13066
+ children: composerCard
13067
+ }
13068
+ );
13027
13069
  return /* @__PURE__ */ jsxs(
13028
13070
  "div",
13029
13071
  {
@@ -13034,17 +13076,16 @@ var ChatComposer = React13.forwardRef(function ChatComposer2({
13034
13076
  className
13035
13077
  ),
13036
13078
  children: [
13037
- /* @__PURE__ */ jsx(
13038
- "div",
13079
+ allowAttachments ? /* @__PURE__ */ jsx(
13080
+ DragDropZone,
13039
13081
  {
13040
- "data-slot": "chat-composer-card",
13041
- className: cn(
13042
- "rounded-2xl border border-neutral-200 bg-white shadow-sm",
13043
- "dark:border-[#2e2e30] dark:bg-[#1c1c1e]"
13044
- ),
13045
- children: composerCard
13082
+ onFilesDropped: addFiles,
13083
+ maxFiles: Number.MAX_SAFE_INTEGER,
13084
+ disabled,
13085
+ overlayLabel: dropFilesLabel,
13086
+ children: card
13046
13087
  }
13047
- ),
13088
+ ) : card,
13048
13089
  selectorsRow
13049
13090
  ]
13050
13091
  }