@algolia/satellite 2.3.0-rc.1 → 2.3.0-rc.3

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 (38) hide show
  1. package/dist/cjs/Fields/AutoComplete/AutoComplete.js +7 -5
  2. package/dist/cjs/Fields/AutoComplete/types.d.ts +8 -0
  3. package/dist/cjs/Fields/AutoComplete/utils.d.ts +1 -1
  4. package/dist/cjs/Fields/AutoComplete/utils.js +3 -2
  5. package/dist/cjs/Helpers/ShimmerText/ShimmerText.tailwind.js +1 -1
  6. package/dist/cjs/Layout/Chat/ChatContextAccordion/ChatContextAccordion.styles.d.ts +3 -3
  7. package/dist/cjs/Layout/Chat/ChatMessage/ChatMessage.styles.js +8 -2
  8. package/dist/cjs/Layout/Chat/ChatMessageError/ChatMessageError.js +2 -2
  9. package/dist/cjs/Layout/Chat/ChatMessageLoader/ChatMessageLoader.styles.js +1 -1
  10. package/dist/cjs/Layout/Chat/ChatMessages/ChatMessages.d.ts +6 -4
  11. package/dist/cjs/Layout/Chat/ChatMessages/ChatMessages.js +46 -18
  12. package/dist/cjs/Layout/Chat/ChatMessages/useLastMessageHeight.d.ts +2 -4
  13. package/dist/cjs/Layout/Chat/ChatMessages/useLastMessageHeight.js +15 -14
  14. package/dist/cjs/Layout/Chat/ChatPrompt/ChatPrompt.d.ts +19 -11
  15. package/dist/cjs/Layout/Chat/ChatPrompt/ChatPrompt.js +17 -3
  16. package/dist/cjs/Layout/Chat/ChatPrompt/ChatPrompt.styles.js +1 -1
  17. package/dist/cjs/Layout/Chat/ChatPrompt/useFocusTyping.d.ts +12 -0
  18. package/dist/cjs/Layout/Chat/ChatPrompt/useFocusTyping.js +60 -0
  19. package/dist/esm/Fields/AutoComplete/AutoComplete.js +7 -5
  20. package/dist/esm/Fields/AutoComplete/types.d.ts +8 -0
  21. package/dist/esm/Fields/AutoComplete/utils.d.ts +1 -1
  22. package/dist/esm/Fields/AutoComplete/utils.js +3 -2
  23. package/dist/esm/Helpers/ShimmerText/ShimmerText.tailwind.js +1 -1
  24. package/dist/esm/Layout/Chat/ChatContextAccordion/ChatContextAccordion.styles.d.ts +3 -3
  25. package/dist/esm/Layout/Chat/ChatMessage/ChatMessage.styles.js +8 -2
  26. package/dist/esm/Layout/Chat/ChatMessageError/ChatMessageError.js +1 -1
  27. package/dist/esm/Layout/Chat/ChatMessageLoader/ChatMessageLoader.styles.js +1 -1
  28. package/dist/esm/Layout/Chat/ChatMessages/ChatMessages.d.ts +6 -4
  29. package/dist/esm/Layout/Chat/ChatMessages/ChatMessages.js +46 -20
  30. package/dist/esm/Layout/Chat/ChatMessages/useLastMessageHeight.d.ts +2 -4
  31. package/dist/esm/Layout/Chat/ChatMessages/useLastMessageHeight.js +16 -15
  32. package/dist/esm/Layout/Chat/ChatPrompt/ChatPrompt.d.ts +19 -11
  33. package/dist/esm/Layout/Chat/ChatPrompt/ChatPrompt.js +17 -3
  34. package/dist/esm/Layout/Chat/ChatPrompt/ChatPrompt.styles.js +1 -1
  35. package/dist/esm/Layout/Chat/ChatPrompt/useFocusTyping.d.ts +12 -0
  36. package/dist/esm/Layout/Chat/ChatPrompt/useFocusTyping.js +54 -0
  37. package/dist/satellite.min.css +1 -1
  38. package/package.json +2 -2
@@ -88,6 +88,8 @@ var AutoComplete = exports.AutoComplete = /*#__PURE__*/(0, _react.forwardRef)(fu
88
88
  value = _ref.value,
89
89
  selectOnBlur = _ref.selectOnBlur,
90
90
  onChange = _ref.onChange,
91
+ _ref$allowDuplicates = _ref.allowDuplicates,
92
+ allowDuplicates = _ref$allowDuplicates === void 0 ? false : _ref$allowDuplicates,
91
93
  options = _ref.options,
92
94
  optionItemComponent = _ref.optionItemComponent,
93
95
  creatable = _ref.creatable,
@@ -155,7 +157,7 @@ var AutoComplete = exports.AutoComplete = /*#__PURE__*/(0, _react.forwardRef)(fu
155
157
  return !value ? [] : Array.isArray(value) ? value : [value];
156
158
  }, [value]);
157
159
  var items = (0, _react.useMemo)(function () {
158
- var results = (0, _utils.filter)(options !== null && options !== void 0 ? options : [], multiple ? selectedItems : [], inputValue);
160
+ var results = (0, _utils.filter)(options !== null && options !== void 0 ? options : [], multiple ? selectedItems : [], inputValue, allowDuplicates);
159
161
  var emptyInputValue = !inputValue || inputValue.trim().length === 0;
160
162
  if (creatable && !emptyInputValue) {
161
163
  results.unshift.apply(results, (0, _toConsumableArray2["default"])(createFromInputValue(options, inputValue)));
@@ -169,7 +171,7 @@ var AutoComplete = exports.AutoComplete = /*#__PURE__*/(0, _react.forwardRef)(fu
169
171
  });
170
172
  }
171
173
  return results;
172
- }, [creatable, createFromInputValue, inputValue, locale, maxItems, multiple, options, selectedItems, showAllItems]);
174
+ }, [creatable, createFromInputValue, inputValue, locale, maxItems, multiple, options, selectedItems, showAllItems, allowDuplicates]);
173
175
  var hasValue = !!selectedItems.length;
