@assistant-ui/react 0.0.2 → 0.0.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.
package/dist/index.d.mts CHANGED
@@ -35,8 +35,13 @@ declare const ThreadViewport: react.ForwardRefExoticComponent<Pick<Omit<react.De
35
35
  type ThreadMessagesProps = {
36
36
  components: {
37
37
  Message: React.ComponentType;
38
+ UserMessage?: React.ComponentType;
39
+ EditingUserMessage?: React.ComponentType;
40
+ AssistantMessage?: React.ComponentType;
38
41
  } | {
42
+ Message?: React.ComponentType;
39
43
  UserMessage: React.ComponentType;
44
+ EditingUserMessage?: React.ComponentType;
40
45
  AssistantMessage: React.ComponentType;
41
46
  };
42
47
  };
@@ -90,7 +95,7 @@ type MessageIfFilters = {
90
95
  editing: boolean | undefined;
91
96
  hasBranches: boolean | undefined;
92
97
  copied: boolean | undefined;
93
- unstable_hoveringOrLast: boolean | undefined;
98
+ lastOrHover: boolean | undefined;
94
99
  };
95
100
  type MessageIfProps = RequireAtLeastOne<MessageIfFilters> & {
96
101
  children: React.ReactNode;
@@ -138,7 +143,8 @@ declare const ActionBarRoot: react.ForwardRefExoticComponent<Pick<Omit<react.Det
138
143
  } & {
139
144
  asChild?: boolean;
140
145
  }, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & {
141
- hideWhenEditing?: boolean;
146
+ hideWhenBusy?: boolean;
147
+ hideWhenNotLastOrHover?: boolean;
142
148
  } & react.RefAttributes<HTMLDivElement>>;
143
149
 
144
150
  type ActionBarCopyProps = {
@@ -170,9 +176,7 @@ declare const EditBarRoot: react.ForwardRefExoticComponent<Pick<Omit<react.Detai
170
176
  ref?: ((instance: HTMLDivElement | null) => void) | react.RefObject<HTMLDivElement> | null | undefined;
171
177
  } & {
172
178
  asChild?: boolean;
173
- }, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & {
174
- hideWhenNotEditing?: boolean;
175
- } & react.RefAttributes<HTMLDivElement>>;
179
+ }, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & react.RefAttributes<HTMLDivElement>>;
176
180
 
177
181
  declare const EditBarSave: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
178
182
  ref?: ((instance: HTMLButtonElement | null) => void) | react.RefObject<HTMLButtonElement> | null | undefined;
@@ -221,7 +225,7 @@ declare const useMessageContext: <Selection>(consumerName: string, selector: (s:
221
225
 
222
226
  declare const useCopyMessage: ({ copiedDuration }: {
223
227
  copiedDuration?: number | undefined;
224
- }) => () => void;
228
+ }) => (() => void) | null;
225
229
 
226
230
  declare const useReloadMessage: () => (() => Promise<void>) | null;
227
231
 
package/dist/index.d.ts CHANGED
@@ -35,8 +35,13 @@ declare const ThreadViewport: react.ForwardRefExoticComponent<Pick<Omit<react.De
35
35
  type ThreadMessagesProps = {
36
36
  components: {
37
37
  Message: React.ComponentType;
38
+ UserMessage?: React.ComponentType;
39
+ EditingUserMessage?: React.ComponentType;
40
+ AssistantMessage?: React.ComponentType;
38
41
  } | {
42
+ Message?: React.ComponentType;
39
43
  UserMessage: React.ComponentType;
44
+ EditingUserMessage?: React.ComponentType;
40
45
  AssistantMessage: React.ComponentType;
41
46
  };
42
47
  };
@@ -90,7 +95,7 @@ type MessageIfFilters = {
90
95
  editing: boolean | undefined;
91
96
  hasBranches: boolean | undefined;
92
97
  copied: boolean | undefined;
93
- unstable_hoveringOrLast: boolean | undefined;
98
+ lastOrHover: boolean | undefined;
94
99
  };
