@liveblocks/react-ui 2.25.0-aiprivatebeta5 → 2.25.0-aiprivatebeta7

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 (199) hide show
  1. package/dist/_private/index.cjs +4 -0
  2. package/dist/_private/index.cjs.map +1 -1
  3. package/dist/_private/index.d.cts +31 -94
  4. package/dist/_private/index.d.ts +31 -94
  5. package/dist/_private/index.js +2 -0
  6. package/dist/_private/index.js.map +1 -1
  7. package/dist/components/AiChat.cjs +217 -0
  8. package/dist/components/AiChat.cjs.map +1 -0
  9. package/dist/components/AiChat.js +215 -0
  10. package/dist/components/AiChat.js.map +1 -0
  11. package/dist/components/Comment.cjs +2 -2
  12. package/dist/components/Comment.cjs.map +1 -1
  13. package/dist/components/Comment.js +1 -1
  14. package/dist/components/Comment.js.map +1 -1
  15. package/dist/components/Composer.cjs +1 -2
  16. package/dist/components/Composer.cjs.map +1 -1
  17. package/dist/components/Composer.js +1 -2
  18. package/dist/components/Composer.js.map +1 -1
  19. package/dist/components/internal/AiChatAssistantMessage.cjs +83 -124
  20. package/dist/components/internal/AiChatAssistantMessage.cjs.map +1 -1
  21. package/dist/components/internal/AiChatAssistantMessage.js +81 -122
  22. package/dist/components/internal/AiChatAssistantMessage.js.map +1 -1
  23. package/dist/components/internal/AiChatComposer.cjs +30 -266
  24. package/dist/components/internal/AiChatComposer.cjs.map +1 -1
  25. package/dist/components/internal/AiChatComposer.js +35 -267
  26. package/dist/components/internal/AiChatComposer.js.map +1 -1
  27. package/dist/components/internal/AiChatUserMessage.cjs +18 -168
  28. package/dist/components/internal/AiChatUserMessage.cjs.map +1 -1
  29. package/dist/components/internal/AiChatUserMessage.js +20 -170
  30. package/dist/components/internal/AiChatUserMessage.js.map +1 -1
  31. package/dist/constants.cjs +2 -0
  32. package/dist/constants.cjs.map +1 -1
  33. package/dist/constants.js +2 -1
  34. package/dist/constants.js.map +1 -1
  35. package/dist/icon.cjs +4 -0
  36. package/dist/icon.cjs.map +1 -1
  37. package/dist/icon.js +2 -0
  38. package/dist/icon.js.map +1 -1
  39. package/dist/icons/Copy.cjs +8 -9
  40. package/dist/icons/Copy.cjs.map +1 -1
  41. package/dist/icons/Copy.js +8 -9
  42. package/dist/icons/Copy.js.map +1 -1
  43. package/dist/icons/Retry.cjs +21 -0
  44. package/dist/icons/Retry.cjs.map +1 -0
  45. package/dist/icons/Retry.js +19 -0
  46. package/dist/icons/Retry.js.map +1 -0
  47. package/dist/icons/index.cjs +4 -0
  48. package/dist/icons/index.cjs.map +1 -1
  49. package/dist/icons/index.js +2 -0
  50. package/dist/icons/index.js.map +1 -1
  51. package/dist/index.cjs +1 -1
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +32 -43
  54. package/dist/index.d.ts +32 -43
  55. package/dist/index.js +1 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/overrides.cjs +10 -10
  58. package/dist/overrides.cjs.map +1 -1
  59. package/dist/overrides.js +10 -10
  60. package/dist/overrides.js.map +1 -1
  61. package/dist/primitives/AiChatComposer/index.cjs +203 -0
  62. package/dist/primitives/AiChatComposer/index.cjs.map +1 -0
  63. package/dist/primitives/AiChatComposer/index.js +196 -0
  64. package/dist/primitives/AiChatComposer/index.js.map +1 -0
  65. package/dist/primitives/Comment/index.cjs +2 -2
  66. package/dist/primitives/Comment/index.cjs.map +1 -1
  67. package/dist/primitives/Comment/index.js +1 -1
  68. package/dist/primitives/Comment/index.js.map +1 -1
  69. package/dist/primitives/Composer/index.cjs +19 -14
  70. package/dist/primitives/Composer/index.cjs.map +1 -1
  71. package/dist/primitives/Composer/index.js +18 -13
  72. package/dist/primitives/Composer/index.js.map +1 -1
  73. package/dist/{slate → primitives/Composer/slate}/plugins/auto-formatting.cjs +3 -3
  74. package/dist/primitives/Composer/slate/plugins/auto-formatting.cjs.map +1 -0
  75. package/dist/{slate → primitives/Composer/slate}/plugins/auto-formatting.js +3 -3
  76. package/dist/primitives/Composer/slate/plugins/auto-formatting.js.map +1 -0
  77. package/dist/{slate → primitives/Composer/slate}/plugins/auto-links.cjs +7 -2
  78. package/dist/primitives/Composer/slate/plugins/auto-links.cjs.map +1 -0
  79. package/dist/{slate → primitives/Composer/slate}/plugins/auto-links.js +8 -3
  80. package/dist/primitives/Composer/slate/plugins/auto-links.js.map +1 -0
  81. package/dist/{slate → primitives/Composer/slate}/plugins/custom-links.cjs +8 -3
  82. package/dist/primitives/Composer/slate/plugins/custom-links.cjs.map +1 -0
  83. package/dist/{slate → primitives/Composer/slate}/plugins/custom-links.js +9 -4
  84. package/dist/primitives/Composer/slate/plugins/custom-links.js.map +1 -0
  85. package/dist/{slate → primitives/Composer/slate}/plugins/mentions.cjs +9 -10
  86. package/dist/primitives/Composer/slate/plugins/mentions.cjs.map +1 -0
  87. package/dist/{slate → primitives/Composer/slate}/plugins/mentions.js +6 -6
  88. package/dist/primitives/Composer/slate/plugins/mentions.js.map +1 -0
  89. package/dist/{slate → primitives/Composer/slate}/plugins/paste.cjs +1 -1
  90. package/dist/primitives/Composer/slate/plugins/paste.cjs.map +1 -0
  91. package/dist/{slate → primitives/Composer/slate}/plugins/paste.js +1 -1
  92. package/dist/primitives/Composer/slate/plugins/paste.js.map +1 -0
  93. package/dist/primitives/Composer/utils.cjs +4 -4
  94. package/dist/primitives/Composer/utils.cjs.map +1 -1
  95. package/dist/primitives/Composer/utils.js +4 -4
  96. package/dist/primitives/Composer/utils.js.map +1 -1
  97. package/dist/primitives/index.cjs +2 -5
  98. package/dist/primitives/index.cjs.map +1 -1
  99. package/dist/primitives/index.d.cts +33 -62
  100. package/dist/primitives/index.d.ts +33 -62
  101. package/dist/primitives/index.js +6 -5
  102. package/dist/primitives/index.js.map +1 -1
  103. package/dist/primitives/internal/{Collapsible.cjs → Collapsible/index.cjs} +23 -17
  104. package/dist/primitives/internal/Collapsible/index.cjs.map +1 -0
  105. package/dist/primitives/internal/{Collapsible.js → Collapsible/index.js} +23 -17
  106. package/dist/primitives/internal/Collapsible/index.js.map +1 -0
  107. package/dist/primitives/slate/plugins/empty-clear-formatting.cjs.map +1 -0
  108. package/dist/primitives/slate/plugins/empty-clear-formatting.js.map +1 -0
  109. package/dist/{slate → primitives/slate}/plugins/normalize.cjs +0 -5
  110. package/dist/primitives/slate/plugins/normalize.cjs.map +1 -0
  111. package/dist/{slate → primitives/slate}/plugins/normalize.js +0 -5
  112. package/dist/primitives/slate/plugins/normalize.js.map +1 -0
  113. package/dist/primitives/slate/utils/get-character.cjs.map +1 -0
  114. package/dist/primitives/slate/utils/get-character.js.map +1 -0
  115. package/dist/primitives/slate/utils/get-dom-range.cjs.map +1 -0
  116. package/dist/primitives/slate/utils/get-dom-range.js.map +1 -0
  117. package/dist/primitives/slate/utils/get-match-range.cjs.map +1 -0
  118. package/dist/primitives/slate/utils/get-match-range.js.map +1 -0
  119. package/dist/primitives/slate/utils/is-empty-string.cjs.map +1 -0
  120. package/dist/primitives/slate/utils/is-empty-string.js.map +1 -0
  121. package/dist/primitives/slate/utils/is-empty.cjs.map +1 -0
  122. package/dist/primitives/slate/utils/is-empty.js.map +1 -0
  123. package/dist/primitives/slate/utils/is-text.cjs.map +1 -0
  124. package/dist/primitives/slate/utils/is-text.js.map +1 -0
  125. package/dist/primitives/slate/utils/is-whitespace-character.cjs.map +1 -0
  126. package/dist/primitives/slate/utils/is-whitespace-character.js.map +1 -0
  127. package/dist/{slate → primitives/slate}/utils/marks.cjs +9 -9
  128. package/dist/primitives/slate/utils/marks.cjs.map +1 -0
  129. package/dist/{slate → primitives/slate}/utils/marks.js +9 -9
  130. package/dist/primitives/slate/utils/marks.js.map +1 -0
  131. package/dist/primitives/slate/utils/selection-contains-inlines.cjs.map +1 -0
  132. package/dist/primitives/slate/utils/selection-contains-inlines.js.map +1 -0
  133. package/dist/version.cjs +1 -1
  134. package/dist/version.js +1 -1
  135. package/package.json +4 -4
  136. package/src/styles/index.css +119 -133
  137. package/src/styles/utils.css +7 -2
  138. package/styles.css +1 -1
  139. package/styles.css.map +1 -1
  140. package/dist/components/AiChat/AiChat.cjs +0 -211
  141. package/dist/components/AiChat/AiChat.cjs.map +0 -1
  142. package/dist/components/AiChat/AiChat.js +0 -209
  143. package/dist/components/AiChat/AiChat.js.map +0 -1
  144. package/dist/primitives/Chat/Composer/index.cjs +0 -323
  145. package/dist/primitives/Chat/Composer/index.cjs.map +0 -1
  146. package/dist/primitives/Chat/Composer/index.js +0 -315
  147. package/dist/primitives/Chat/Composer/index.js.map +0 -1
  148. package/dist/primitives/internal/Collapsible.cjs.map +0 -1
  149. package/dist/primitives/internal/Collapsible.js.map +0 -1
  150. package/dist/slate/plugins/auto-formatting.cjs.map +0 -1
  151. package/dist/slate/plugins/auto-formatting.js.map +0 -1
  152. package/dist/slate/plugins/auto-links.cjs.map +0 -1
  153. package/dist/slate/plugins/auto-links.js.map +0 -1
  154. package/dist/slate/plugins/custom-links.cjs.map +0 -1
  155. package/dist/slate/plugins/custom-links.js.map +0 -1
  156. package/dist/slate/plugins/empty-clear-formatting.cjs.map +0 -1
  157. package/dist/slate/plugins/empty-clear-formatting.js.map +0 -1
  158. package/dist/slate/plugins/mentions.cjs.map +0 -1
  159. package/dist/slate/plugins/mentions.js.map +0 -1
  160. package/dist/slate/plugins/normalize.cjs.map +0 -1
  161. package/dist/slate/plugins/normalize.js.map +0 -1
  162. package/dist/slate/plugins/paste.cjs.map +0 -1
  163. package/dist/slate/plugins/paste.js.map +0 -1
  164. package/dist/slate/utils/get-character.cjs.map +0 -1
  165. package/dist/slate/utils/get-character.js.map +0 -1
  166. package/dist/slate/utils/get-dom-range.cjs.map +0 -1
  167. package/dist/slate/utils/get-dom-range.js.map +0 -1
  168. package/dist/slate/utils/get-match-range.cjs.map +0 -1
  169. package/dist/slate/utils/get-match-range.js.map +0 -1
  170. package/dist/slate/utils/is-empty-string.cjs.map +0 -1
  171. package/dist/slate/utils/is-empty-string.js.map +0 -1
  172. package/dist/slate/utils/is-empty.cjs.map +0 -1
  173. package/dist/slate/utils/is-empty.js.map +0 -1
  174. package/dist/slate/utils/is-text.cjs.map +0 -1
  175. package/dist/slate/utils/is-text.js.map +0 -1
  176. package/dist/slate/utils/is-whitespace-character.cjs.map +0 -1
  177. package/dist/slate/utils/is-whitespace-character.js.map +0 -1
  178. package/dist/slate/utils/marks.cjs.map +0 -1
  179. package/dist/slate/utils/marks.js.map +0 -1
  180. package/dist/slate/utils/selection-contains-inlines.cjs.map +0 -1
  181. package/dist/slate/utils/selection-contains-inlines.js.map +0 -1
  182. /package/dist/{slate → primitives/slate}/plugins/empty-clear-formatting.cjs +0 -0
  183. /package/dist/{slate → primitives/slate}/plugins/empty-clear-formatting.js +0 -0
  184. /package/dist/{slate → primitives/slate}/utils/get-character.cjs +0 -0
  185. /package/dist/{slate → primitives/slate}/utils/get-character.js +0 -0
  186. /package/dist/{slate → primitives/slate}/utils/get-dom-range.cjs +0 -0
  187. /package/dist/{slate → primitives/slate}/utils/get-dom-range.js +0 -0
  188. /package/dist/{slate → primitives/slate}/utils/get-match-range.cjs +0 -0
  189. /package/dist/{slate → primitives/slate}/utils/get-match-range.js +0 -0
  190. /package/dist/{slate → primitives/slate}/utils/is-empty-string.cjs +0 -0
  191. /package/dist/{slate → primitives/slate}/utils/is-empty-string.js +0 -0
  192. /package/dist/{slate → primitives/slate}/utils/is-empty.cjs +0 -0
  193. /package/dist/{slate → primitives/slate}/utils/is-empty.js +0 -0
  194. /package/dist/{slate → primitives/slate}/utils/is-text.cjs +0 -0
  195. /package/dist/{slate → primitives/slate}/utils/is-text.js +0 -0
  196. /package/dist/{slate → primitives/slate}/utils/is-whitespace-character.cjs +0 -0
  197. /package/dist/{slate → primitives/slate}/utils/is-whitespace-character.js +0 -0
  198. /package/dist/{slate → primitives/slate}/utils/selection-contains-inlines.cjs +0 -0
  199. /package/dist/{slate → primitives/slate}/utils/selection-contains-inlines.js +0 -0