174
176
  var showClearButton = !disabled && clearable && hasValue;
175
177
  var multipleSelection = (0, _downshift.useMultipleSelection)({
@@ -178,7 +180,7 @@ var AutoComplete = exports.AutoComplete = /*#__PURE__*/(0, _react.forwardRef)(fu
178
180
  if (typeof changes.selectedItems === "undefined") {
179
181
  onChange(null, changes.type);
180
182
  } else if (multiple) {
181
- onChange((0, _uniqBy.uniqBy)(changes.selectedItems, function (i) {
183
+ onChange(allowDuplicates ? changes.selectedItems : (0, _uniqBy.uniqBy)(changes.selectedItems, function (i) {
182
184
  return i.value;
183
185
  }), changes.type);
184
186
  } else {
@@ -374,7 +376,7 @@ var AutoComplete = exports.AutoComplete = /*#__PURE__*/(0, _react.forwardRef)(fu
374
376
  option: option,
375
377
  editable: !disabled
376
378
  })
377
- }), String(option.value)) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Indicators.Tag, _objectSpread(_objectSpread({
379
+ }), "".concat(option.value, "-").concat(index)) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Indicators.Tag, _objectSpread(_objectSpread({
378
380
  onRemove: disabled ? undefined : function (evt) {
379
381
  evt.stopPropagation();
380
382
  multipleSelection.removeSelectedItem(option);
@@ -385,7 +387,7 @@ var AutoComplete = exports.AutoComplete = /*#__PURE__*/(0, _react.forwardRef)(fu
385
387
  index: index
386
388
  })), {}, {
387
389
  children: option.label
388
- }), String(option.value));
390
+ }), "".concat(option.value, "-").concat(index));
389
391
  }), shouldRenderCustomTemplate && renderValueTemplate({
390
392
  option: value,
391
393
  editable: !disabled
@@ -173,6 +173,10 @@ export interface AutoCompleteSingleProps<T extends Option = Option> extends Auto
173
173
  * The callback function that is called when the value of the `AutoComplete` changes.
174
174
  */
175
175
  onChange: (option: T | null, changeType?: AutoCompleteChangeTypesValue) => void;
176
+ /**
177
+ * Whether the `AutoComplete` allows duplicate selections (only in `multiple` mode).
178
+ */
179
+ allowDuplicates?: never;
176
180
  }
177
181
  declare type UseMultipleSelectionStateChangeTypesKey = keyof typeof UseMultipleSelectionStateChangeTypes;
178
182
  export declare type AutoCompleteChangeTypesValue = (typeof UseMultipleSelectionStateChangeTypes)[UseMultipleSelectionStateChangeTypesKey];
@@ -189,6 +193,10 @@ export interface AutoCompleteMultiProps<T extends Option = Option> extends AutoC
189
193
  * The callback function that is called when the value of the `AutoComplete` changes.
190
194
  */
191
195
  onChange: (option: T[] | null, changeType?: AutoCompleteChangeTypesValue) => void;
196
+ /**
197
+ * Whether the `AutoComplete` allows duplicate selections (only in `multiple` mode).
198
+ */
199
+ allowDuplicates?: boolean;
192
200
  }
193
201
  export declare type AutoCompleteProps<T extends Option = Option> = AutoCompleteMultiProps<T> | AutoCompleteSingleProps<T>;
194
202
  declare type OptionsValue = string | number | boolean;
@@ -4,5 +4,5 @@ export declare const defaultCreateFromInputValue: <T extends Option = Option>(op
4
4
  export declare const caseInsensitiveCreateFromInputValue: <T extends Option = Option>(options: T[] | undefined, inputValue: string) => Option[];
5
5
  export declare const DEFAULT_AUTOCOMPLETE_LOCALE: Required<AutoCompleteLocale>;
6
6
  export declare const optionToString: (option: Option | null | undefined) => string;
7
- export declare function filter<T extends Option = Option>(options: T[], selectedItems: T[], itemValue: string): T[];
7
+ export declare function filter<T extends Option = Option>(options: T[], selectedItems: T[], itemValue: string, allowDuplicates?: boolean): T[];
8
8
  export declare function inputValueFromProps<T extends Option = Option>(props: AutoCompleteProps<T>): string;
@@ -65,12 +65,13 @@ function needlesMatch(needles, option) {
65
65
  });
66
66
  }
67
67
  function filter(options, selectedItems, itemValue) {
68
+ var allowDuplicates = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
68
69
  var needles = itemValue.toLowerCase().trim().split(/\s+/);
69
70
  return options.filter(function (option) {
70
- return !selectedItems.some(function (_ref) {
71
+ return (allowDuplicates || !selectedItems.some(function (_ref) {
71
72
  var value = _ref.value;
72
73
  return value === option.value;
73
- }) && (option.bypassNeedleMatch || needlesMatch(needles, option));
74
+ })) && (option.bypassNeedleMatch || needlesMatch(needles, option));
74
75
  });
75
76
  }
