@agents24/chat-react 0.5.37 → 0.5.39

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/ui/index.js CHANGED
@@ -940,15 +940,33 @@ function useAgentChatComposer(options) {
940
940
  const generationRef = React4.useRef(0);
941
941
  const mountedRef = React4.useRef(true);
942
942
  const textRef = React4.useRef(text);
943
+ const scope = React4.useMemo(() => ({ active: false }), [options.scopeKey]);
944
+ const [textInteraction, setTextInteraction] = React4.useState(null);
945
+ const handledTextInteractionRef = React4.useRef(textInteraction);
943
946
  React4.useLayoutEffect(() => {
947
+ scope.active = true;
944
948
  mountedRef.current = true;
945
949
  submittingRef.current = false;
946
950
  setIsSubmitting(false);
947
951
  return () => {
952
+ scope.active = false;
948
953
  mountedRef.current = false;
949
954
  generationRef.current += 1;
950
955
  };
951
- }, [options.scopeKey]);
956
+ }, [scope]);
957
+ React4.useLayoutEffect(() => {
958
+ if (handledTextInteractionRef.current === textInteraction) return;
959
+ handledTextInteractionRef.current = textInteraction;
960
+ if (!textInteraction || textInteraction.scope !== scope || !scope.active || textInteraction.revision !== revisionRef.current || options.disabled) return;
961
+ const textarea = textareaRef.current;
962
+ if (!textarea) return;
963
+ if (textInteraction.options.focus) textarea.focus({ preventScroll: true });
964
+ const selection = textInteraction.options.selection;
965
+ if (selection) {
966
+ const clamp = (offset) => Math.max(0, Math.min(textRef.current.length, offset));
967
+ textarea.setSelectionRange(clamp(selection.start), clamp(selection.end), selection.direction);
968
+ }
969
+ }, [textInteraction, scope, textareaRef, options.disabled]);
952
970
  React4.useEffect(() => () => {
953
971
  revokeAgentChatComposerFiles(filesRef.current);
954
972
  revokeAgentChatComposerFiles([...inFlightFilesRef.current.values()].flat());
@@ -973,11 +991,14 @@ function useAgentChatComposer(options) {
973
991
  }
974
992
  });
975
993
  const attachmentMimeTypes = inputMimeTypes(options.inputContract);
976
- const setText = (value) => {
977
- revisionRef.current += 1;
994
+ const setText = React4.useCallback((value, interaction = {}) => {
995
+ if (!scope.active) return false;
996
+ const revision = ++revisionRef.current;
978
997
  textRef.current = value;
979
998
  setTextState(value);
980
- };
999
+ setTextInteraction({ scope, revision, options: interaction });
1000
+ return true;
1001
+ }, [scope]);
981
1002
  const addFiles = (selected) => {
982
1003
  const accepted = selected.filter((file) => attachmentMimeTypes.includes(canonicalInputMimeType(file.type, file.name)));
983
1004
  revisionRef.current += 1;
@@ -1190,6 +1211,7 @@ function formatFileCount(files) {
1190
1211
  var pillButtonClass = "inline-flex size-8 shrink-0 items-center justify-center gap-2 rounded-lg border-0 bg-muted text-sm text-muted-foreground shadow-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50";
1191
1212
  var submitButtonClass = "inline-flex size-9 shrink-0 items-center justify-center gap-2 rounded-lg border-0 bg-primary text-sm text-primary-foreground shadow-none transition-[background-color,color,opacity,transform] duration-200 hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-0 disabled:pointer-events-none disabled:opacity-50";
1192
1213
  function AgentChatComposer({
1214
+ ref,
1193
1215
  inputContract,
1194
1216
  recordingEnabled,
1195
1217
  contextWindow,
@@ -1225,6 +1247,7 @@ function AgentChatComposer({
1225
1247
  onSubmit: (text2, files2) => onSubmit({ text: text2.trim(), files: files2, attachmentIds: files2.flatMap((file) => file.id ? [file.id] : []) })
1226
1248
  });
1227
1249
  const { text, files, setText, isSubmitting, canSubmit, action, submit } = composer;
1250
+ React6.useImperativeHandle(ref, () => ({ setText }), [setText]);
1228
1251
  const isExpanded = forceExpanded || text.includes("\n") || text.length > 62;
1229
1252
  const setTextareaRef = React6.useCallback(
1230
1253
  (node) => {