95
100
  type MessageIfProps = RequireAtLeastOne<MessageIfFilters> & {
96
101
  children: React.ReactNode;
@@ -138,7 +143,8 @@ declare const ActionBarRoot: react.ForwardRefExoticComponent<Pick<Omit<react.Det
138
143
  } & {
139
144
  asChild?: boolean;
140
145
  }, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & {
141
- hideWhenEditing?: boolean;
146
+ hideWhenBusy?: boolean;
147
+ hideWhenNotLastOrHover?: boolean;
142
148
  } & react.RefAttributes<HTMLDivElement>>;
143
149
 
144
150
  type ActionBarCopyProps = {
@@ -170,9 +176,7 @@ declare const EditBarRoot: react.ForwardRefExoticComponent<Pick<Omit<react.Detai
170
176
  ref?: ((instance: HTMLDivElement | null) => void) | react.RefObject<HTMLDivElement> | null | undefined;
171
177
  } & {
172
178
  asChild?: boolean;
173
- }, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & {
174
- hideWhenNotEditing?: boolean;
175
- } & react.RefAttributes<HTMLDivElement>>;
179
+ }, "key" | keyof react.HTMLAttributes<HTMLDivElement> | "asChild"> & react.RefAttributes<HTMLDivElement>>;
176
180
 
177
181
  declare const EditBarSave: react.ForwardRefExoticComponent<Pick<Omit<react.DetailedHTMLProps<react.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
178
182
  ref?: ((instance: HTMLButtonElement | null) => void) | react.RefObject<HTMLButtonElement> | null | undefined;
@@ -221,7 +225,7 @@ declare const useMessageContext: <Selection>(consumerName: string, selector: (s:
221
225
 
222
226
  declare const useCopyMessage: ({ copiedDuration }: {
223
227
  copiedDuration?: number | undefined;
224
- }) => () => void;
228
+ }) => (() => void) | null;
225
229
 
226
230
  declare const useReloadMessage: () => (() => Promise<void>) | null;
227
231
 