76
77
  function inputValueFromProps(props) {
@@ -14,7 +14,7 @@ var shimmerTextPlugin = plugin(function (_ref) {
14
14
  "animation-duration": "3s",
15
15
  "animation-iteration-count": "infinite",
16
16
  "animation-name": "shimmer-text",
17
- background: "".concat(theme("colors.grey.900"), " linear-gradient(to right, ").concat(theme("colors.grey.900"), " 0%, #ffffffbf 40%, #ffffffbf 60%, ").concat(theme("colors.grey.900"), " 100%)"),
17
+ background: "".concat(theme("colors.grey.600"), " linear-gradient(to right, ").concat(theme("colors.grey.600"), " 0%, #ffffffbf 40%, #ffffffbf 60%, ").concat(theme("colors.grey.600"), " 100%)"),
18
18
  "-webkit-background-clip": "text",
19
19
  "background-clip": "text",
20
20
  "background-repeat": "no-repeat",
@@ -6,8 +6,8 @@ export declare const chatContextAccordionStyles: import("tailwind-variants").TVR
6
6
  title?: import("tailwind-merge").ClassNameValue;
7
7
  content?: import("tailwind-merge").ClassNameValue;
8
8
  item?: import("tailwind-merge").ClassNameValue;
9
- trigger?: import("tailwind-merge").ClassNameValue;
10
9
  iconBg?: import("tailwind-merge").ClassNameValue;
10
+ trigger?: import("tailwind-merge").ClassNameValue;
11
11
  titleWrapper?: import("tailwind-merge").ClassNameValue;
12
12
  };
13
13
  };
@@ -19,8 +19,8 @@ export declare const chatContextAccordionStyles: import("tailwind-variants").TVR
19
19
  title?: import("tailwind-merge").ClassNameValue;
20
20
  content?: import("tailwind-merge").ClassNameValue;
21
21
  item?: import("tailwind-merge").ClassNameValue;
22
- trigger?: import("tailwind-merge").ClassNameValue;
23
22
  iconBg?: import("tailwind-merge").ClassNameValue;
23
+ trigger?: import("tailwind-merge").ClassNameValue;
24
24
  titleWrapper?: import("tailwind-merge").ClassNameValue;
25
25
  };
26
26
  };
@@ -41,8 +41,8 @@ export declare const chatContextAccordionStyles: import("tailwind-variants").TVR
41
41
  title?: import("tailwind-merge").ClassNameValue;
42
42
  content?: import("tailwind-merge").ClassNameValue;
43
43
  item?: import("tailwind-merge").ClassNameValue;
44
- trigger?: import("tailwind-merge").ClassNameValue;
45
44
  iconBg?: import("tailwind-merge").ClassNameValue;
45
+ trigger?: import("tailwind-merge").ClassNameValue;
46
46
  titleWrapper?: import("tailwind-merge").ClassNameValue;
47
47
  };
48
48
  };
@@ -8,13 +8,13 @@ exports.chatMessageStyles = void 0;
8
8
  var _taggedTemplateLiteral2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteral"));
9
9
  var _satellitePrefixer = _interopRequireDefault(require("./../../../styles/helpers/satellitePrefixer"));
10
10
  var _tv = require("./../../../styles/helpers/tv");
11
- var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12, _templateObject13, _templateObject14, _templateObject15, _templateObject16, _templateObject17;
11
+ var _templateObject, _templateObject2, _templateObject3, _templateObject4, _templateObject5, _templateObject6, _templateObject7, _templateObject8, _templateObject9, _templateObject10, _templateObject11, _templateObject12, _templateObject13, _templateObject14, _templateObject15, _templateObject16, _templateObject17, _templateObject18;
12
12
  var chatMessageStyles = exports.chatMessageStyles = (0, _tv.tv)({
13
13
  slots: {
14
14
  base: (0, _satellitePrefixer["default"])(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2["default"])(["relative w-full scroll-mt-4 group/message"]))),
15
15
  container: (0, _satellitePrefixer["default"])(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["relative flex items-start group-data-[role=user]/message:max-w-[70%] gap-3"]))),
16
16
  leading: (0, _satellitePrefixer["default"])(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2["default"])(["inline-flex items-center justify-center"]))),
17
- content: (0, _satellitePrefixer["default"])(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col gap-3 group-data-[role=assistant]/message:grow overflow-x-auto"]))),
17
+ content: (0, _satellitePrefixer["default"])(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col gap-3 group-data-[role=assistant]/message:grow overflow-y-hidden overflow-x-auto"]))),
18
18
  message: (0, _satellitePrefixer["default"])(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2["default"])(["relative text-pretty typo-display-body"]))),
19
19
  actions: (0, _satellitePrefixer["default"])(_templateObject6 || (_templateObject6 = (0, _taggedTemplateLiteral2["default"])(["flex items-center gap-1"])))
20
20
  },
@@ -63,6 +63,12 @@ var chatMessageStyles = exports.chatMessageStyles = (0, _tv.tv)({
63
63
  className: {
64
64
  actions: (0, _satellitePrefixer["default"])(_templateObject17 || (_templateObject17 = (0, _taggedTemplateLiteral2["default"])(["opacity-0 group-hover/message:opacity-100 transition-opacity"])))
65
65
  }
66
+ }, {
67
+ actions: true,
68
+ side: "right",
69
+ className: {
70
+ actions: (0, _satellitePrefixer["default"])(_templateObject18 || (_templateObject18 = (0, _taggedTemplateLiteral2["default"])(["justify-end"])))
71
+ }
66
72
  }],