@@ -1,209 +0,0 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { kInternal } from '@liveblocks/core';
3
- import { useAiChatMessages, useClient } from '@liveblocks/react';
4
- import { useLayoutEffect } from '@liveblocks/react/_private';
5
- import { forwardRef, useRef, useState, useImperativeHandle, useEffect } from 'react';
6
- import { ChevronDownIcon } from '../../icons/ChevronDown.js';
7
- import { SpinnerIcon } from '../../icons/Spinner.js';
8
- import { useOverrides } from '../../overrides.js';
9
- import { classNames } from '../../utils/class-names.js';
10
- import { AiChatAssistantMessage } from '../internal/AiChatAssistantMessage.js';
11
- import { AiChatComposer } from '../internal/AiChatComposer.js';
12
- import { AiChatUserMessage } from '../internal/AiChatUserMessage.js';
13
-
14
- const MIN_DISTANCE_TO_BOTTOM = 50;
15
- const AiChat = forwardRef(function({
16
- chatId,
17
- copilotId,
18
- overrides,
19
- contexts = [],
20
- tools = {},
21
- className,
22
- ...props
23
- }, forwardedRef) {
24
- const { messages, isLoading, error } = useAiChatMessages(chatId);
25
- const $ = useOverrides(overrides);
26
- const containerRef = useRef(null);
27
- const [distanceToBottom, setDistanceToBottom] = useState(null);
28
- const client = useClient();
29
- useImperativeHandle(
30
- forwardedRef,
31
- () => containerRef.current,
32
- []
33
- );
34
- useEffect(() => {
35
- const unregister = contexts.map(
36
- (context) => client[kInternal].ai.registerChatContext(chatId, context)
37
- );
38
- return () => {
39
- unregister.forEach((unregister2) => unregister2());
40
- };
41
- }, [client, chatId, contexts]);
42
- useEffect(() => {
43
- Object.entries(tools).map(
44
- ([key, value]) => client[kInternal].ai.registerChatTool(chatId, key, value)
45
- );
46
- return () => {
47
- Object.entries(tools).map(
48
- ([key]) => client[kInternal].ai.unregisterChatTool(chatId, key)
49
- );
50
- };
51
- }, [client, chatId, tools]);
52
- useEffect(() => {
53
- const container = containerRef.current;
54
- if (container === null)
55
- return;
56
- function handleScrollChange() {
57
- const container2 = containerRef.current;
58
- if (container2 === null)
59
- return;
60
- setDistanceToBottom(
61
- container2.scrollHeight - container2.clientHeight - container2.scrollTop
62
- );
63
- }
64
- container.addEventListener("scroll", handleScrollChange);
65
- return () => {
66
- container.removeEventListener("scroll", handleScrollChange);
67
- };
68
- }, []);
69
- useEffect(() => {
70
- const container = containerRef.current;
71
- if (container === null)
72
- return;
73
- setDistanceToBottom(
74
- container.scrollHeight - container.clientHeight - container.scrollTop
75
- );
76
- }, [messages]);
77
- useEffect(() => {
78
- const container = containerRef.current;
79
- if (container === null)
80
- return;
81
- const distanceToBottom2 = container.scrollHeight - container.clientHeight - container.scrollTop;
82
- if (messages === void 0)
83
- return;
84
- const lastMessage = messages[messages.length - 1];
85
- if (lastMessage !== void 0 && lastMessage.role === "user") {
86
- container.scrollTo({
87
- top: container.scrollHeight,
88
- behavior: "smooth"
89
- });
90
- } else if (distanceToBottom2 <= MIN_DISTANCE_TO_BOTTOM) {
91
- container.scrollTo({
92
- top: container.scrollHeight,
93
- behavior: "smooth"
94
- });
95
- }
96
- }, [messages]);
97
- useEffect(() => {
98
- const container = containerRef.current;
99
- if (container === null)
100
- return;
101
- const observer = new ResizeObserver(() => {
102
- const container2 = containerRef.current;
103
- if (container2 === null)
104
- return;
105
- setDistanceToBottom(
106
- container2.scrollHeight - container2.clientHeight - container2.scrollTop
107
- );
108
- });
109
- observer.observe(container);
110
- return () => {
111
- observer.disconnect();
112
- };
113
- }, []);
114
- const scrollToBottomCallbackRef = useRef(void 0);
115
- if (scrollToBottomCallbackRef.current === void 0) {
116
- scrollToBottomCallbackRef.current = function() {
117
- const container = containerRef.current;
118
- if (container === null)
119
- return;
120
- container.scrollTo({
121
- top: container.scrollHeight,
122
- behavior: "instant"
123
- });
124
- };
125
- }
126
- return /* @__PURE__ */ jsxs("div", {
127
- ref: containerRef,
128
- ...props,
129
- className: classNames("lb-root lb-ai-chat", className),
130
- children: [
131
- isLoading ? /* @__PURE__ */ jsx("div", {
132
- className: "lb-ai-chat-loading lb-loading",
133
- children: /* @__PURE__ */ jsx(SpinnerIcon, {})
134
- }) : error !== void 0 ? /* @__PURE__ */ jsx("div", {
135
- className: "lb-ai-chat-error lb-error",
136
- children: $.GET_CHAT_MESSAGES_ERROR(error)
137
- }) : /* @__PURE__ */ jsx("div", {
138
- className: "lb-ai-chat-messages",
139
- children: /* @__PURE__ */ jsx(Messages, {
140
- messages,
141
- overrides: $,
142
- onDistanceToBottomChange: scrollToBottomCallbackRef.current
143
- })
144
- }),
145
- /* @__PURE__ */ jsxs("div", {
146
- className: "lb-ai-chat-footer",
147
- children: [
148
- /* @__PURE__ */ jsx("div", {
149
- className: "lb-ai-chat-footer-actions",
150
- children: /* @__PURE__ */ jsx("button", {
151
- className: "lb-ai-chat-scroll-button lb-button",
152
- "data-visible": distanceToBottom !== null && distanceToBottom > MIN_DISTANCE_TO_BOTTOM ? "" : void 0,
153
- "data-variant": "secondary",
154
- onClick: () => {
155
- const container = containerRef.current;
156
- if (container === null)
157
- return;
158
- container.scrollTo({
159
- top: container.scrollHeight,
160
- behavior: "smooth"
161
- });
162
- },
163
- children: /* @__PURE__ */ jsx("span", {
164
- className: "lb-icon-container",
165
- children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
166
- })
167
- })
168
- }),
169
- /* @__PURE__ */ jsx(AiChatComposer, {
170
- chatId,
171
- copilotId,
172
- className: "lb-ai-chat-composer",
173
- overrides: $
174
- }, chatId)
175
- ]
176
- })
177
- ]
178
- });
179
- });
180
- function Messages({
181
- messages,
182
- overrides,
183
- onDistanceToBottomChange
184
- }) {
185
- const $ = useOverrides(overrides);
186
- useLayoutEffect(() => {
187
- onDistanceToBottomChange();
188
- }, [onDistanceToBottomChange]);
189
- return messages.map((message) => {
190
- if (message.role === "user") {
191
- return /* @__PURE__ */ jsx(AiChatUserMessage, {
192
- message,
193
- overrides: $,
194
- className: "lb-ai-chat-messages-user-message"
195
- }, message.id);
196
- } else if (message.role === "assistant") {
197
- return /* @__PURE__ */ jsx(AiChatAssistantMessage, {
198
- message,
199
- overrides: $,
200
- className: "lb-ai-chat-messages-assistant-message"
201
- }, message.id);
202
- } else {
203
- return null;
204
- }
205
- });
206
- }
207
-
208
- export { AiChat };
209
- //# sourceMappingURL=AiChat.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AiChat.js","sources":["../../../src/components/AiChat/AiChat.tsx"],"sourcesContent":["import {\n type AiChatContext,\n type ClientToolDefinition,\n type CopilotId,\n kInternal,\n type UiChatMessage,\n} from \"@liveblocks/core\";\nimport { useAiChatMessages, useClient } from \"@liveblocks/react\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport {\n forwardRef,\n type HTMLAttributes,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\n\nimport { ChevronDownIcon } from \"../../icons/ChevronDown\";\nimport { SpinnerIcon } from \"../../icons/Spinner\";\nimport {\n type ChatComposerOverrides,\n type ChatMessageOverrides,\n type ChatOverrides,\n type GlobalOverrides,\n useOverrides,\n} from \"../../overrides\";\nimport { classNames } from \"../../utils/class-names\";\nimport { AiChatAssistantMessage } from \"../internal/AiChatAssistantMessage\";\nimport { AiChatComposer } from \"../internal/AiChatComposer\";\nimport { AiChatUserMessage } from \"../internal/AiChatUserMessage\";\n\n/**\n * The number of pixels from the bottom of the messages list to trigger the scroll to bottom.\n */\nconst MIN_DISTANCE_TO_BOTTOM = 50;\n\nexport type AiChatProps = HTMLAttributes<HTMLDivElement> & {\n /**\n * The id of the chat the composer belongs to.\n */\n chatId: string;\n /**\n * The id of the copilot to use to send the message.\n */\n copilotId?: string;\n /**\n * The contextual information to include in the chat. Used by the assistant when generating responses.\n */\n contexts?: AiChatContext[];\n /**\n * The contextual information to include in the chat. Used by the assistant when generating responses.\n */\n tools?: Record<string, ClientToolDefinition>;\n /**\n * Override the component's strings.\n */\n overrides?: Partial<\n GlobalOverrides &\n ChatMessageOverrides &\n ChatComposerOverrides &\n ChatOverrides\n >;\n};\nexport const AiChat = forwardRef<HTMLDivElement, AiChatProps>(function (\n {\n chatId,\n copilotId,\n overrides,\n contexts = [],\n tools = {},\n className,\n ...props\n },\n forwardedRef\n) {\n const { messages, isLoading, error } = useAiChatMessages(chatId);\n const $ = useOverrides(overrides);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const [distanceToBottom, setDistanceToBottom] = useState<number | null>(null);\n const client = useClient();\n\n useImperativeHandle<HTMLDivElement | null, HTMLDivElement | null>(\n forwardedRef,\n () => containerRef.current,\n []\n );\n\n // Add the provided contextual information to the chat on mount and remove on unmount\n // Note: 'contexts' will most likely be a new object on each render (unless user passes a stable object), but this won't be an issue as context addition and removal is a quick operation\n useEffect(() => {\n const unregister = contexts.map((context) =>\n client[kInternal].ai.registerChatContext(chatId, context)\n );\n return () => {\n unregister.forEach((unregister) => unregister());\n };\n }, [client, chatId, contexts]);\n\n // Register the provided tools to the chat on mount and unregister them on unmount\n useEffect(() => {\n Object.entries(tools).map(([key, value]) =>\n client[kInternal].ai.registerChatTool(chatId, key, value)\n );\n return () => {\n Object.entries(tools).map(([key]) =>\n client[kInternal].ai.unregisterChatTool(chatId, key)\n );\n };\n }, [client, chatId, tools]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n function handleScrollChange() {\n const container = containerRef.current;\n if (container === null) return;\n\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n }\n container.addEventListener(\"scroll\", handleScrollChange);\n return () => {\n container.removeEventListener(\"scroll\", handleScrollChange);\n };\n }, []);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n }, [messages]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const distanceToBottom =\n container.scrollHeight - container.clientHeight - container.scrollTop;\n\n if (messages === undefined) return;\n const lastMessage = messages[messages.length - 1];\n if (lastMessage !== undefined && lastMessage.role === \"user\") {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"smooth\",\n });\n } else if (distanceToBottom <= MIN_DISTANCE_TO_BOTTOM) {\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"smooth\",\n });\n }\n }, [messages]);\n\n useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n\n const observer = new ResizeObserver(() => {\n const container = containerRef.current;\n if (container === null) return;\n setDistanceToBottom(\n container.scrollHeight - container.clientHeight - container.scrollTop\n );\n });\n observer.observe(container);\n return () => {\n observer.disconnect();\n };\n }, []);\n\n const scrollToBottomCallbackRef = useRef<() => void>(undefined);\n if (scrollToBottomCallbackRef.current === undefined) {\n scrollToBottomCallbackRef.current = function () {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"instant\",\n });\n };\n }\n\n return (\n <div\n ref={containerRef}\n {...props}\n className={classNames(\"lb-root lb-ai-chat\", className)}\n >\n {isLoading ? (\n <div className=\"lb-ai-chat-loading lb-loading\">\n <SpinnerIcon />\n </div>\n ) : error !== undefined ? (\n <div className=\"lb-ai-chat-error lb-error\">\n {$.GET_CHAT_MESSAGES_ERROR(error)}\n </div>\n ) : (\n <div className=\"lb-ai-chat-messages\">\n <Messages\n messages={messages}\n overrides={$}\n onDistanceToBottomChange={scrollToBottomCallbackRef.current}\n />\n </div>\n )}\n\n <div className=\"lb-ai-chat-footer\">\n <div className=\"lb-ai-chat-footer-actions\">\n <button\n className=\"lb-ai-chat-scroll-button lb-button\"\n data-visible={\n distanceToBottom !== null &&\n distanceToBottom > MIN_DISTANCE_TO_BOTTOM\n ? \"\"\n : undefined\n }\n data-variant=\"secondary\"\n onClick={() => {\n const container = containerRef.current;\n if (container === null) return;\n\n container.scrollTo({\n top: container.scrollHeight,\n behavior: \"smooth\",\n });\n }}\n >\n <span className=\"lb-icon-container\">\n <ChevronDownIcon />\n </span>\n </button>\n </div>\n <AiChatComposer\n key={chatId}\n chatId={chatId}\n copilotId={copilotId as CopilotId}\n className=\"lb-ai-chat-composer\"\n overrides={$}\n />\n </div>\n </div>\n );\n});\n\nfunction Messages({\n messages,\n overrides,\n onDistanceToBottomChange,\n}: {\n messages: readonly UiChatMessage[];\n overrides: Partial<GlobalOverrides & ChatMessageOverrides>;\n onDistanceToBottomChange: () => void;\n}) {\n const $ = useOverrides(overrides);\n\n useLayoutEffect(() => {\n onDistanceToBottomChange();\n }, [onDistanceToBottomChange]);\n\n return messages.map((message) => {\n if (message.role === \"user\") {\n return (\n <AiChatUserMessage\n key={message.id}\n message={message}\n overrides={$}\n className=\"lb-ai-chat-messages-user-message\"\n />\n );\n } else if (message.role === \"assistant\") {\n return (\n <AiChatAssistantMessage\n key={message.id}\n message={message}\n overrides={$}\n className=\"lb-ai-chat-messages-assistant-message\"\n />\n );\n } else {\n return null;\n }\n });\n}\n"],"names":["unregister","container","distanceToBottom"],"mappings":"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"}
@@ -1,323 +0,0 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var core = require('@liveblocks/core');
5
- var react$1 = require('@liveblocks/react');
6
- var _private = require('@liveblocks/react/_private');
7
- var react = require('react');
8
- var slate = require('slate');
9
- var slateHistory = require('slate-history');
10
- var slateReact = require('slate-react');
11
- var normalize = require('../../../slate/plugins/normalize.cjs');
12
- var isEmpty = require('../../../slate/utils/is-empty.cjs');
13
- var utils = require('../../Composer/utils.cjs');
14
-
15
- const ComposerContext = react.createContext(null);
16
- const MAX_ATTACHMENTS = 10;
17
- const MAX_ATTACHMENT_SIZE = 1024 * 1024 * 1024;
18
- const Form = react.forwardRef(
19
- ({ onComposerSubmit, onSubmit, disabled, chatId, ...props }, forwardedRef) => {
20
- const formRef = react.useRef(null);
21
- const fileInputRef = react.useRef(null);
22
- const editorRef = react.useRef(
23
- null
24
- );
25
- if (editorRef.current === null) {
26
- editorRef.current = normalize.withNormalize(slateHistory.withHistory(slateReact.withReact(slate.createEditor())));
27
- }
28
- const editor = editorRef.current;
29
- const [isEditorEmpty, setIsEditorEmpty] = react.useState(true);
30
- const [attachments, setAttachments] = react.useState([]);
31
- const handleSubmit = react.useCallback(
32
- (event) => {
33
- if (disabled || isEmpty.isEmpty(editor, editor.children))
34
- return;
35
- onSubmit?.(event);
36
- if (onComposerSubmit === void 0 || event.isDefaultPrevented()) {
37
- event.preventDefault();
38
- return;
39
- }
40
- const content = editor.children.map((block) => {
41
- if ("type" in block && block.type === "paragraph") {
42
- return block.children.map((child) => {
43
- if ("text" in child) {
44
- return child.text;
45
- }
46
- return "";
47
- }).join("");
48
- }
49
- return "";
50
- }).join("\n");
51
- onComposerSubmit({ text: content }, event);
52
- if (event.isDefaultPrevented()) {
53
- return;
54
- }
55
- event.preventDefault();
56
- slate.Transforms.delete(editor, {
57
- at: {
58
- anchor: slate.Editor.start(editor, []),
59
- focus: slate.Editor.end(editor, [])
60
- }
61
- });
62
- },
63
- [disabled, editor, onSubmit, onComposerSubmit]
64
- );
65
- _private.useLayoutEffect(() => {
66
- setIsEditorEmpty(isEmpty.isEmpty(editor, editor.children));
67
- }, [editor]);
68
- const handleEditorValueChange = react.useCallback(() => {
69
- setIsEditorEmpty(isEmpty.isEmpty(editor, editor.children));
70
- }, [editor]);
71
- const requestFormSubmit = react.useCallback(() => {
72
- if (isEmpty.isEmpty(editor, editor.children))
73
- return;
74
- if (attachments.some((attachment) => attachment.status === "uploading")) {
75
- return;
76
- }
77
- requestAnimationFrame(() => {
78
- if (formRef.current === null)
79
- return;
80
- if (typeof formRef.current.requestSubmit === "function") {
81
- return formRef.current.requestSubmit();
82
- }
83
- const submitter = document.createElement("input");
84
- submitter.type = "submit";
85
- submitter.hidden = true;
86
- formRef.current.appendChild(submitter);
87
- submitter.click();
88
- formRef.current.removeChild(submitter);
89
- });
90
- }, [editor, attachments]);
91
- const handleAttachFiles = react.useCallback(() => {
92
- if (disabled)
93
- return;
94
- fileInputRef.current?.click();
95
- }, [disabled]);
96
- const handleRemoveAttachment = react.useCallback((id) => {
97
- setAttachments(
98
- (attachments2) => attachments2.filter((attachment) => attachment.id !== id)
99
- );
100
- }, []);
101
- react.useImperativeHandle(
102
- forwardedRef,
103
- () => formRef.current,
104
- []
105
- );
106
- const client = react$1.useClient();
107
- return /* @__PURE__ */ jsxRuntime.jsxs(ComposerContext.Provider, {
108
- value: {
109
- chatId,
110
- editor,
111
- onEditorValueChange: handleEditorValueChange,
112
- isEditorEmpty,
113
- requestFormSubmit,
114
- disabled: disabled || false,
115
- attachments,
116
- onAttachFiles: handleAttachFiles,
117
- onRemoveAttachment: handleRemoveAttachment,
118
- numOfAttachments: attachments.length
119
- },
120
- children: [
121
- /* @__PURE__ */ jsxRuntime.jsx("form", {
122
- onSubmit: handleSubmit,
123
- ...props,
124
- ref: formRef
125
- }),
126
- /* @__PURE__ */ jsxRuntime.jsx("input", {
127
- type: "file",
128
- multiple: true,
129
- accept: "image/png, image/jpeg",
130
- ref: fileInputRef,
131
- onClick: (event) => {
132
- event.stopPropagation();
133
- },
134
- onChange: function(event) {
135
- if (disabled)
136
- return;
137
- if (event.target.files === null)
138
- return;
139
- if (event.target.files.length === 0)
140
- return;
141
- for (const file of Array.from(event.target.files).slice(
142
- 0,
143
- MAX_ATTACHMENTS - attachments.length
144
- )) {
145
- const id = `at_${core.nanoid()}`;
146
- if (file.size > MAX_ATTACHMENT_SIZE) {
147
- setAttachments((attachments2) => [
148
- ...attachments2,
149
- {
150
- id,
151
- file,
152
- status: "error",
153
- error: new utils.AttachmentTooLargeError("File is too large.")
154
- }
155
- ]);
156
- continue;
157
- }
158
- setAttachments((attachments2) => [
159
- ...attachments2,
160
- {
161
- id,
162
- file,
163
- status: "uploading"
164
- }
165
- ]);
166
- client[core.kInternal].httpClient.uploadChatAttachment({
167
- chatId,
168
- attachment: {
169
- id,
170
- file
171
- }
172
- }).then(() => {
173
- setAttachments(
174
- (attachments2) => attachments2.map(
175
- (attachment) => attachment.id === id ? { ...attachment, status: "uploaded" } : attachment
176
- )
177
- );
178
- }).catch((error) => {
179
- if (error instanceof Error) {
180
- setAttachments(
181
- (attachments2) => attachments2.map(
182
- (attachment) => attachment.id === id ? {
183
- ...attachment,
184
- status: "error",
185
- error: error instanceof core.HttpError && error.status === 413 ? new utils.AttachmentTooLargeError(
186
- "File is too large"
187
- ) : error
188
- } : attachment
189
- )
190
- );
191
- }
192
- });
193
- }
194
- event.target.value = "";
195
- },
196
- tabIndex: -1,
197
- style: { display: "none" }
198
- })
199
- ]
200
- });
201
- }
202
- );
203
- const Editor = react.forwardRef(
204
- ({ defaultValue = "", onKeyDown, disabled, autoFocus, ...props }, forwardedRef) => {
205
- const context = react.useContext(ComposerContext);
206
- if (context === null) {
207
- throw new Error("Editor must be a descendant of Form.");
208
- }
209
- const {
210
- editor,
211
- onEditorValueChange,
212
- requestFormSubmit,
213
- disabled: isFormDisabled
214
- } = context;
215
- const handleKeyDown = react.useCallback(
216
- (event) => {
217
- onKeyDown?.(event);
218
- if (event.isDefaultPrevented())
219
- return;
220
- if (event.key === "Enter" && !event.shiftKey) {
221
- event.preventDefault();
222
- requestFormSubmit();
223
- } else if (event.key === "Enter" && event.shiftKey) {
224
- event.preventDefault();
225
- editor.insertBreak();
226
- }
227
- },
228
- [editor, onKeyDown, requestFormSubmit]
229
- );
230
- react.useImperativeHandle(
231
- forwardedRef,
232
- () => slateReact.ReactEditor.toDOMNode(editor, editor),
233
- [editor]
234
- );
235
- react.useEffect(() => {
236
- if (!autoFocus)
237
- return;
238
- try {
239
- if (!slateReact.ReactEditor.isFocused(editor)) {
240
- slate.Transforms.select(editor, slate.Editor.end(editor, []));
241
- slateReact.ReactEditor.focus(editor);
242
- }
243
- } catch {
244
- }
245
- }, [editor, autoFocus]);
246
- const initialValue = react.useMemo(() => {
247
- return defaultValue.split("\n").map((text) => ({ type: "paragraph", children: [{ text }] }));
248
- }, [defaultValue]);
249
- return /* @__PURE__ */ jsxRuntime.jsx(slateReact.Slate, {
250
- editor,
251
- initialValue,
252
- onValueChange: onEditorValueChange,
253
- children: /* @__PURE__ */ jsxRuntime.jsx(slateReact.Editable, {
254
- enterKeyHint: "send",
255
- autoCapitalize: "sentences",
256
- onKeyDown: handleKeyDown,
257
- "data-disabled": disabled || isFormDisabled || void 0,
258
- ...props,
259
- readOnly: disabled || isFormDisabled,
260
- disabled: disabled || isFormDisabled,
261
- renderPlaceholder: function({ attributes, children }) {
262
- const { opacity: _opacity, ...style } = attributes.style;
263
- return /* @__PURE__ */ jsxRuntime.jsx("span", {
264
- ...attributes,
265
- style,
266
- "data-placeholder": "",
267
- children
268
- });
269
- }
270
- })
271
- });
272
- }
273
- );
274
- const Submit = react.forwardRef(
275
- ({ disabled, ...props }, forwardedRef) => {
276
- const context = react.useContext(ComposerContext);
277
- if (context === null) {
278
- throw new Error("Submit must be a descendant of Form.");
279
- }
280
- const { disabled: isFormDisabled, isEditorEmpty, attachments } = context;
281
- return /* @__PURE__ */ jsxRuntime.jsx("button", {
282
- type: "submit",
283
- ...props,
284
- ref: forwardedRef,
285
- disabled: disabled || isFormDisabled || isEditorEmpty || attachments.some((attachment) => attachment.status === "uploading")
286
- });
287
- }
288
- );
289
- const AttachFiles = react.forwardRef(
290
- ({ onClick, disabled, ...props }, forwardedRef) => {
291
- const context = react.useContext(ComposerContext);
292
- if (context === null) {
293
- throw new Error("AttachFiles must be a descendant of Form.");
294
- }
295
- const {
296
- disabled: isFormDisabled,
297
- onAttachFiles,
298
- numOfAttachments
299
- } = context;
300
- return /* @__PURE__ */ jsxRuntime.jsx("button", {
301
- type: "button",
302
- ...props,
303
- onClick: function(event) {
304
- onClick?.(event);
305
- if (event.isDefaultPrevented())
306
- return;
307
- onAttachFiles();
308
- },
309
- onPointerDown: (event) => event.preventDefault(),
310
- ref: forwardedRef,
311
- disabled: isFormDisabled || disabled || numOfAttachments >= MAX_ATTACHMENTS
312
- });
313
- }
314
- );
315
-
316
- exports.AttachFiles = AttachFiles;
317
- exports.ComposerContext = ComposerContext;
318
- exports.Editor = Editor;
319
- exports.Form = Form;
320
- exports.MAX_ATTACHMENTS = MAX_ATTACHMENTS;
321
- exports.MAX_ATTACHMENT_SIZE = MAX_ATTACHMENT_SIZE;
322
- exports.Submit = Submit;
323
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../src/primitives/Chat/Composer/index.tsx"],"sourcesContent":["import { HttpError, kInternal, nanoid } from \"@liveblocks/core\";\nimport { useClient } from \"@liveblocks/react\";\nimport { useLayoutEffect } from \"@liveblocks/react/_private\";\nimport type {\n ButtonHTMLAttributes,\n FormEvent,\n FormHTMLAttributes,\n HTMLAttributes,\n KeyboardEvent,\n} from \"react\";\nimport {\n createContext,\n forwardRef,\n useCallback,\n useContext,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { BaseEditor, Descendant } from \"slate\";\nimport { createEditor, Editor as SlateEditor, Transforms } from \"slate\";\nimport type { HistoryEditor } from \"slate-history\";\nimport { withHistory } from \"slate-history\";\nimport { Editable, ReactEditor, Slate, withReact } from \"slate-react\";\n\nimport { withNormalize } from \"../../../slate/plugins/normalize\";\nimport { isEmpty } from \"../../../slate/utils/is-empty\";\nimport { AttachmentTooLargeError } from \"../../Composer/utils\";\n\n/* -------------------------------------------------------------------------------------------------\n * Form\n * -----------------------------------------------------------------------------------------------*/\nexport const ComposerContext = createContext<{\n chatId: string;\n\n editor: SlateEditor;\n onEditorValueChange: (value: Descendant[]) => void;\n isEditorEmpty: boolean;\n\n attachments: ({\n id: string;\n file: File;\n } & (\n | {\n status: \"uploading\" | \"uploaded\";\n }\n | {\n status: \"error\";\n error: Error;\n }\n ))[];\n onAttachFiles: () => void;\n onRemoveAttachment: (id: string) => void;\n numOfAttachments: number;\n\n requestFormSubmit: () => void;\n disabled: boolean;\n} | null>(null);\n\nexport const MAX_ATTACHMENTS = 10;\nexport const MAX_ATTACHMENT_SIZE = 1024 * 1024 * 1024; // 1 GB\n\nexport type FormProps = FormHTMLAttributes<HTMLFormElement> & {\n /**\n * The event handler called when a chat message is submitted.\n */\n onComposerSubmit?: (\n message: {\n /**\n * The submitted message text.\n */\n text: string;\n },\n event: FormEvent<HTMLFormElement>\n ) => void;\n /**\n * Whether the composer is disabled.\n */\n disabled?: boolean;\n /**\n * The id of the chat the composer belongs to.\n */\n chatId: string;\n};\n\n/**\n * Surrounds the chat composer's content and handles submissions.\n *\n * @example\n * <Form onComposerSubmit={({ text }) => {}}>\n *\t <Editor />\n * <Submit />\n * </Form>\n */\nexport const Form = forwardRef<HTMLFormElement, FormProps>(\n (\n { onComposerSubmit, onSubmit, disabled, chatId, ...props },\n forwardedRef\n ) => {\n const formRef = useRef<HTMLFormElement | null>(null);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n\n const editorRef = useRef<(BaseEditor & ReactEditor & HistoryEditor) | null>(\n null\n );\n if (editorRef.current === null) {\n editorRef.current = withNormalize(withHistory(withReact(createEditor())));\n }\n const editor = editorRef.current;\n\n const [isEditorEmpty, setIsEditorEmpty] = useState(true);\n\n const [attachments, setAttachments] = useState<\n ({\n id: string;\n file: File;\n } & (\n | {\n status: \"uploading\" | \"uploaded\";\n }\n | {\n status: \"error\";\n error: Error;\n }\n ))[]\n >([]);\n\n const handleSubmit = useCallback(\n (event: FormEvent<HTMLFormElement>) => {\n if (disabled || isEmpty(editor, editor.children)) return;\n\n onSubmit?.(event);\n\n if (onComposerSubmit === undefined || event.isDefaultPrevented()) {\n event.preventDefault();\n return;\n }\n\n // Extract the text content from the editor.\n const content = editor.children\n .map((block) => {\n if (\"type\" in block && block.type === \"paragraph\") {\n return block.children\n .map((child) => {\n if (\"text\" in child) {\n return child.text;\n }\n return \"\";\n })\n .join(\"\");\n }\n return \"\";\n })\n .join(\"\\n\");\n\n onComposerSubmit({ text: content }, event);\n\n if (event.isDefaultPrevented()) {\n return;\n }\n\n event.preventDefault();\n\n // Clear the editor after dispatching the message.\n Transforms.delete(editor, {\n at: {\n anchor: SlateEditor.start(editor, []),\n focus: SlateEditor.end(editor, []),\n },\n });\n },\n [disabled, editor, onSubmit, onComposerSubmit]\n );\n\n useLayoutEffect(() => {\n setIsEditorEmpty(isEmpty(editor, editor.children));\n }, [editor]);\n\n const handleEditorValueChange = useCallback(() => {\n setIsEditorEmpty(isEmpty(editor, editor.children));\n }, [editor]);\n\n const requestFormSubmit = useCallback(() => {\n if (isEmpty(editor, editor.children)) return;\n\n if (attachments.some((attachment) => attachment.status === \"uploading\")) {\n return;\n }\n\n // We need to wait for the next frame in some cases like when composing diacritics,\n // we want any native handling to be done first while still being handled on `keydown`.\n requestAnimationFrame(() => {\n if (formRef.current === null) return;\n if (typeof formRef.current.requestSubmit === \"function\") {\n return formRef.current.requestSubmit();\n }\n const submitter = document.createElement(\"input\");\n submitter.type = \"submit\";\n submitter.hidden = true;\n formRef.current.appendChild(submitter);\n submitter.click();\n formRef.current.removeChild(submitter);\n });\n }, [editor, attachments]);\n\n const handleAttachFiles = useCallback(() => {\n if (disabled) return;\n fileInputRef.current?.click();\n }, [disabled]);\n\n const handleRemoveAttachment = useCallback((id: string) => {\n setAttachments((attachments) =>\n attachments.filter((attachment) => attachment.id !== id)\n );\n }, []);\n\n useImperativeHandle<HTMLFormElement | null, HTMLFormElement | null>(\n forwardedRef,\n () => formRef.current,\n []\n );\n\n const client = useClient();\n\n return (\n <ComposerContext.Provider\n value={{\n chatId,\n editor,\n onEditorValueChange: handleEditorValueChange,\n isEditorEmpty,\n requestFormSubmit,\n disabled: disabled || false,\n attachments,\n onAttachFiles: handleAttachFiles,\n onRemoveAttachment: handleRemoveAttachment,\n numOfAttachments: attachments.length,\n }}\n >\n <form onSubmit={handleSubmit} {...props} ref={formRef} />\n <input\n type=\"file\"\n multiple\n accept=\"image/png, image/jpeg\"\n ref={fileInputRef}\n onClick={(event) => {\n event.stopPropagation();\n }}\n onChange={function (event) {\n if (disabled) return;\n\n if (event.target.files === null) return;\n if (event.target.files.length === 0) return;\n\n for (const file of Array.from(event.target.files).slice(\n 0,\n MAX_ATTACHMENTS - attachments.length\n )) {\n const id = `at_${nanoid()}`;\n if (file.size > MAX_ATTACHMENT_SIZE) {\n setAttachments((attachments) => [\n ...attachments,\n {\n id,\n file,\n status: \"error\",\n error: new AttachmentTooLargeError(\"File is too large.\"),\n },\n ]);\n continue;\n }\n\n setAttachments((attachments) => [\n ...attachments,\n {\n id,\n file,\n status: \"uploading\",\n },\n ]);\n\n client[kInternal].httpClient\n .uploadChatAttachment({\n chatId,\n attachment: {\n id,\n file,\n },\n })\n .then(() => {\n setAttachments((attachments) =>\n attachments.map((attachment) =>\n attachment.id === id\n ? { ...attachment, status: \"uploaded\" }\n : attachment\n )\n );\n })\n .catch((error) => {\n if (error instanceof Error) {\n setAttachments((attachments) =>\n attachments.map((attachment) =>\n attachment.id === id\n ? {\n ...attachment,\n status: \"error\",\n error:\n error instanceof HttpError &&\n error.status === 413\n ? new AttachmentTooLargeError(\n \"File is too large\"\n )\n : error,\n }\n : attachment\n )\n );\n }\n });\n }\n\n event.target.value = \"\";\n }}\n tabIndex={-1}\n style={{ display: \"none\" }}\n />\n </ComposerContext.Provider>\n );\n }\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Editor\n * -----------------------------------------------------------------------------------------------*/\nexport type EditorProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"defaultValue\"\n> & {\n /**\n * The editor's initial value.\n */\n defaultValue?: string;\n /**\n * The text to display when the editor is empty.\n */\n placeholder?: string;\n /**\n * Whether the editor is disabled.\n */\n disabled?: boolean;\n /**\n * Whether to focus the editor on mount.\n */\n autoFocus?: boolean;\n};\n\n/**\n * Displays the chat composer's editor.\n *\n * @example\n * <Editor placeholder=\"Write a message…\" />\n */\nexport const Editor = forwardRef<HTMLDivElement, EditorProps>(\n (\n { defaultValue = \"\", onKeyDown, disabled, autoFocus, ...props },\n forwardedRef\n ) => {\n const context = useContext(ComposerContext);\n if (context === null) {\n throw new Error(\"Editor must be a descendant of Form.\");\n }\n\n const {\n editor,\n onEditorValueChange,\n requestFormSubmit,\n disabled: isFormDisabled,\n } = context;\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.isDefaultPrevented()) return;\n\n if (event.key === \"Enter\" && !event.shiftKey) {\n event.preventDefault();\n requestFormSubmit();\n } else if (event.key === \"Enter\" && event.shiftKey) {\n event.preventDefault();\n editor.insertBreak();\n }\n },\n [editor, onKeyDown, requestFormSubmit]\n );\n\n useImperativeHandle(\n forwardedRef,\n () => ReactEditor.toDOMNode(editor, editor) as HTMLDivElement,\n [editor]\n );\n\n useEffect(() => {\n if (!autoFocus) return;\n\n try {\n if (!ReactEditor.isFocused(editor)) {\n Transforms.select(editor, SlateEditor.end(editor, []));\n ReactEditor.focus(editor);\n }\n } catch {\n // Slate's DOM-specific methods will throw if the editor's DOM node no longer exists. This action doesn't make sense on an unmounted editor so we can safely ignore it.\n }\n }, [editor, autoFocus]);\n\n const initialValue: { type: \"paragraph\"; children: { text: string }[] }[] =\n useMemo(() => {\n return defaultValue\n .split(\"\\n\")\n .map((text) => ({ type: \"paragraph\", children: [{ text }] }));\n }, [defaultValue]);\n\n return (\n <Slate\n editor={editor}\n initialValue={initialValue}\n onValueChange={onEditorValueChange}\n >\n <Editable\n enterKeyHint=\"send\"\n autoCapitalize=\"sentences\"\n onKeyDown={handleKeyDown}\n data-disabled={disabled || isFormDisabled || undefined}\n {...props}\n readOnly={disabled || isFormDisabled}\n disabled={disabled || isFormDisabled}\n renderPlaceholder={function ({ attributes, children }) {\n const { opacity: _opacity, ...style } = attributes.style;\n return (\n <span {...attributes} style={style} data-placeholder=\"\">\n {children}\n </span>\n );\n }}\n />\n </Slate>\n );\n }\n);\n\n/* -------------------------------------------------------------------------------------------------\n * Submit\n * -----------------------------------------------------------------------------------------------*/\nexport type SubmitProps = ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * A button to submit a chat message.\n *\n * @example\n * <ChatComposer.Submit>Send</ChatComposer.Submit>\n */\nexport const Submit = forwardRef<HTMLButtonElement, SubmitProps>(\n ({ disabled, ...props }, forwardedRef) => {\n const context = useContext(ComposerContext);\n if (context === null) {\n throw new Error(\"Submit must be a descendant of Form.\");\n }\n\n const { disabled: isFormDisabled, isEditorEmpty, attachments } = context;\n\n return (\n <button\n type=\"submit\"\n {...props}\n ref={forwardedRef}\n disabled={\n disabled ||\n isFormDisabled ||\n isEditorEmpty ||\n attachments.some((attachment) => attachment.status === \"uploading\")\n }\n />\n );\n }\n);\n\n/* -------------------------------------------------------------------------------------------------\n * AttachFiles\n * -----------------------------------------------------------------------------------------------*/\nexport type AttachFilesProps = ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * A button which opens a file picker to create attachments.\n *\n * @example\n * <Composer.AttachFiles>Attach files</Composer.AttachFiles>\n */\nexport const AttachFiles = forwardRef<HTMLButtonElement, AttachFilesProps>(\n ({ onClick, disabled, ...props }, forwardedRef) => {\n const context = useContext(ComposerContext);\n if (context === null) {\n throw new Error(\"AttachFiles must be a descendant of Form.\");\n }\n\n const {\n disabled: isFormDisabled,\n onAttachFiles,\n numOfAttachments,\n } = context;\n\n return (\n <button\n type=\"button\"\n {...props}\n onClick={function (event) {\n onClick?.(event);\n if (event.isDefaultPrevented()) return;\n onAttachFiles();\n }}\n onPointerDown={(event) => event.preventDefault()}\n ref={forwardedRef}\n disabled={\n isFormDisabled || disabled || numOfAttachments >= MAX_ATTACHMENTS\n }\n />\n );\n }\n);\n"],"names":["createContext","forwardRef","useRef","withNormalize","withHistory","withReact","createEditor","useState","useCallback","isEmpty","Transforms","SlateEditor","useLayoutEffect","attachments","useImperativeHandle","useClient","jsxs","jsx","nanoid","AttachmentTooLargeError","kInternal","HttpError","useContext","ReactEditor","useEffect","useMemo","Slate","Editable"],"mappings":"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"}