package/dist/index.js CHANGED
@@ -186,7 +186,6 @@ var useOnResizeContent = (ref, callback) => {
186
186
  return;
187
187
  const resizeObserver = new ResizeObserver(() => {
188
188
  callbackRef.current();
189
- console.log("resize observed");
190
189
  });
191
190
  const mutationObserver = new MutationObserver((mutations) => {
192
191
  for (const mutation of mutations) {
@@ -203,6 +202,7 @@ var useOnResizeContent = (ref, callback) => {
203
202
  }
204
203
  callbackRef.current();
205
204
  });
205
+ resizeObserver.observe(el);
206
206
  mutationObserver.observe(el, { childList: true });
207
207
  for (const child of el.children) {
208
208
  resizeObserver.observe(child);
@@ -365,6 +365,9 @@ var useChatWithBranches = (chat) => {
365
365
  [chat, getBranchState, switchToBranch, editAt, reloadAt]
366
366
  );
367
367
  };
368
+ var hasUpcomingMessage = (thread) => {
369
+ return thread.isLoading && thread.messages[thread.messages.length - 1]?.role !== "assistant";
370
+ };
368
371
 
369
372
  // src/primitives/message/index.ts
370
373
  var message_exports = {};
@@ -445,6 +448,10 @@ var MessageRoot = (0, import_react7.forwardRef)(
445
448
  );
446
449
 
447
450
  // src/primitives/message/MessageIf.tsx
451
+ var isLast = (thread, message) => {
452
+ const hasUpcoming = hasUpcomingMessage(thread);
453
+ return hasUpcoming ? message.id === UPCOMING_MESSAGE_ID : thread.messages[thread.messages.length - 1]?.id === message.id;
454
+ };
448
455
  var useMessageIf = (props) => {
449
456
  const thread = useThreadContext("Message.If", (s) => s.chat);
450
457
  return useMessageContext(
@@ -461,7 +468,7 @@ var useMessageIf = (props) => {
461
468
  return false;
462
469
  if (props.editing === false && isEditing)
463
470
  return false;
464
- if (props.unstable_hoveringOrLast === true && !isHovering && thread.messages[thread.messages.length - 1]?.id !== message.id)
471
+ if (props.lastOrHover === true && !isHovering && !isLast(thread, message))
465
472
  return false;
466
473
  if (props.copied === true && !isCopied)
467
474
  return false;
@@ -514,23 +521,24 @@ var MessageEditableContent = (0, import_react8.forwardRef)(({ onChange, value, .
514
521
 
515
522
  // src/primitives/thread/ThreadMessages.tsx
516
523
  var getComponents = (components) => {
517
- if ("Message" in components) {
518
- return {
519
- UserMessage: components.Message,
520
- AssistantMessage: components.Message
521
- };
522
- }
523
- return components;
524
+ return {
525
+ EditingUserMessage: components.EditingUserMessage ?? components.UserMessage ?? components.Message,
526
+ UserMessage: components.UserMessage ?? components.Message,
527
+ AssistantMessage: components.AssistantMessage ?? components.Message
528
+ };
524
529
  };
525
530
  var ThreadMessages = ({ components }) => {
526
531
  const chat = useThreadContext("Thread.Messages", (s) => s.chat);
527
532
  const messages = chat.messages;
528
- const { UserMessage, AssistantMessage } = getComponents(components);
533
+ const { UserMessage, EditingUserMessage, AssistantMessage } = getComponents(components);
529
534
  if (messages.length === 0)
530
535
  return null;
531
- return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message) => {
532
- return /* @__PURE__ */ React.createElement(MessageProvider, { key: message.id, message }, message.role === "assistant" ? /* @__PURE__ */ React.createElement(AssistantMessage, null) : /* @__PURE__ */ React.createElement(UserMessage, null));
533
- }), chat.isLoading && chat.messages[chat.messages.length - 1]?.role !== "assistant" && /* @__PURE__ */ React.createElement(
536
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message, idx) => {
537
+ return (
538
+ // biome-ignore lint/suspicious/noArrayIndexKey: fixes a11y issues with branch navigation
539
+ /* @__PURE__ */ React.createElement(MessageProvider, { key: idx, message }, /* @__PURE__ */ React.createElement(MessageIf, { user: true, editing: false }, /* @__PURE__ */ React.createElement(UserMessage, null)), /* @__PURE__ */ React.createElement(MessageIf, { user: true, editing: true }, /* @__PURE__ */ React.createElement(EditingUserMessage, null)), /* @__PURE__ */ React.createElement(MessageIf, { assistant: true }, /* @__PURE__ */ React.createElement(AssistantMessage, null)))
540
+ );
541
+ }), hasUpcomingMessage(chat) && /* @__PURE__ */ React.createElement(
534
542
  MessageProvider,
535
543
  {
536
544
  message: {
@@ -698,12 +706,19 @@ var useGoToNextBranch = () => {
698
706
  "BranchPicker.Next",
699
707
  (s) => s.chat.switchToBranch
700
708
  );
701
- const [message, { branchId, branchCount }] = useMessageContext(
702
- "BranchPicker.Next",
703
- (s) => [s.message, s.branchState]
704
- );
705
- if (branchCount <= 1 || branchId + 1 >= branchCount)
709
+ const context = useMessageContext("BranchPicker.Next", (s) => {
710
+ const {
711
+ message: message2,
712
+ editState: { isEditing },
713
+ branchState: { branchId: branchId2, branchCount }
714
+ } = s;
715
+ if (isEditing || branchCount <= 1 || branchId2 + 1 >= branchCount)
716
+ return null;
717
+ return { message: message2, branchId: branchId2 };
718
+ });
719
+ if (!context)
706
720
  return null;
721
+ const { message, branchId } = context;
707
722
  return () => {
708
723
  switchToBranch(message, branchId + 1);
709
724
  };
@@ -718,12 +733,19 @@ var useGoToPreviousBranch = () => {
718
733
  "BranchPicker.Previous",
719
734
  (s) => s.chat.switchToBranch
720
735
  );
721
- const [message, { branchId, branchCount }] = useMessageContext(
722
- "BranchPicker.Previous",
723
- (s) => [s.message, s.branchState]
724
- );
725
- if (branchCount <= 1 || branchId <= 0)
736
+ const context = useMessageContext("BranchPicker.Previous", (s) => {
737
+ const {
738
+ message: message2,
739
+ editState: { isEditing },
740
+ branchState: { branchId: branchId2, branchCount }
741
+ } = s;
742
+ if (isEditing || branchCount <= 1 || branchId2 <= 0)
743
+ return null;
744
+ return { message: message2, branchId: branchId2 };
745
+ });
746
+ if (!context)
726
747
  return null;
748
+ const { message, branchId } = context;
727
749
  return () => {
728
750
  switchToBranch(message, branchId - 1);
729
751
  };
@@ -769,18 +791,27 @@ __export(actionBar_exports, {
769
791
  // src/primitives/actionBar/ActionBarRoot.tsx
770
792
  var import_react_primitive8 = require("@radix-ui/react-primitive");
771
793
  var import_react14 = require("react");
772
- var ActionBarRoot = (0, import_react14.forwardRef)(({ hideWhenEditing = false, ...rest }, ref) => {
773
- return /* @__PURE__ */ React.createElement(MessageIf, { editing: hideWhenEditing ? false : void 0 }, /* @__PURE__ */ React.createElement(import_react_primitive8.Primitive.div, { ...rest, ref }));
794
+ var ActionBarRoot = (0, import_react14.forwardRef)(({ hideWhenBusy, hideWhenNotLastOrHover, ...rest }, ref) => {
795
+ return /* @__PURE__ */ React.createElement(ThreadIf, { busy: hideWhenBusy ? false : void 0 }, /* @__PURE__ */ React.createElement(MessageIf, { lastOrHover: hideWhenNotLastOrHover ? true : void 0 }, /* @__PURE__ */ React.createElement(import_react_primitive8.Primitive.div, { ...rest, ref })));
774
796
  });
775
797
 
776
798
  // src/actions/useCopyMessage.tsx
777
799
  var useCopyMessage = ({ copiedDuration = 3e3 }) => {
778
- const [messageContent, setIsCopied] = useMessageContext(
779
- "ActionBar.Copy",
780
- (s) => [s.message.content, s.setIsCopied]
781
- );
800
+ const context = useMessageContext("ActionBar.Copy", (s) => {
801
+ const {
802
+ editState: { isEditing },
803
+ message: { content: content2 },
804
+ setIsCopied: setIsCopied2
805
+ } = s;
806
+ if (isEditing)
807
+ return null;
808
+ return { content: content2, setIsCopied: setIsCopied2 };
809
+ });
810
+ if (!context)
811
+ return null;
812
+ const { content, setIsCopied } = context;
782
813
  return () => {
783
- navigator.clipboard.writeText(messageContent);
814
+ navigator.clipboard.writeText(content);
784
815
  setIsCopied(true);
785
816
  setTimeout(() => setIsCopied(false), copiedDuration);
786
817
  };
@@ -795,8 +826,13 @@ var useReloadMessage = () => {
795
826
  s.chat.isLoading,
796
827
  s.chat.reloadAt
797
828
  ]);
798
- const message = useMessageContext("ActionBar.Reload", (s) => s.message);
799
- if (message.role !== "assistant" || isLoading)
829
+ const message = useMessageContext("ActionBar.Reload", (s) => {
830
+ const message2 = s.message;
831
+ if (message2.role !== "assistant" || isLoading)
832
+ return null;
833
+ return message2;
834
+ });
835
+ if (!message)
800
836
  return null;
801
837
  return () => reloadAt(message);
802
838
  };
@@ -806,14 +842,21 @@ var ActionBarReload = createActionButton(useReloadMessage);
806
842
 
807
843
  // src/actions/useBeginMessageEdit.tsx
808
844
  var useBeginMessageEdit = () => {
809
- const [editState, messageContent, setEditState] = useMessageContext(
810
- "ActionBar.Edit",
811
- (s) => [s.editState, s.message.content, s.setEditState]
812
- );
813
- if (editState.isEditing)
845
+ const context = useMessageContext("ActionBar.Edit", (s) => {
846
+ const {
847
+ message: { content: content2 },
848
+ editState: { isEditing },
849
+ setEditState: setEditState2
850
+ } = s;
851
+ if (isEditing)
852
+ return null;
853
+ return { content: content2, setEditState: setEditState2 };
854
+ });
855
+ if (!context)
814
856
  return null;
857
+ const { content, setEditState } = context;
815
858
  return () => {
816
- setEditState({ isEditing: true, value: messageContent });
859
+ setEditState({ isEditing: true, value: content });
817
860
  };
818
861
  };
819
862
 
@@ -832,28 +875,29 @@ __export(editBar_exports, {
832
875
  var import_react_primitive9 = require("@radix-ui/react-primitive");
833
876
  var import_react15 = require("react");
834
877
  var EditBarRoot = (0, import_react15.forwardRef)(
835
- ({ hideWhenNotEditing, ...rest }, ref) => {
836
- return /* @__PURE__ */ React.createElement(MessageIf, { editing: hideWhenNotEditing ? true : void 0 }, /* @__PURE__ */ React.createElement(import_react_primitive9.Primitive.div, { ...rest, ref }));
878
+ ({ ...rest }, ref) => {
879
+ return /* @__PURE__ */ React.createElement(import_react_primitive9.Primitive.div, { ...rest, ref });
837
880
  }
838
881
  );
839
882
 
840
883
  // src/actions/useSaveMessageEdit.tsx
841
884
  var useSaveMessageEdit = () => {
842
885
  const chat = useThreadContext("EditBar.Save", (s) => s.chat);
843
- const [editState, message, setEditState] = useMessageContext(
844
- "EditBar.Save",
845
- (s) => [s.editState, s.message, s.setEditState]
846
- );
847
- if (!editState.isEditing)
886
+ const context = useMessageContext("EditBar.Save", (s) => {
887
+ const { message: message2, editState, setEditState: setEditState2 } = s;
888
+ if (!editState.isEditing)
889
+ return null;
890
+ return { message: message2, content: editState.value, setEditState: setEditState2 };
891
+ });
892
+ if (!context)
848
893
  return null;
894
+ const { message, content, setEditState } = context;
849
895
  return () => {
850
- if (!editState.isEditing)
851
- return;
852
896
  chat.editAt(message, {
853
897
  ...message,
854
898
  id: void 0,
855
899
  // remove id to create a new message
856
- content: editState.value
900
+ content
857
901
  });
858
902
  setEditState({ isEditing: false });
859
903
  };
@@ -864,12 +908,18 @@ var EditBarSave = createActionButton(useSaveMessageEdit);
864
908
 
865
909
  // src/actions/useCancelMessageEdit.tsx
866
910
  var useCancelMessageEdit = () => {
867
- const [isEditing, setEditState] = useMessageContext("EditBar.Cancel", (s) => [
868
- s.editState.isEditing,
869
- s.setEditState
870
- ]);
871
- if (!isEditing)
911
+ const context = useMessageContext("EditBar.Cancel", (s) => {
912
+ const {
913
+ editState: { isEditing },
914
+ setEditState: setEditState2
915
+ } = s;
916
+ if (!isEditing)
917
+ return null;
918
+ return { setEditState: setEditState2 };
919
+ });
920
+ if (!context)
872
921
  return null;
922
+ const { setEditState } = context;
873
923
  return () => {
874
924
  setEditState({ isEditing: false });
875
925
  };
package/dist/index.mjs CHANGED
@@ -151,7 +151,6 @@ var useOnResizeContent = (ref, callback) => {
151
151
  return;
152
152
  const resizeObserver = new ResizeObserver(() => {
153
153
  callbackRef.current();
154
- console.log("resize observed");
155
154
  });
156
155
  const mutationObserver = new MutationObserver((mutations) => {
157
156
  for (const mutation of mutations) {
@@ -168,6 +167,7 @@ var useOnResizeContent = (ref, callback) => {
168
167
  }
169
168
  callbackRef.current();
170
169
  });
170
+ resizeObserver.observe(el);
171
171
  mutationObserver.observe(el, { childList: true });
172
172
  for (const child of el.children) {
173
173
  resizeObserver.observe(child);
@@ -330,6 +330,9 @@ var useChatWithBranches = (chat) => {
330
330
  [chat, getBranchState, switchToBranch, editAt, reloadAt]
331
331
  );
332
332
  };
333
+ var hasUpcomingMessage = (thread) => {
334
+ return thread.isLoading && thread.messages[thread.messages.length - 1]?.role !== "assistant";
335
+ };
333
336
 
334
337
  // src/primitives/message/index.ts
335
338
  var message_exports = {};
@@ -412,6 +415,10 @@ var MessageRoot = forwardRef3(
412
415
  );
413
416
 
414
417
  // src/primitives/message/MessageIf.tsx
418
+ var isLast = (thread, message) => {
419
+ const hasUpcoming = hasUpcomingMessage(thread);
420
+ return hasUpcoming ? message.id === UPCOMING_MESSAGE_ID : thread.messages[thread.messages.length - 1]?.id === message.id;
421
+ };
415
422
  var useMessageIf = (props) => {
416
423
  const thread = useThreadContext("Message.If", (s) => s.chat);
417
424
  return useMessageContext(
@@ -428,7 +435,7 @@ var useMessageIf = (props) => {
428
435
  return false;
429
436
  if (props.editing === false && isEditing)
430
437
  return false;
431
- if (props.unstable_hoveringOrLast === true && !isHovering && thread.messages[thread.messages.length - 1]?.id !== message.id)
438
+ if (props.lastOrHover === true && !isHovering && !isLast(thread, message))
432
439
  return false;
433
440
  if (props.copied === true && !isCopied)
434
441
  return false;
@@ -481,23 +488,24 @@ var MessageEditableContent = forwardRef4(({ onChange, value, ...rest }, forwarde
481
488
 
482
489
  // src/primitives/thread/ThreadMessages.tsx
483
490
  var getComponents = (components) => {
484
- if ("Message" in components) {
485
- return {
486
- UserMessage: components.Message,
487
- AssistantMessage: components.Message
488
- };
489
- }
490
- return components;
491
+ return {
492
+ EditingUserMessage: components.EditingUserMessage ?? components.UserMessage ?? components.Message,
493
+ UserMessage: components.UserMessage ?? components.Message,
494
+ AssistantMessage: components.AssistantMessage ?? components.Message
495
+ };
491
496
  };
492
497
  var ThreadMessages = ({ components }) => {
493
498
  const chat = useThreadContext("Thread.Messages", (s) => s.chat);
494
499
  const messages = chat.messages;
495
- const { UserMessage, AssistantMessage } = getComponents(components);
500
+ const { UserMessage, EditingUserMessage, AssistantMessage } = getComponents(components);
496
501
  if (messages.length === 0)
497
502
  return null;
498
- return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message) => {
499
- return /* @__PURE__ */ React.createElement(MessageProvider, { key: message.id, message }, message.role === "assistant" ? /* @__PURE__ */ React.createElement(AssistantMessage, null) : /* @__PURE__ */ React.createElement(UserMessage, null));
500
- }), chat.isLoading && chat.messages[chat.messages.length - 1]?.role !== "assistant" && /* @__PURE__ */ React.createElement(
503
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, messages.map((message, idx) => {
504
+ return (
505
+ // biome-ignore lint/suspicious/noArrayIndexKey: fixes a11y issues with branch navigation
506
+ /* @__PURE__ */ React.createElement(MessageProvider, { key: idx, message }, /* @__PURE__ */ React.createElement(MessageIf, { user: true, editing: false }, /* @__PURE__ */ React.createElement(UserMessage, null)), /* @__PURE__ */ React.createElement(MessageIf, { user: true, editing: true }, /* @__PURE__ */ React.createElement(EditingUserMessage, null)), /* @__PURE__ */ React.createElement(MessageIf, { assistant: true }, /* @__PURE__ */ React.createElement(AssistantMessage, null)))
507
+ );
508
+ }), hasUpcomingMessage(chat) && /* @__PURE__ */ React.createElement(
501
509
  MessageProvider,
502
510
  {
503
511
  message: {
@@ -671,12 +679,19 @@ var useGoToNextBranch = () => {
671
679
  "BranchPicker.Next",
672
680
  (s) => s.chat.switchToBranch
673
681
  );
674
- const [message, { branchId, branchCount }] = useMessageContext(
675
- "BranchPicker.Next",
676
- (s) => [s.message, s.branchState]
677
- );
678
- if (branchCount <= 1 || branchId + 1 >= branchCount)
682
+ const context = useMessageContext("BranchPicker.Next", (s) => {
683
+ const {
684
+ message: message2,
685
+ editState: { isEditing },
686
+ branchState: { branchId: branchId2, branchCount }
687
+ } = s;
688
+ if (isEditing || branchCount <= 1 || branchId2 + 1 >= branchCount)
689
+ return null;
690
+ return { message: message2, branchId: branchId2 };
691
+ });
692
+ if (!context)
679
693
  return null;
694
+ const { message, branchId } = context;
680
695
  return () => {
681
696
  switchToBranch(message, branchId + 1);
682
697
  };
@@ -691,12 +706,19 @@ var useGoToPreviousBranch = () => {
691
706
  "BranchPicker.Previous",
692
707
  (s) => s.chat.switchToBranch
693
708
  );
694
- const [message, { branchId, branchCount }] = useMessageContext(
695
- "BranchPicker.Previous",
696
- (s) => [s.message, s.branchState]
697
- );
698
- if (branchCount <= 1 || branchId <= 0)
709
+ const context = useMessageContext("BranchPicker.Previous", (s) => {
710
+ const {
711
+ message: message2,
712
+ editState: { isEditing },
713
+ branchState: { branchId: branchId2, branchCount }
714
+ } = s;
715
+ if (isEditing || branchCount <= 1 || branchId2 <= 0)
716
+ return null;
717
+ return { message: message2, branchId: branchId2 };
718
+ });
719
+ if (!context)
699
720
  return null;
721
+ const { message, branchId } = context;
700
722
  return () => {
701
723
  switchToBranch(message, branchId - 1);
702
724
  };
@@ -746,18 +768,27 @@ import {
746
768
  Primitive as Primitive8
747
769
  } from "@radix-ui/react-primitive";
748
770
  import { forwardRef as forwardRef10 } from "react";
749
- var ActionBarRoot = forwardRef10(({ hideWhenEditing = false, ...rest }, ref) => {
750
- return /* @__PURE__ */ React.createElement(MessageIf, { editing: hideWhenEditing ? false : void 0 }, /* @__PURE__ */ React.createElement(Primitive8.div, { ...rest, ref }));
771
+ var ActionBarRoot = forwardRef10(({ hideWhenBusy, hideWhenNotLastOrHover, ...rest }, ref) => {
772
+ return /* @__PURE__ */ React.createElement(ThreadIf, { busy: hideWhenBusy ? false : void 0 }, /* @__PURE__ */ React.createElement(MessageIf, { lastOrHover: hideWhenNotLastOrHover ? true : void 0 }, /* @__PURE__ */ React.createElement(Primitive8.div, { ...rest, ref })));
751
773
  });
752
774
 
753
775
  // src/actions/useCopyMessage.tsx
754
776
  var useCopyMessage = ({ copiedDuration = 3e3 }) => {
755
- const [messageContent, setIsCopied] = useMessageContext(
756
- "ActionBar.Copy",
757
- (s) => [s.message.content, s.setIsCopied]
758
- );
777
+ const context = useMessageContext("ActionBar.Copy", (s) => {
778
+ const {
779
+ editState: { isEditing },
780
+ message: { content: content2 },
781
+ setIsCopied: setIsCopied2
782
+ } = s;
783
+ if (isEditing)
784
+ return null;
785
+ return { content: content2, setIsCopied: setIsCopied2 };
786
+ });
787
+ if (!context)
788
+ return null;
789
+ const { content, setIsCopied } = context;
759
790
  return () => {
760
- navigator.clipboard.writeText(messageContent);
791
+ navigator.clipboard.writeText(content);
761
792
  setIsCopied(true);
762
793
  setTimeout(() => setIsCopied(false), copiedDuration);
763
794
  };
@@ -772,8 +803,13 @@ var useReloadMessage = () => {
772
803
  s.chat.isLoading,
773
804
  s.chat.reloadAt
774
805
  ]);
775
- const message = useMessageContext("ActionBar.Reload", (s) => s.message);
776
- if (message.role !== "assistant" || isLoading)
806
+ const message = useMessageContext("ActionBar.Reload", (s) => {
807
+ const message2 = s.message;
808
+ if (message2.role !== "assistant" || isLoading)
809
+ return null;
810
+ return message2;
811
+ });
812
+ if (!message)
777
813
  return null;
778
814
  return () => reloadAt(message);
779
815
  };
@@ -783,14 +819,21 @@ var ActionBarReload = createActionButton(useReloadMessage);
783
819
 
784
820
  // src/actions/useBeginMessageEdit.tsx
785
821
  var useBeginMessageEdit = () => {
786
- const [editState, messageContent, setEditState] = useMessageContext(
787
- "ActionBar.Edit",
788
- (s) => [s.editState, s.message.content, s.setEditState]
789
- );
790
- if (editState.isEditing)
822
+ const context = useMessageContext("ActionBar.Edit", (s) => {
823
+ const {
824
+ message: { content: content2 },
825
+ editState: { isEditing },
826
+ setEditState: setEditState2
827
+ } = s;
828
+ if (isEditing)
829
+ return null;
830
+ return { content: content2, setEditState: setEditState2 };
831
+ });
832
+ if (!context)
791
833
  return null;
834
+ const { content, setEditState } = context;
792
835
  return () => {
793
- setEditState({ isEditing: true, value: messageContent });
836
+ setEditState({ isEditing: true, value: content });
794
837
  };
795
838
  };
796
839
 
@@ -811,28 +854,29 @@ import {
811
854
  } from "@radix-ui/react-primitive";
812
855
  import { forwardRef as forwardRef11 } from "react";
813
856
  var EditBarRoot = forwardRef11(
814
- ({ hideWhenNotEditing, ...rest }, ref) => {
815
- return /* @__PURE__ */ React.createElement(MessageIf, { editing: hideWhenNotEditing ? true : void 0 }, /* @__PURE__ */ React.createElement(Primitive9.div, { ...rest, ref }));
857
+ ({ ...rest }, ref) => {
858
+ return /* @__PURE__ */ React.createElement(Primitive9.div, { ...rest, ref });
816
859
  }
817
860
  );
818
861
 
819
862
  // src/actions/useSaveMessageEdit.tsx
820
863
  var useSaveMessageEdit = () => {
821
864
  const chat = useThreadContext("EditBar.Save", (s) => s.chat);
822
- const [editState, message, setEditState] = useMessageContext(
823
- "EditBar.Save",
824
- (s) => [s.editState, s.message, s.setEditState]
825
- );
826
- if (!editState.isEditing)
865
+ const context = useMessageContext("EditBar.Save", (s) => {
866
+ const { message: message2, editState, setEditState: setEditState2 } = s;
867
+ if (!editState.isEditing)
868
+ return null;
869
+ return { message: message2, content: editState.value, setEditState: setEditState2 };
870
+ });
871
+ if (!context)
827
872
  return null;
873
+ const { message, content, setEditState } = context;
828
874
  return () => {
829
- if (!editState.isEditing)
830
- return;
831
875
  chat.editAt(message, {
832
876
  ...message,
833
877
  id: void 0,
834
878
  // remove id to create a new message
835
- content: editState.value
879
+ content
836
880
  });
837
881
  setEditState({ isEditing: false });
838
882
  };
@@ -843,12 +887,18 @@ var EditBarSave = createActionButton(useSaveMessageEdit);
843
887
 
844
888
  // src/actions/useCancelMessageEdit.tsx
845
889
  var useCancelMessageEdit = () => {
846
- const [isEditing, setEditState] = useMessageContext("EditBar.Cancel", (s) => [
847
- s.editState.isEditing,
848
- s.setEditState
849
- ]);
850
- if (!isEditing)
890
+ const context = useMessageContext("EditBar.Cancel", (s) => {
891
+ const {
892
+ editState: { isEditing },
893
+ setEditState: setEditState2
894
+ } = s;
895
+ if (!isEditing)
896
+ return null;
897
+ return { setEditState: setEditState2 };
898
+ });
899
+ if (!context)
851
900
  return null;
901
+ const { setEditState } = context;
852
902
  return () => {
853
903
  setEditState({ isEditing: false });
854
904
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": {
@@ -31,7 +31,7 @@
31
31
  "@radix-ui/react-compose-refs": "^1.0.1",
32
32
  "@radix-ui/react-primitive": "^1.0.3",
33
33
  "@radix-ui/react-slot": "^1.0.2",
34
- "ai": "^3.1.1",
34
+ "ai": "^3.1.8",
35
35
  "react-textarea-autosize": "^8.5.3",
36
36
  "use-sync-external-store": "^1.2.2"
37
37
  },