67
73
  defaultVariants: {
68
74
  variant: "subtle",
@@ -7,10 +7,10 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.ChatMessageError = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
10
- var _lucideReact = require("lucide-react");
11
10
  var _react = require("react");
12
11
  var _ChatMessageError = require("./ChatMessageError.styles");
13
12
  var _Actions = require("./../../../Actions");
13
+ var _Icons = require("./../../../Icons");
14
14
  var _Satellite = require("./../../../Satellite");
15
15
  var _jsxRuntime = require("react/jsx-runtime");
16
16
  var _excluded = ["renderError", "actions", "renderFooter", "locale", "onReload", "rtl", "className"];
@@ -57,7 +57,7 @@ var ChatMessageError = exports.ChatMessageError = /*#__PURE__*/(0, _react.forwar
57
57
  })
58
58
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Actions.Button, {
59
59
  variant: "primary",
60
- startIcon: _lucideReact.RotateCwIcon,
60
+ startIcon: _Icons.RotateCwIcon,
61
61
  onClick: onReload,
62
62
  children: locale.retry
63
63
  }), renderFooter]
@@ -14,7 +14,7 @@ var chatMessageLoaderStyles = exports.chatMessageLoaderStyles = (0, _tv.tv)({
14
14
  extend: _ChatMessage.chatMessageStyles,
15
15
  slots: {
16
16
  content: (0, _satellitePrefixer["default"])(_templateObject || (_templateObject = (0, _taggedTemplateLiteral2["default"])(["w-full"]))),
17
- message: (0, _satellitePrefixer["default"])(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col gap-2 typo-subdued"]))),
17
+ message: (0, _satellitePrefixer["default"])(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col gap-2"]))),
18
18
  skeletonWrapper: (0, _satellitePrefixer["default"])(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2["default"])(["flex flex-col gap-1"]))),
19
19
  skeleton: (0, _satellitePrefixer["default"])(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2["default"])(["h-4"])))
20
20
  }
@@ -6,10 +6,11 @@ import type { ChatMessageBase, ChatStatus } from "../../../Layout/Chat/types";
6
6
  export declare type ChatMessageLocale = {
7
7
  scrollToBottomText?: string;
8
8
  };
9
+ declare type ChatMessageWithoutContent<Message extends ChatMessageBase> = Omit<ChatMessageProps<Message>, "content">;
9
10
  export declare type ChatMessagesProps<Message extends ChatMessageBase = ChatMessageBase> = Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
10
11
  messages: Message[];
11
- userMessageProps?: Omit<ChatMessageProps<Message>, "content">;
12
- assistantMessageProps?: Omit<ChatMessageProps<Message>, "content">;
12
+ userMessageProps?: ChatMessageWithoutContent<Message> | ((message: Message) => ChatMessageWithoutContent<Message>);
13
+ assistantMessageProps?: ChatMessageWithoutContent<Message> | ((message: Message) => ChatMessageWithoutContent<Message>);
13
14
  loaderProps?: ChatMessageLoaderProps;
14
15
  errorProps?: Omit<ChatMessageErrorProps, "onReload">;
15
16
  renderMessage?: (message: Message) => ReactNode;
@@ -24,8 +25,8 @@ export declare type ChatMessagesProps<Message extends ChatMessageBase = ChatMess
24
25
  };
25
26
  export declare const ChatMessages: <Message extends ChatMessageBase = ChatMessageBase>(props: Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
26
27
  messages: Message[];
27
- userMessageProps?: Omit<ChatMessageProps<Message>, "content"> | undefined;
28
- assistantMessageProps?: Omit<ChatMessageProps<Message>, "content"> | undefined;
28
+ userMessageProps?: ChatMessageWithoutContent<Message> | ((message: Message) => ChatMessageWithoutContent<Message>) | undefined;
29
+ assistantMessageProps?: ChatMessageWithoutContent<Message> | ((message: Message) => ChatMessageWithoutContent<Message>) | undefined;
29
30
  loaderProps?: ChatMessageLoaderProps | undefined;
30
31
  errorProps?: Omit<ChatMessageErrorProps, "onReload"> | undefined;
31
32
  renderMessage?: ((message: Message) => ReactNode) | undefined;
@@ -40,3 +41,4 @@ export declare const ChatMessages: <Message extends ChatMessageBase = ChatMessag
40
41
  } & {
41
42
  ref?: Ref<HTMLDivElement> | undefined;
42
43
  }) => ReactElement | null;
44
+ export {};
@@ -9,12 +9,12 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
12
- var _lucideReact = require("lucide-react");
13
12
  var _react = require("react");
14
13
  var _useStickToBottom2 = require("use-stick-to-bottom");
15
14
  var _ChatMessages = require("./ChatMessages.styles");
16
15
  var _useLastMessageHeight = require("./useLastMessageHeight");
17
16
  var _Actions = require("./../../../Actions");
17
+ var _Icons = require("./../../../Icons");
18
18
  var _ChatMessage = require("./../ChatMessage");
19
19
  var _ChatMessageError = require("./../ChatMessageError");
20
20
  var _ChatMessageLoader = require("./../ChatMessageLoader");
@@ -26,6 +26,12 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
26
26
  var DEFAULT_CHAT_MESSAGE_LOCALE = {
27
27
  scrollToBottomText: "Scroll to bottom"
28
28
  };
29
+ function resolveProps(propsOrFn, message) {
30
+ if (typeof propsOrFn === "function") {
31
+ return propsOrFn(message);
32
+ }
33
+ return propsOrFn;
34
+ }
29
35
  var ChatMessagesBase = function ChatMessagesBase(_ref, forwardedRef) {
30
36
  var messages = _ref.messages,
31
37
  userMessageProps = _ref.userMessageProps,
@@ -47,15 +53,16 @@ var ChatMessagesBase = function ChatMessagesBase(_ref, forwardedRef) {
47
53
  var contextLocale = (0, _Satellite.useLocale)("chatMessage");
48
54
  var locale = _objectSpread(_objectSpread(_objectSpread({}, DEFAULT_CHAT_MESSAGE_LOCALE), contextLocale), propsLocale);
49
55
  var _useStickToBottom = (0, _useStickToBottom2.useStickToBottom)({
50
- resize: "smooth",
51
- initial: "smooth"
56
+ // @ts-expect-error - Types are wrong in use-stick-to-bottom
57
+ initial: "instant",
58
+ resize: "smooth"
52
59
  }),
53
60
  scrollRef = _useStickToBottom.scrollRef,
54
61
  contentRef = _useStickToBottom.contentRef,
55
62
  isAtBottom = _useStickToBottom.isAtBottom,
56
63
  scrollToBottom = _useStickToBottom.scrollToBottom;
57
64
  var styles = (0, _ChatMessages.chatMessagesStyles)();
58
- var messageRefs = (0, _react.useRef)(new Map());
65
+ var lastUserMessageRef = (0, _react.useRef)(null);
59
66
  var _useState = (0, _react.useState)(false),
60
67
  _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
61
68
  lastMessageSubmitted = _useState2[0],
@@ -63,19 +70,41 @@ var ChatMessagesBase = function ChatMessagesBase(_ref, forwardedRef) {
63
70
  var lastUserMessage = (0, _toConsumableArray2["default"])(messages).reverse().find(function (m) {
64
71
  return m.role === "user";
65
72
  });
66
- var lastUserMessageEl = lastUserMessage ? messageRefs.current.get(lastUserMessage.id) : undefined;
67
- var lastMessageHeight = (0, _useLastMessageHeight.useLastMessageHeight)(scrollRef, messages, lastUserMessageEl, lastMessageSubmitted, 24);
73
+ var lastMessageHeight = (0, _useLastMessageHeight.useLastMessageHeight)(scrollRef, lastUserMessageRef, messages, lastMessageSubmitted, 24);
74
+ var lastMessageId = (0, _react.useMemo)(function () {
75
+ var _messages;
76
+ return (_messages = messages[messages.length - 1]) === null || _messages === void 0 ? void 0 : _messages.id;
77
+ }, [messages]);
78
+ var getMessageProps = (0, _react.useCallback)(function (message) {
79
+ var propsResult;
80
+ if (message.role === "assistant") {
81
+ propsResult = resolveProps(assistantMessageProps, message);
82
+
83
+ // If the last assistant message is streaming, we don't want to render actions or footer
84
+ if (status === "streaming" && lastMessageId === message.id) {
85
+ propsResult = _objectSpread(_objectSpread({}, propsResult), {}, {
86
+ renderFooter: undefined,
87
+ renderActions: undefined,
88
+ actions: undefined
89
+ });
90
+ }
91
+ } else {
92
+ propsResult = resolveProps(userMessageProps, message);
93
+ }
94
+ return propsResult;
95
+ }, [assistantMessageProps, userMessageProps, status, lastMessageId]);
68
96
  (0, _react.useEffect)(function () {
69
- if (status !== "submitted" || !lastUserMessage) {
70
- return;
97
+ if (status === "submitted" && lastUserMessage) {
98
+ setLastMessageSubmitted(true);
71
99
  }
72
- setLastMessageSubmitted(true);
73
- }, [status, messages, lastUserMessage]);
100
+ }, [status, lastUserMessage]);
74
101
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", _objectSpread(_objectSpread({}, props), {}, {
75
102
  ref: forwardedRef,
76
103
  className: styles.base({
77
104
  className: className
78
105
  }),
106
+ role: "log",
107
+ "aria-live": "polite",
79
108
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
80
109
  ref: scrollRef,
81
110
  className: styles.scroll({
@@ -91,16 +120,15 @@ var ChatMessagesBase = function ChatMessagesBase(_ref, forwardedRef) {
91
120
  },
92
121
  children: [messages.map(function (message) {
93
122
  var isAssistant = message.role === "assistant";
123
+ var isLastUserMessage = (lastUserMessage === null || lastUserMessage === void 0 ? void 0 : lastUserMessage.id) === message.id;
94
124
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ChatMessage.ChatMessage, _objectSpread(_objectSpread({
95
- ref: function ref(el) {
96
- if (el) messageRefs.current.set(message.id, el);else messageRefs.current["delete"](message.id);
97
- },
125
+ ref: isLastUserMessage ? lastUserMessageRef : undefined,
98
126
  side: isAssistant ? "left" : "right",
99
- variant: isAssistant ? "subtle" : "neutral",
100
- content: renderMessage ? renderMessage(message) : message.content
101
- }, isAssistant ? assistantMessageProps : userMessageProps), {}, {
102
- "data-role": message.role,
127
+ variant: isAssistant ? "subtle" : "neutral"
128
+ }, getMessageProps(message)), {}, {
129
+ content: renderMessage ? renderMessage(message) : message.content,
103
130
  actionsExtraData: message,
131
+ "data-role": message.role,
104
132
  "data-key": message.id
105
133
  }), message.id);
106
134
  }), status === "submitted" && (renderLoader !== null && renderLoader !== void 0 ? renderLoader : /*#__PURE__*/(0, _jsxRuntime.jsx)(_ChatMessageLoader.ChatMessageLoader, _objectSpread({}, loaderProps))), status === "error" && (renderError !== null && renderError !== void 0 ? renderError : /*#__PURE__*/(0, _jsxRuntime.jsx)(_ChatMessageError.ChatMessageError, _objectSpread(_objectSpread({}, errorProps), {}, {
@@ -108,7 +136,7 @@ var ChatMessagesBase = function ChatMessagesBase(_ref, forwardedRef) {
108
136
  })))]
109
137
  })
110
138
  }), !hideScrollToBottom && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Actions.IconButton, {
111
- icon: _lucideReact.ChevronDownIcon,
139
+ icon: _Icons.ChevronDownIcon,
112
140
  title: locale.scrollToBottomText,
113
141
  size: "small",
114
142
  onClick: function onClick() {
@@ -1,10 +1,8 @@
1
1
  import type { RefObject } from "react";
2
+ import type { ChatMessageBase } from "../../../Layout/Chat/types";
2
3
  /**
3
4
  * React hook to compute the “fill” height below the last user message,
4
5
  * based on the scroll container’s height, the last user‐message element’s height,
5
6
  * and any CSS gap/padding offsets.
6
7
  */
7
- export declare function useLastMessageHeight(scrollRef: RefObject<HTMLElement>, messages: Array<{
8
- id: string;
9
- role: string;
10
- }>, lastUserMessageEl: HTMLElement | undefined, lastMessageSubmitted: boolean, spacingOffset?: number): number;
8
+ export declare function useLastMessageHeight(scrollRef: RefObject<HTMLElement>, lastUserMessageRef: RefObject<HTMLDivElement | null>, messages: ChatMessageBase[], lastMessageSubmitted: boolean, spacingOffset?: number): number;
@@ -12,29 +12,30 @@ var _react = require("react");
12
12
  * based on the scroll container’s height, the last user‐message element’s height,
13
13
  * and any CSS gap/padding offsets.
14
14
  */
15
- function useLastMessageHeight(scrollRef, messages, lastUserMessageEl, lastMessageSubmitted) {
15
+ function useLastMessageHeight(scrollRef, lastUserMessageRef, messages, lastMessageSubmitted) {
16
16
  var spacingOffset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
17
17
  var _useState = (0, _react.useState)(0),
18
18
  _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
19
19
  lastMessageHeight = _useState2[0],
20
20
  setLastMessageHeight = _useState2[1];
21
- var updateLastMessageHeight = function updateLastMessageHeight() {
22
- var scrollEl = scrollRef.current;
23
- if (!scrollEl || messages.length === 0 || !lastMessageSubmitted || !lastUserMessageEl) return;
24
-
25
- // Measure parent/container height
26
- var parentHeight = scrollEl.clientHeight;
21
+ var offsetsRef = (0, _react.useRef)(0);
22
+ function getStaticOffsets() {
23
+ if (offsetsRef.current || !scrollRef.current) return offsetsRef.current;
27
24
 
28
25
  // Compute any CSS gap/rowGap/padding offsets by reading computed style
29
- var computed = window.getComputedStyle(scrollEl);
26
+ var computed = window.getComputedStyle(scrollRef.current);
30
27
  var rowGapValue = parseFloat(computed.rowGap) || parseFloat(computed.gap) || 0;
31
28
  var paddingTop = parseFloat(computed.paddingTop) || 0;
32
29
  var paddingBottom = parseFloat(computed.paddingBottom) || 0;
33
- var totalOffset = spacingOffset + rowGapValue + paddingTop + paddingBottom;
34
-
35
- // The “remaining” height is parentHeight − lastMsgElem.offsetHeight − totalOffset
36
- var remaining = parentHeight - lastUserMessageEl.offsetHeight - totalOffset;
37
- setLastMessageHeight(Math.max(remaining, 0));
30
+ offsetsRef.current = spacingOffset + rowGapValue + paddingTop + paddingBottom;
31
+ return offsetsRef.current;
32
+ }
33
+ var updateLastMessageHeight = function updateLastMessageHeight() {
34
+ var scrollEl = scrollRef.current;
35
+ var lastUserMessageEl = lastUserMessageRef.current;
36
+ if (!scrollEl || messages.length === 0 || !lastMessageSubmitted || !lastUserMessageEl) return;
37
+ var height = Math.max(scrollEl.clientHeight - lastUserMessageEl.offsetHeight - getStaticOffsets(), 0);
38
+ setLastMessageHeight(height);
38
39
  };
39
40
 
40
41
  // Recompute whenever messages change and a new user message has just been submitted
@@ -42,6 +43,6 @@ function useLastMessageHeight(scrollRef, messages, lastUserMessageEl, lastMessag
42
43
  if (!lastMessageSubmitted) return;
43
44
  updateLastMessageHeight();
44
45
  // eslint-disable-next-line react-hooks/exhaustive-deps
45
- }, [messages, lastMessageSubmitted]);
46
+ }, [messages.length, lastMessageSubmitted]);
46
47
  return lastMessageHeight;
47
48
  }
@@ -1,5 +1,5 @@
1
1
  import type { FormEvent, KeyboardEvent, ReactNode } from "react";
2
- import type { TextAreaProps } from "../../../Fields";
2
+ import type { TextAreaAutoSizeProps } from "../../../Fields/TextAreaAutoSize/TextAreaAutoSize";
3
3
  import type { ChatStatus } from "../../../Layout/Chat/types";
4
4
  export declare type ChatPromptLocale = {
5
5
  textareaLabel?: string;
@@ -7,7 +7,7 @@ export declare type ChatPromptLocale = {
7
7
  stopResponseTooltip?: string;
8
8
  sendMessageTooltip?: string;
9
9
  };
10
- export declare type ChatPromptProps = Omit<TextAreaProps, "onSubmit"> & {
10
+ export declare type ChatPromptProps = Omit<TextAreaAutoSizeProps, "onSubmit"> & {
11
11
  /**
12
12
  * Content to render above the textarea (e.g., a title or instructions).
13
13
  */
@@ -30,6 +30,14 @@ export declare type ChatPromptProps = Omit<TextAreaProps, "onSubmit"> & {
30
30
  * - "error": An error occurred during the API request, preventing successful completion.
31
31
  */
32
32
  status?: ChatStatus;
33
+ /**
34
+ * Whether to automatically focus the textarea when the user starts typing.
35
+ */
36
+ autoFocusOnTyping?: boolean;
37
+ /**
38
+ * Optional locale.
39
+ */
40
+ locale?: ChatPromptLocale;
33
41
  /**
34
42
  * Callback invoked when the user submits the form, either by clicking
35
43
  * the submit button or pressing Enter (without Shift) inside the textarea.
@@ -39,12 +47,8 @@ export declare type ChatPromptProps = Omit<TextAreaProps, "onSubmit"> & {
39
47
  * Callback invoked when the user requests to stop the current chat response stream.
40
48
  */
41
49
  onStop?: () => void;
42
- /**
43
- * Optional locale.
44
- */
45
- locale?: ChatPromptLocale;
46
50
  };
47
- export declare const ChatPrompt: import("react").ForwardRefExoticComponent<Omit<TextAreaProps, "onSubmit"> & {
51
+ export declare const ChatPrompt: import("react").ForwardRefExoticComponent<Omit<TextAreaAutoSizeProps, "onSubmit"> & {
48
52
  /**
49
53
  * Content to render above the textarea (e.g., a title or instructions).
50
54
  */
@@ -67,6 +71,14 @@ export declare const ChatPrompt: import("react").ForwardRefExoticComponent<Omit<
67
71
  * - "error": An error occurred during the API request, preventing successful completion.
68
72
  */
69
73
  status?: ChatStatus | undefined;
74
+ /**
75
+ * Whether to automatically focus the textarea when the user starts typing.
76
+ */
77
+ autoFocusOnTyping?: boolean | undefined;
78
+ /**
79
+ * Optional locale.
80
+ */
81
+ locale?: ChatPromptLocale | undefined;
70
82
  /**
71
83
  * Callback invoked when the user submits the form, either by clicking
72
84
  * the submit button or pressing Enter (without Shift) inside the textarea.
@@ -76,8 +88,4 @@ export declare const ChatPrompt: import("react").ForwardRefExoticComponent<Omit<
76
88
  * Callback invoked when the user requests to stop the current chat response stream.
77
89
  */
78
90
  onStop?: (() => void) | undefined;
79
- /**
80
- * Optional locale.
81
- */
82
- locale?: ChatPromptLocale | undefined;
83
91
  } & import("react").RefAttributes<HTMLTextAreaElement>>;
@@ -8,16 +8,18 @@ exports.ChatPrompt = void 0;
8
8
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
10
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
11
- var _lucideReact = require("lucide-react");
12
11
  var _react = require("react");
13
12
  var _ChatPrompt = require("./ChatPrompt.styles");
13
+ var _useFocusTyping = require("./useFocusTyping");
14
14
  var _useTypewriter = require("./useTypewriter");
15
15
  var _Actions = require("./../../../Actions");
16
16
  var _TextAreaAutoSize = require("./../../../Fields/TextAreaAutoSize/TextAreaAutoSize");
17
+ var _Icons = require("./../../../Icons");
17
18
  var _Satellite = require("./../../../Satellite");
19
+ var _utils = require("./../../../utils");
18
20
  var _mergeRefs = require("./../../../utils/mergeRefs");
19
21
  var _jsxRuntime = require("react/jsx-runtime");
20
- var _excluded = ["className", "renderHeader", "children", "renderFooter", "onSubmit", "onStop", "placeholder", "placeholders", "status", "defaultValue", "value", "locale"];
22
+ var _excluded = ["className", "renderHeader", "children", "renderFooter", "onSubmit", "onStop", "placeholder", "placeholders", "status", "autoFocusOnTyping", "defaultValue", "value", "locale", "id"];
21
23
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
22
24
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
23
25
  var DEFAULT_CHAT_PROMPT_LOCALE = {
@@ -39,12 +41,18 @@ var ChatPrompt = exports.ChatPrompt = /*#__PURE__*/(0, _react.forwardRef)(functi
39
41
  placeholders = _ref$placeholders === void 0 ? [] : _ref$placeholders,
40
42
  _ref$status = _ref.status,
41
43
  status = _ref$status === void 0 ? "ready" : _ref$status,
44
+ autoFocusOnTyping = _ref.autoFocusOnTyping,
42
45
  defaultValue = _ref.defaultValue,
43
46
  valueProp = _ref.value,
44
47
  propsLocale = _ref.locale,
48
+ propId = _ref.id,
45
49
  props = (0, _objectWithoutProperties2["default"])(_ref, _excluded);
46
50
  var contextLocale = (0, _Satellite.useLocale)("chatPrompt");
47
51
  var locale = _objectSpread(_objectSpread(_objectSpread({}, DEFAULT_CHAT_PROMPT_LOCALE), contextLocale), propsLocale);
52
+
53
+ // eslint-disable-next-line @algolia/stl/prefer-stl-helper
54
+ var generatedId = (0, _utils.uniqueId)("stl-chat-prompt-");
55
+ var textareaId = propId !== null && propId !== void 0 ? propId : generatedId;
48
56
  var internalRef = (0, _react.useRef)(null);
49
57
  var styles = (0, _ChatPrompt.chatPromptStyles)();
50
58
  var _useState = (0, _react.useState)(defaultValue !== null && defaultValue !== void 0 ? defaultValue : ""),
@@ -58,6 +66,10 @@ var ChatPrompt = exports.ChatPrompt = /*#__PURE__*/(0, _react.forwardRef)(functi
58
66
  var buttonDisabled = !hasValue && !canStop;
59
67
  var dynamicPlaceholder = (0, _useTypewriter.useTypewriter)(placeholders, !hasValue);
60
68
  var computedPlaceholder = placeholders.length > 0 ? dynamicPlaceholder : staticPlaceholder;
69
+ (0, _useFocusTyping.useFocusOnTyping)(internalRef, {
70
+ enabled: autoFocusOnTyping,
71
+ strictChars: true
72
+ });
61
73
  var submit = function submit(e) {
62
74
  e.preventDefault();
63
75
  if (!hasValue || canStop) {
@@ -79,6 +91,7 @@ var ChatPrompt = exports.ChatPrompt = /*#__PURE__*/(0, _react.forwardRef)(functi
79
91
  (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 || _internalRef$current.focus();
80
92
  },
81
93
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextAreaAutoSize.TextAreaAutoSize, _objectSpread(_objectSpread({
94
+ id: textareaId,
82
95
  ref: (0, _mergeRefs.mergeRefs)([forwardedRef, internalRef]),
83
96
  rows: 2,
84
97
  maxRows: 8,
@@ -86,6 +99,7 @@ var ChatPrompt = exports.ChatPrompt = /*#__PURE__*/(0, _react.forwardRef)(functi
86
99
  value: value,
87
100
  "aria-label": (_ref2 = placeholders[0] ? placeholders[0] : staticPlaceholder) !== null && _ref2 !== void 0 ? _ref2 : locale.textareaLabel,
88
101
  translate: "no",
102
+ autoComplete: "off",
89
103
  onInput: function onInput(e) {
90
104
  var _props$onInput;
91
105
  if (!isControlled) {
@@ -117,7 +131,7 @@ var ChatPrompt = exports.ChatPrompt = /*#__PURE__*/(0, _react.forwardRef)(functi
117
131
  onStop === null || onStop === void 0 || onStop();
118
132
  }
119
133
  },
120
- icon: canStop ? _lucideReact.CircleStopIcon : _lucideReact.ArrowUpIcon,
134
+ icon: canStop ? _Icons.StopCircleIcon : _Icons.ArrowUpIcon,
121
135
  variant: canStop ? "neutral" : "primary",
122
136
  size: "small",
123
137
  title: buttonDisabled ? locale.emptyMessageTooltip : canStop ? locale.stopResponseTooltip : locale.sendMessageTooltip,
@@ -15,7 +15,7 @@ var chatPromptStyles = exports.chatPromptStyles = (0, _tv.tv)({
15
15
  header: (0, _satellitePrefixer["default"])(_templateObject2 || (_templateObject2 = (0, _taggedTemplateLiteral2["default"])(["flex items-center gap-1.5"]))),
16
16
  body: (0, _satellitePrefixer["default"])(_templateObject3 || (_templateObject3 = (0, _taggedTemplateLiteral2["default"])([""]))),
17
17
  textarea: (0, _satellitePrefixer["default"])(_templateObject4 || (_templateObject4 = (0, _taggedTemplateLiteral2["default"])(["[&>textarea]:p-3 [&>textarea]:pb-0 [&>textarea]:thin-scrollbar"]))),
18
- actions: (0, _satellitePrefixer["default"])(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2["default"])(["flex flex-row p-3 pt-2 justify-end"]))),
18
+ actions: (0, _satellitePrefixer["default"])(_templateObject5 || (_templateObject5 = (0, _taggedTemplateLiteral2["default"])(["flex flex-row p-3 pt-2 justify-end cursor-text"]))),
19
19
  submit: (0, _satellitePrefixer["default"])(_templateObject6 || (_templateObject6 = (0, _taggedTemplateLiteral2["default"])([""]))),
20
20
  footer: (0, _satellitePrefixer["default"])(_templateObject7 || (_templateObject7 = (0, _taggedTemplateLiteral2["default"])(["flex items-center justify-between gap-1.5"])))
21
21
  }
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ declare type Editable = HTMLTextAreaElement | HTMLInputElement | HTMLElement;
3
+ interface Options {
4
+ enabled?: boolean;
5
+ strictChars?: boolean;
6
+ }
7
+ /**
8
+ * Focus `editableRef` the moment the user types anywhere on the page,
9
+ * *unless* their cursor is already inside an editable control.
10
+ */
11
+ export declare function useFocusOnTyping<E extends Editable = Editable>(editableRef: React.RefObject<E>, { enabled, strictChars }?: Options): void;
12
+ export {};