@rolder/kit 3.0.0-alpha.7 → 3.0.0-alpha.8

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 (263) hide show
  1. package/package.json +1 -4
  2. package/rslib.config.ts +21 -0
  3. package/src/ai/ui/conversation/ConversationContext.ts +21 -0
  4. package/src/ai/ui/conversation/ConversationProvider.tsx +21 -0
  5. package/src/ai/ui/conversation/Empty.tsx +15 -0
  6. package/src/ai/ui/conversation/File.tsx +40 -0
  7. package/src/ai/ui/conversation/FileIcon.tsx +143 -0
  8. package/src/ai/ui/conversation/Loader.tsx +8 -0
  9. package/src/ai/ui/conversation/Message.tsx +34 -0
  10. package/src/ai/ui/conversation/Root.tsx +24 -0
  11. package/src/ai/ui/conversation/index.ts +16 -0
  12. package/{dist/ai/ui/conversation/types.d.ts → src/ai/ui/conversation/types.ts} +5 -4
  13. package/src/ai/ui/conversation/useChatMessage.ts +13 -0
  14. package/src/ai/ui/promptInput/File.tsx +98 -0
  15. package/src/ai/ui/promptInput/FileIcon.tsx +149 -0
  16. package/src/ai/ui/promptInput/Footer.tsx +5 -0
  17. package/src/ai/ui/promptInput/PromptInputContext.ts +24 -0
  18. package/src/ai/ui/promptInput/PromptInputProvider.tsx +54 -0
  19. package/src/ai/ui/promptInput/Root.tsx +29 -0
  20. package/src/ai/ui/promptInput/Submit.tsx +39 -0
  21. package/src/ai/ui/promptInput/Textarea.tsx +39 -0
  22. package/src/ai/ui/promptInput/index.ts +15 -0
  23. package/src/ai/ui/promptInput/types.ts +9 -0
  24. package/src/ai/utils/convertFileUIPartBlobToDataURL.ts +29 -0
  25. package/src/ai/utils/parseAiMessagePart.ts +19 -0
  26. package/src/app/AppDefaults.tsx +21 -0
  27. package/src/app/DefaultApp.tsx +50 -0
  28. package/src/app/cookieColorSchemeManager.ts +70 -0
  29. package/src/app/defaultRequestMiddlewares.ts +22 -0
  30. package/src/app/defaultTheme.ts +22 -0
  31. package/src/functions/getCookie.ts +36 -0
  32. package/src/functions/setCookie.ts +29 -0
  33. package/src/functions/setCookies.ts +24 -0
  34. package/src/hooks/useMutation.ts +14 -0
  35. package/src/hooks/useMutationWithInvalidate.ts +23 -0
  36. package/{dist/index.d.ts → src/index.ts} +45 -5
  37. package/{dist → src}/styles.css +21 -11
  38. package/src/surreal/connection.ts +72 -0
  39. package/src/surreal/deafaultCrud.ts +25 -0
  40. package/src/surreal/deserialize.ts +144 -0
  41. package/src/surreal/encryption.ts +51 -0
  42. package/src/ui/AnimatedChevron.tsx +32 -0
  43. package/src/ui/JsonInput.tsx +52 -0
  44. package/src/ui/RouterLink.tsx +78 -0
  45. package/src/ui/editor/Content.tsx +11 -0
  46. package/src/ui/editor/Provider.tsx +96 -0
  47. package/src/ui/editor/Root.tsx +25 -0
  48. package/src/ui/editor/Toolbar.tsx +92 -0
  49. package/src/ui/editor/index.ts +13 -0
  50. package/src/ui/editor/types.ts +7 -0
  51. package/src/ui/error/DefaultError.tsx +60 -0
  52. package/src/ui/error/DefaultNotFound.tsx +19 -0
  53. package/src/ui/error/Forbidden.tsx +18 -0
  54. package/src/ui/error/defaultErrorNotification.ts +9 -0
  55. package/src/ui/form/blurOnError.ts +21 -0
  56. package/src/ui/form/buttons/CancelButton.tsx +42 -0
  57. package/src/ui/form/buttons/SubmitButton.tsx +43 -0
  58. package/src/ui/form/buttons/SubscribeActionIcon.tsx +18 -0
  59. package/src/ui/form/buttons/SubscribeButton.tsx +17 -0
  60. package/src/ui/form/context.ts +45 -0
  61. package/src/ui/form/fields/JsonField.tsx +16 -0
  62. package/src/ui/form/fields/MultiSelectField.tsx +17 -0
  63. package/src/ui/form/fields/NumberField.tsx +17 -0
  64. package/src/ui/form/fields/PassowrdField.tsx +20 -0
  65. package/src/ui/form/fields/SelectField.tsx +17 -0
  66. package/src/ui/form/fields/SwitchField.tsx +17 -0
  67. package/src/ui/form/fields/TextField.tsx +17 -0
  68. package/src/ui/form/fields/TextPassowrdField.tsx +51 -0
  69. package/src/ui/form/fields/TextareaField.tsx +17 -0
  70. package/src/ui/form/fieldsSchema.ts +24 -0
  71. package/src/ui/hoverPaper/HoverPaper.tsx +17 -0
  72. package/src/ui/hoverPaper/usePaperHover.ts +9 -0
  73. package/src/ui/saveInput/JsonInput.tsx +40 -0
  74. package/src/ui/saveInput/NumberInput.tsx +40 -0
  75. package/src/ui/saveInput/SaveInput.tsx +15 -0
  76. package/src/ui/saveInput/Select.tsx +41 -0
  77. package/src/ui/saveInput/Switch.tsx +46 -0
  78. package/src/ui/saveInput/TextInput.tsx +40 -0
  79. package/src/ui/saveInput/Textarea.tsx +40 -0
  80. package/src/ui/scrollArea/ARCH.md +204 -0
  81. package/src/ui/scrollArea/README.md +369 -0
  82. package/{dist/ui/scrollArea/ScrollArea.d.ts → src/ui/scrollArea/ScrollArea.tsx} +41 -10
  83. package/src/ui/scrollArea/ScrollAreaButton.tsx +56 -0
  84. package/src/ui/scrollArea/ScrollAreaContent.tsx +36 -0
  85. package/{dist/ui/scrollArea/context.d.ts → src/ui/scrollArea/context.tsx} +18 -3
  86. package/src/ui/scrollArea/index.ts +10 -0
  87. package/src/ui/scrollArea/types.ts +77 -0
  88. package/src/ui/scrollArea/useScrollArea.ts +227 -0
  89. package/tsconfig.json +14 -0
  90. package/dist/ai/ui/conversation/ConversationContext.d.ts +0 -7
  91. package/dist/ai/ui/conversation/ConversationContext.js +0 -8
  92. package/dist/ai/ui/conversation/ConversationProvider.d.ts +0 -2
  93. package/dist/ai/ui/conversation/ConversationProvider.js +0 -14
  94. package/dist/ai/ui/conversation/Empty.d.ts +0 -1
  95. package/dist/ai/ui/conversation/Empty.js +0 -21
  96. package/dist/ai/ui/conversation/File.d.ts +0 -4
  97. package/dist/ai/ui/conversation/File.js +0 -42
  98. package/dist/ai/ui/conversation/FileIcon.d.ts +0 -3
  99. package/dist/ai/ui/conversation/FileIcon.js +0 -225
  100. package/dist/ai/ui/conversation/Loader.d.ts +0 -2
  101. package/dist/ai/ui/conversation/Loader.js +0 -12
  102. package/dist/ai/ui/conversation/Message.d.ts +0 -4
  103. package/dist/ai/ui/conversation/Message.js +0 -25
  104. package/dist/ai/ui/conversation/Root.d.ts +0 -2
  105. package/dist/ai/ui/conversation/Root.js +0 -26
  106. package/dist/ai/ui/conversation/index.d.ts +0 -13
  107. package/dist/ai/ui/conversation/index.js +0 -14
  108. package/dist/ai/ui/conversation/types.js +0 -0
  109. package/dist/ai/ui/conversation/useChatMessage.d.ts +0 -2
  110. package/dist/ai/ui/conversation/useChatMessage.js +0 -12
  111. package/dist/ai/ui/promptInput/File.d.ts +0 -2
  112. package/dist/ai/ui/promptInput/File.js +0 -117
  113. package/dist/ai/ui/promptInput/FileIcon.d.ts +0 -3
  114. package/dist/ai/ui/promptInput/FileIcon.js +0 -225
  115. package/dist/ai/ui/promptInput/Footer.d.ts +0 -2
  116. package/dist/ai/ui/promptInput/Footer.js +0 -8
  117. package/dist/ai/ui/promptInput/PromptInputContext.d.ts +0 -12
  118. package/dist/ai/ui/promptInput/PromptInputContext.js +0 -8
  119. package/dist/ai/ui/promptInput/PromptInputProvider.d.ts +0 -2
  120. package/dist/ai/ui/promptInput/PromptInputProvider.js +0 -50
  121. package/dist/ai/ui/promptInput/Root.d.ts +0 -3
  122. package/dist/ai/ui/promptInput/Root.js +0 -17
  123. package/dist/ai/ui/promptInput/Submit.d.ts +0 -2
  124. package/dist/ai/ui/promptInput/Submit.js +0 -40
  125. package/dist/ai/ui/promptInput/Textarea.d.ts +0 -2
  126. package/dist/ai/ui/promptInput/Textarea.js +0 -33
  127. package/dist/ai/ui/promptInput/index.d.ts +0 -8
  128. package/dist/ai/ui/promptInput/index.js +0 -13
  129. package/dist/ai/ui/promptInput/types.d.ts +0 -11
  130. package/dist/ai/ui/promptInput/types.js +0 -0
  131. package/dist/ai/utils/convertFileUIPartBlobToDataURL.d.ts +0 -5
  132. package/dist/ai/utils/convertFileUIPartBlobToDataURL.js +0 -21
  133. package/dist/ai/utils/parseAiMessagePart.d.ts +0 -2
  134. package/dist/ai/utils/parseAiMessagePart.js +0 -12
  135. package/dist/app/AppDefaults.d.ts +0 -3
  136. package/dist/app/AppDefaults.js +0 -27
  137. package/dist/app/DefaultApp.d.ts +0 -6
  138. package/dist/app/DefaultApp.js +0 -43
  139. package/dist/app/cookieColorSchemeManager.d.ts +0 -6
  140. package/dist/app/cookieColorSchemeManager.js +0 -46
  141. package/dist/app/defaultRequestMiddlewares.d.ts +0 -4
  142. package/dist/app/defaultRequestMiddlewares.js +0 -24
  143. package/dist/app/defaultTheme.d.ts +0 -141
  144. package/dist/app/defaultTheme.js +0 -24
  145. package/dist/functions/getCookie.d.ts +0 -3
  146. package/dist/functions/getCookie.js +0 -8
  147. package/dist/functions/setCookie.d.ts +0 -10
  148. package/dist/functions/setCookie.js +0 -19
  149. package/dist/functions/setCookies.d.ts +0 -14
  150. package/dist/functions/setCookies.js +0 -13
  151. package/dist/hooks/useMutation.d.ts +0 -4
  152. package/dist/hooks/useMutation.js +0 -8
  153. package/dist/hooks/useMutationWithInvalidate.d.ts +0 -4
  154. package/dist/hooks/useMutationWithInvalidate.js +0 -16
  155. package/dist/index.js +0 -26
  156. package/dist/surreal/connection.d.ts +0 -9
  157. package/dist/surreal/connection.js +0 -49
  158. package/dist/surreal/deafaultCrud.d.ts +0 -2
  159. package/dist/surreal/deafaultCrud.js +0 -18
  160. package/dist/surreal/deserialize.d.ts +0 -17
  161. package/dist/surreal/deserialize.js +0 -46
  162. package/dist/surreal/encryption.d.ts +0 -6
  163. package/dist/surreal/encryption.js +0 -30
  164. package/dist/ui/AnimatedChevron.d.ts +0 -6
  165. package/dist/ui/AnimatedChevron.js +0 -31
  166. package/dist/ui/JsonInput.d.ts +0 -2
  167. package/dist/ui/JsonInput.js +0 -45
  168. package/dist/ui/RouterLink.d.ts +0 -16
  169. package/dist/ui/RouterLink.js +0 -36
  170. package/dist/ui/editor/Content.d.ts +0 -3
  171. package/dist/ui/editor/Content.js +0 -13
  172. package/dist/ui/editor/Provider.d.ts +0 -17
  173. package/dist/ui/editor/Provider.js +0 -80
  174. package/dist/ui/editor/Root.d.ts +0 -2
  175. package/dist/ui/editor/Root.js +0 -18
  176. package/dist/ui/editor/Toolbar.d.ts +0 -5
  177. package/dist/ui/editor/Toolbar.js +0 -156
  178. package/dist/ui/editor/index.d.ts +0 -12
  179. package/dist/ui/editor/index.js +0 -11
  180. package/dist/ui/editor/types.d.ts +0 -7
  181. package/dist/ui/editor/types.js +0 -0
  182. package/dist/ui/error/DefaultError.d.ts +0 -2
  183. package/dist/ui/error/DefaultError.js +0 -62
  184. package/dist/ui/error/DefaultNotFound.d.ts +0 -1
  185. package/dist/ui/error/DefaultNotFound.js +0 -37
  186. package/dist/ui/error/Forbidden.d.ts +0 -1
  187. package/dist/ui/error/Forbidden.js +0 -32
  188. package/dist/ui/error/defaultErrorNotification.d.ts +0 -1
  189. package/dist/ui/error/defaultErrorNotification.js +0 -8
  190. package/dist/ui/error/index.js +0 -5
  191. package/dist/ui/form/blurOnError.d.ts +0 -4
  192. package/dist/ui/form/blurOnError.js +0 -11
  193. package/dist/ui/form/buttons/CancelButton.d.ts +0 -5
  194. package/dist/ui/form/buttons/CancelButton.js +0 -44
  195. package/dist/ui/form/buttons/SubmitButton.d.ts +0 -5
  196. package/dist/ui/form/buttons/SubmitButton.js +0 -47
  197. package/dist/ui/form/buttons/SubscribeActionIcon.d.ts +0 -4
  198. package/dist/ui/form/buttons/SubscribeActionIcon.js +0 -15
  199. package/dist/ui/form/buttons/SubscribeButton.d.ts +0 -5
  200. package/dist/ui/form/buttons/SubscribeButton.js +0 -16
  201. package/dist/ui/form/buttons/index.js +0 -4
  202. package/dist/ui/form/context.d.ts +0 -83
  203. package/dist/ui/form/context.js +0 -26
  204. package/dist/ui/form/fields/JsonField.d.ts +0 -2
  205. package/dist/ui/form/fields/JsonField.js +0 -13
  206. package/dist/ui/form/fields/MultiSelectField.d.ts +0 -2
  207. package/dist/ui/form/fields/MultiSelectField.js +0 -15
  208. package/dist/ui/form/fields/NumberField.d.ts +0 -2
  209. package/dist/ui/form/fields/NumberField.js +0 -15
  210. package/dist/ui/form/fields/PassowrdField.d.ts +0 -2
  211. package/dist/ui/form/fields/PassowrdField.js +0 -18
  212. package/dist/ui/form/fields/SelectField.d.ts +0 -2
  213. package/dist/ui/form/fields/SelectField.js +0 -15
  214. package/dist/ui/form/fields/SwitchField.d.ts +0 -2
  215. package/dist/ui/form/fields/SwitchField.js +0 -15
  216. package/dist/ui/form/fields/TextField.d.ts +0 -2
  217. package/dist/ui/form/fields/TextField.js +0 -15
  218. package/dist/ui/form/fields/TextPassowrdField.d.ts +0 -2
  219. package/dist/ui/form/fields/TextPassowrdField.js +0 -51
  220. package/dist/ui/form/fields/TextareaField.d.ts +0 -2
  221. package/dist/ui/form/fields/TextareaField.js +0 -15
  222. package/dist/ui/form/fields/index.js +0 -9
  223. package/dist/ui/form/fieldsSchema.d.ts +0 -12
  224. package/dist/ui/form/fieldsSchema.js +0 -13
  225. package/dist/ui/form/index.js +0 -4
  226. package/dist/ui/hoverPaper/HoverPaper.d.ts +0 -6
  227. package/dist/ui/hoverPaper/HoverPaper.js +0 -15
  228. package/dist/ui/hoverPaper/index.js +0 -3
  229. package/dist/ui/hoverPaper/usePaperHover.d.ts +0 -4
  230. package/dist/ui/hoverPaper/usePaperHover.js +0 -9
  231. package/dist/ui/saveInput/JsonInput.d.ts +0 -6
  232. package/dist/ui/saveInput/JsonInput.js +0 -34
  233. package/dist/ui/saveInput/NumberInput.d.ts +0 -6
  234. package/dist/ui/saveInput/NumberInput.js +0 -27
  235. package/dist/ui/saveInput/SaveInput.d.ts +0 -36
  236. package/dist/ui/saveInput/SaveInput.js +0 -15
  237. package/dist/ui/saveInput/Select.d.ts +0 -6
  238. package/dist/ui/saveInput/Select.js +0 -27
  239. package/dist/ui/saveInput/Switch.d.ts +0 -6
  240. package/dist/ui/saveInput/Switch.js +0 -30
  241. package/dist/ui/saveInput/TextInput.d.ts +0 -6
  242. package/dist/ui/saveInput/TextInput.js +0 -26
  243. package/dist/ui/saveInput/Textarea.d.ts +0 -6
  244. package/dist/ui/saveInput/Textarea.js +0 -26
  245. package/dist/ui/saveInput/index.js +0 -2
  246. package/dist/ui/scrollArea/ScrollArea.js +0 -30
  247. package/dist/ui/scrollArea/ScrollAreaButton.d.ts +0 -5
  248. package/dist/ui/scrollArea/ScrollAreaButton.js +0 -51
  249. package/dist/ui/scrollArea/ScrollAreaContent.d.ts +0 -6
  250. package/dist/ui/scrollArea/ScrollAreaContent.js +0 -29
  251. package/dist/ui/scrollArea/context.js +0 -10
  252. package/dist/ui/scrollArea/index.d.ts +0 -3
  253. package/dist/ui/scrollArea/index.js +0 -3
  254. package/dist/ui/scrollArea/types.d.ts +0 -65
  255. package/dist/ui/scrollArea/types.js +0 -0
  256. package/dist/ui/scrollArea/useScrollArea.d.ts +0 -9
  257. package/dist/ui/scrollArea/useScrollArea.js +0 -146
  258. /package/{dist/ui/error/index.d.ts → src/ui/error/index.ts} +0 -0
  259. /package/{dist/ui/form/buttons/index.d.ts → src/ui/form/buttons/index.ts} +0 -0
  260. /package/{dist/ui/form/fields/index.d.ts → src/ui/form/fields/index.ts} +0 -0
  261. /package/{dist/ui/form/index.d.ts → src/ui/form/index.ts} +0 -0
  262. /package/{dist/ui/hoverPaper/index.d.ts → src/ui/hoverPaper/index.ts} +0 -0
  263. /package/{dist/ui/saveInput/index.d.ts → src/ui/saveInput/index.ts} +0 -0
@@ -0,0 +1,54 @@
1
+ import { useState } from 'react';
2
+ import { PromptInputContext } from './PromptInputContext';
3
+ import type { PromptInputProps } from './types';
4
+
5
+ export const Provider = ({
6
+ children,
7
+ onSubmit,
8
+ submiting,
9
+ uploading,
10
+ accept = ['text', 'image', 'pdf'],
11
+ }: PromptInputProps) => {
12
+ const [text, setText] = useState('');
13
+ const [file, setFile] = useState<File | undefined>();
14
+
15
+ const value: PromptInputContext = {
16
+ text,
17
+ setText,
18
+ file,
19
+ setFile,
20
+ onSubmit: () => {
21
+ if (text.trim()) {
22
+ onSubmit({ text: text.trim(), file });
23
+ setText('');
24
+ setFile(undefined);
25
+ }
26
+ },
27
+ submiting,
28
+ uploading,
29
+ accept: accept
30
+ .map((type) => {
31
+ switch (type) {
32
+ case 'text':
33
+ return 'text/plain';
34
+ case 'image':
35
+ return 'image/*';
36
+ case 'pdf':
37
+ return 'application/pdf';
38
+ case 'excel':
39
+ return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
40
+ case 'word':
41
+ return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
42
+ default:
43
+ return type;
44
+ }
45
+ })
46
+ .join(','),
47
+ };
48
+
49
+ return (
50
+ <PromptInputContext.Provider value={value}>
51
+ {children}
52
+ </PromptInputContext.Provider>
53
+ );
54
+ };
@@ -0,0 +1,29 @@
1
+ import { Paper, type PaperProps } from '@mantine/core';
2
+ import clsx from 'clsx';
3
+ import { Provider } from './PromptInputProvider';
4
+ import type { PromptInputProps } from './types';
5
+
6
+ export const Root = ({
7
+ className,
8
+ onSubmit,
9
+ submiting,
10
+ uploading,
11
+ accept,
12
+ ...props
13
+ }: PaperProps & PromptInputProps) => {
14
+ return (
15
+ <Provider
16
+ onSubmit={onSubmit}
17
+ submiting={submiting}
18
+ uploading={uploading}
19
+ accept={accept}
20
+ >
21
+ <Paper
22
+ radius="md"
23
+ withBorder
24
+ className={clsx('rolder-prompt-input-root', className)}
25
+ {...props}
26
+ />
27
+ </Provider>
28
+ );
29
+ };
@@ -0,0 +1,39 @@
1
+ import { ActionIcon, type ActionIconProps } from '@mantine/core';
2
+ import { usePromptInput } from './PromptInputContext';
3
+
4
+ export const Submit = ({ children, ...props }: ActionIconProps) => {
5
+ const Icon = (
6
+ <svg
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ width="24"
9
+ height="24"
10
+ viewBox="0 0 24 24"
11
+ fill="none"
12
+ stroke="currentColor"
13
+ strokeWidth="1.5"
14
+ strokeLinecap="round"
15
+ strokeLinejoin="round"
16
+ role="img"
17
+ aria-label="Submit"
18
+ >
19
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
20
+ <path d="M9 20v-8h-3.586a1 1 0 0 1 -.707 -1.707l6.586 -6.586a1 1 0 0 1 1.414 0l6.586 6.586a1 1 0 0 1 -.707 1.707h-3.586v8a1 1 0 0 1 -1 1h-4a1 1 0 0 1 -1 -1" />
21
+ </svg>
22
+ );
23
+
24
+ const { onSubmit, submiting, uploading } = usePromptInput();
25
+
26
+ return (
27
+ <ActionIcon
28
+ aria-label="Submit"
29
+ variant="light"
30
+ size="lg"
31
+ onClick={onSubmit}
32
+ disabled={uploading}
33
+ loading={submiting}
34
+ {...props}
35
+ >
36
+ {children ?? Icon}
37
+ </ActionIcon>
38
+ );
39
+ };
@@ -0,0 +1,39 @@
1
+ import { Textarea as MantineTextarea, type TextareaProps } from '@mantine/core';
2
+ import { type KeyboardEventHandler, useState } from 'react';
3
+ import { usePromptInput } from './PromptInputContext';
4
+
5
+ export const Textarea = (props: TextareaProps) => {
6
+ const { text, setText, onSubmit, submiting, uploading } = usePromptInput();
7
+ const [isComposing, setIsComposing] = useState(false);
8
+
9
+ const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {
10
+ if (e.key === 'Enter') {
11
+ if (isComposing || e.nativeEvent.isComposing) {
12
+ return;
13
+ }
14
+ if (e.shiftKey) {
15
+ return;
16
+ }
17
+ e.preventDefault();
18
+
19
+ onSubmit();
20
+ }
21
+ };
22
+
23
+ return (
24
+ <MantineTextarea
25
+ w="100%"
26
+ size="md"
27
+ rows={3}
28
+ classNames={{ input: 'rolder-prompt-input-textarea' }}
29
+ placeholder="Напишите сообщение"
30
+ onCompositionEnd={() => setIsComposing(false)}
31
+ onCompositionStart={() => setIsComposing(true)}
32
+ onKeyDown={handleKeyDown}
33
+ value={text}
34
+ onChange={(e) => setText(e.target.value)}
35
+ disabled={submiting || uploading}
36
+ {...props}
37
+ />
38
+ );
39
+ };
@@ -0,0 +1,15 @@
1
+ import { File } from './File';
2
+ import { Footer } from './Footer';
3
+ import { Root } from './Root';
4
+ import { Submit } from './Submit';
5
+ import { Textarea } from './Textarea';
6
+
7
+ export type { Accept, PromptInputProps } from './types';
8
+
9
+ export const PromptInput = {
10
+ Root,
11
+ Textarea,
12
+ Footer,
13
+ Submit,
14
+ File,
15
+ };
@@ -0,0 +1,9 @@
1
+ export type Accept = 'text' | 'image' | 'pdf' | 'excel' | 'word';
2
+
3
+ export interface PromptInputProps {
4
+ children: React.ReactNode;
5
+ onSubmit: ({ text, file }: { text: string; file?: File }) => void;
6
+ submiting: boolean;
7
+ uploading: boolean;
8
+ accept?: Accept[];
9
+ }
@@ -0,0 +1,29 @@
1
+ import type { FileUIPart } from 'ai';
2
+
3
+ /**
4
+ * Converts a blob URL to a data URL
5
+ */
6
+ async function blobToDataURL(blobUrl: string): Promise<string> {
7
+ const response = await fetch(blobUrl);
8
+ const blob = await response.blob();
9
+
10
+ return new Promise((resolve, reject) => {
11
+ const reader = new FileReader();
12
+ reader.onload = () => resolve(reader.result as string);
13
+ reader.onerror = reject;
14
+ reader.readAsDataURL(blob);
15
+ });
16
+ }
17
+
18
+ /**
19
+ * Converts FileUIPart array with blob URLs to data URLs
20
+ */
21
+ export async function convertFileUIPartBlobToDataURL(
22
+ file: FileUIPart,
23
+ ): Promise<FileUIPart> {
24
+ if (file.url.startsWith('blob:')) {
25
+ const dataUrl = await blobToDataURL(file.url);
26
+ return { ...file, url: dataUrl };
27
+ }
28
+ return file;
29
+ }
@@ -0,0 +1,19 @@
1
+ import { parsePartialJson, type TextUIPart } from 'ai';
2
+
3
+ export const parseAiMessagePart = async <T extends TextUIPart>(
4
+ part: T,
5
+ ): Promise<T> => {
6
+ if (!part.text.startsWith('{')) {
7
+ return part;
8
+ }
9
+
10
+ try {
11
+ // parsePartialJson возвращает промис с результатом
12
+ // biome-ignore lint/suspicious/noExplicitAny: <parsePartialJson>
13
+ const result = (await parsePartialJson(part.text)) as any;
14
+ return result?.value || part;
15
+ } catch (error) {
16
+ console.error('Error parsing partial JSON:', error);
17
+ return part; // Fallback к исходному тексту
18
+ }
19
+ };
@@ -0,0 +1,21 @@
1
+ import { useComputedColorScheme } from '@mantine/core';
2
+ import { useEffect } from 'react';
3
+ import { setCookies } from '../functions/setCookies';
4
+
5
+ export const AppDefaults = ({
6
+ saveColorScheme,
7
+ }: {
8
+ saveColorScheme: boolean;
9
+ }) => {
10
+ const colorScheme = useComputedColorScheme();
11
+
12
+ useEffect(() => {
13
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
14
+ const cookies = [{ name: 'tz', value: tz, expires: 365 }];
15
+ if (saveColorScheme)
16
+ cookies.push({ name: 'colorScheme', value: colorScheme, expires: 365 });
17
+ setCookies(cookies);
18
+ }, [colorScheme, saveColorScheme]);
19
+
20
+ return null;
21
+ };
@@ -0,0 +1,50 @@
1
+ import {
2
+ ColorSchemeScript,
3
+ MantineProvider,
4
+ type MantineProviderProps,
5
+ } from '@mantine/core';
6
+ import { HeadContent, Scripts } from '@tanstack/react-router';
7
+ import { getCookie } from '../functions/getCookie';
8
+ import { AppDefaults } from './AppDefaults';
9
+ import { cookieColorSchemeManager } from './cookieColorSchemeManager';
10
+ import { defaultTheme } from './defaultTheme';
11
+
12
+ interface Props extends MantineProviderProps {
13
+ saveColorScheme?: boolean;
14
+ }
15
+
16
+ const colorSchemeManager = cookieColorSchemeManager();
17
+
18
+ export const DefaultApp = ({
19
+ children,
20
+ saveColorScheme = true,
21
+ defaultColorScheme = 'auto',
22
+ ...props
23
+ }: Props) => {
24
+ const colorScheme = saveColorScheme
25
+ ? getCookie('colorScheme', defaultColorScheme)
26
+ : defaultColorScheme;
27
+
28
+ return (
29
+ <html lang="ru" suppressHydrationWarning>
30
+ <head>
31
+ <HeadContent />
32
+ <ColorSchemeScript defaultColorScheme={colorScheme} />
33
+ </head>
34
+ <body>
35
+ <MantineProvider
36
+ defaultColorScheme={colorScheme}
37
+ theme={defaultTheme}
38
+ colorSchemeManager={colorSchemeManager}
39
+ {...props}
40
+ >
41
+ <AppDefaults saveColorScheme={saveColorScheme} />
42
+
43
+ {children}
44
+ </MantineProvider>
45
+
46
+ <Scripts />
47
+ </body>
48
+ </html>
49
+ );
50
+ };
@@ -0,0 +1,70 @@
1
+ import {
2
+ isMantineColorScheme,
3
+ type MantineColorScheme,
4
+ type MantineColorSchemeManager,
5
+ } from '@mantine/core';
6
+ import { atom } from 'nanostores';
7
+ import { setCookie } from '../functions/setCookie';
8
+
9
+ export interface CookieColorSchemeManager {
10
+ /** Название куки, `colorScheme` по умолчанию */
11
+ key?: string;
12
+ }
13
+
14
+ const $colorScheme = atom<MantineColorScheme | undefined>();
15
+ let unsubscribeSystemTheme: (() => void) | undefined;
16
+
17
+ export const cookieColorSchemeManager = ({
18
+ key = 'colorScheme',
19
+ }: CookieColorSchemeManager = {}): MantineColorSchemeManager => {
20
+ return {
21
+ get: (defaultValue) => {
22
+ try {
23
+ return $colorScheme.get() || defaultValue;
24
+ } catch {
25
+ return defaultValue;
26
+ }
27
+ },
28
+
29
+ set: (value) => {
30
+ try {
31
+ setCookie(key, value);
32
+ $colorScheme.set(value);
33
+ } catch (error) {
34
+ console.warn(
35
+ '[cookieColorSchemeManager] Ошибка при сохранении цветовой схемы в куки.',
36
+ error,
37
+ );
38
+ }
39
+ },
40
+
41
+ subscribe: (onUpdate) => {
42
+ $colorScheme.listen((newValue) => {
43
+ if (isMantineColorScheme(newValue)) {
44
+ setCookie(key, newValue);
45
+ onUpdate(newValue);
46
+ }
47
+ });
48
+
49
+ // Listener на системную тему
50
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
51
+ const handleSystemThemeChange = () => onUpdate('auto');
52
+ mediaQuery.addEventListener('change', handleSystemThemeChange);
53
+ unsubscribeSystemTheme = () =>
54
+ mediaQuery.removeEventListener('change', handleSystemThemeChange);
55
+ },
56
+
57
+ unsubscribe: () => {
58
+ $colorScheme.off();
59
+ if (unsubscribeSystemTheme) {
60
+ unsubscribeSystemTheme();
61
+ unsubscribeSystemTheme = undefined;
62
+ }
63
+ },
64
+
65
+ clear: () => {
66
+ setCookie(key);
67
+ $colorScheme.set(undefined);
68
+ },
69
+ };
70
+ };
@@ -0,0 +1,22 @@
1
+ import { createMiddleware } from '@tanstack/react-start';
2
+ import {
3
+ getCookie,
4
+ getRequestHeader,
5
+ setCookie,
6
+ } from '@tanstack/react-start/server';
7
+
8
+ const locale = createMiddleware().server(async ({ next }) => {
9
+ const header = getRequestHeader('accept-language');
10
+ const headerLocale = header?.split(',')[0] || 'ru-RU';
11
+ const cookieLocale = getCookie('locale');
12
+ const cookieTz = getCookie('tz');
13
+
14
+ const locale = cookieLocale || headerLocale;
15
+ const timeZone = cookieTz || 'UTC';
16
+
17
+ setCookie('locale', locale, { path: '/', maxAge: 60 * 60 * 24 * 365 });
18
+
19
+ return next({ context: { locale, timeZone } });
20
+ });
21
+
22
+ export const defaultRequestMiddlewares = [locale];
@@ -0,0 +1,22 @@
1
+ import { createTheme, Modal } from '@mantine/core';
2
+
3
+ export const defaultTheme = createTheme({
4
+ components: {
5
+ Modal: Modal.extend({
6
+ defaultProps: {
7
+ centered: true,
8
+ padding: 'lg',
9
+ },
10
+ }),
11
+ ModalTitle: Modal.Title.extend({
12
+ defaultProps: { pr: 24 },
13
+ }),
14
+ ModalCloseButton: Modal.CloseButton.extend({
15
+ defaultProps: {
16
+ pos: 'absolute',
17
+ top: 4,
18
+ right: 4,
19
+ },
20
+ }),
21
+ },
22
+ });
@@ -0,0 +1,36 @@
1
+ import { createIsomorphicFn } from '@tanstack/react-start';
2
+ import { getCookie as getServerCookie } from '@tanstack/react-start/server';
3
+ import Cookies from 'js-cookie';
4
+
5
+ const getCookieImpl = createIsomorphicFn()
6
+ .server(
7
+ (name: string, defaultValue?: string) =>
8
+ getServerCookie(name) || defaultValue,
9
+ )
10
+ .client(
11
+ (name: string, defaultValue?: string) => Cookies.get(name) || defaultValue,
12
+ );
13
+
14
+ // Перегрузки функций для правильной типизации
15
+ export function getCookie<T extends string>(name: string, defaultValue: T): T;
16
+ export function getCookie(name: string, defaultValue: string): string;
17
+ export function getCookie(
18
+ name: string,
19
+ defaultValue?: undefined,
20
+ ): string | undefined;
21
+
22
+ /**
23
+ * Изоморфная функция для получения значения куки.
24
+ * На клиенте использует библиотеку js-cookie для работы с куками.
25
+ * На сервере использует функции getCookie и setCookie из tanstack start.
26
+ *
27
+ * @param {string} name - Имя куки
28
+ * @param {string} [defaultValue] - Значение по умолчанию. Если value указан, создается новая кука с этим значением.
29
+ * @returns {string | undefined} Значение куки из хранилища, либо значение по умолчанию (если кука не существует), либо undefined (если кука не существует и value не передан)
30
+ */
31
+ export function getCookie(
32
+ name: string,
33
+ defaultValue?: string,
34
+ ): string | undefined {
35
+ return getCookieImpl(name, defaultValue);
36
+ }
@@ -0,0 +1,29 @@
1
+ import { createIsomorphicFn } from '@tanstack/react-start';
2
+ import {
3
+ deleteCookie,
4
+ setCookie as setServerCookie,
5
+ } from '@tanstack/react-start/server';
6
+ import Cookies from 'js-cookie';
7
+
8
+ /**
9
+ * Изоморфная функция для установки значения куки.
10
+ * На клиенте использует библиотеку js-cookie для работы с куками.
11
+ * На сервере использует функции getCookie и setCookie из tanstack start.
12
+ *
13
+ * @param {string} name - Имя куки
14
+ * @param {string} value - Значение куки, если не указано, кука будет удалена
15
+ * @param {number} [expires=7] - Количество дней до истечения срока действия куки (по умолчанию 7 дней)
16
+ */
17
+ export const setCookie = createIsomorphicFn()
18
+ .server((name: string, value?: string, expires?: number) => {
19
+ const expiresDate = new Date();
20
+ expiresDate.setDate(expiresDate.getDate() + (expires || 7));
21
+ if (value) setServerCookie(name, value, { expires: expiresDate });
22
+ else deleteCookie(name);
23
+ })
24
+ .client((name: string, value?: string, expires?: number) => {
25
+ const expiresDate = new Date();
26
+ expiresDate.setDate(expiresDate.getDate() + (expires || 7));
27
+ if (value) Cookies.set(name, value, { expires: expiresDate });
28
+ else Cookies.remove(name);
29
+ });
@@ -0,0 +1,24 @@
1
+ import { createClientOnlyFn } from '@tanstack/react-start';
2
+ import Cookies from 'js-cookie';
3
+
4
+ interface Cookie {
5
+ name: string;
6
+ value?: string;
7
+ expires?: number;
8
+ }
9
+
10
+ /**
11
+ * Клиентская функция для установки значения нескольких куки.
12
+ * На клиенте использует библиотеку js-cookie для работы с куками.
13
+ * На сервере использует функции getCookie и setCookie из tanstack start.
14
+ *
15
+ * @param {Cookie[]} cookies - Массив объектов с данными куки *
16
+ */
17
+ export const setCookies = createClientOnlyFn((cookies: Cookie[]) => {
18
+ cookies.forEach(({ name, value, expires }) => {
19
+ const expiresDate = new Date();
20
+ expiresDate.setDate(expiresDate.getDate() + (expires || 7));
21
+ if (value) Cookies.set(name, value, { expires: expiresDate });
22
+ else Cookies.remove(name);
23
+ });
24
+ });
@@ -0,0 +1,14 @@
1
+ import {
2
+ useMutation as tanstackUseMutation,
3
+ type UseMutationOptions,
4
+ } from '@tanstack/react-query';
5
+
6
+ export const useMutation = <T, K = void>(
7
+ fn: ({ data }: { data: T }) => Promise<K>,
8
+ options?: Omit<UseMutationOptions<K, Error, T>, 'mutationFn'>,
9
+ ) => {
10
+ return tanstackUseMutation<K, Error, T>({
11
+ mutationFn: (data) => fn({ data }),
12
+ ...options,
13
+ });
14
+ };
@@ -0,0 +1,23 @@
1
+ import {
2
+ type UseMutationOptions,
3
+ useMutation,
4
+ useQueryClient,
5
+ } from '@tanstack/react-query';
6
+
7
+ export const useMutationWithInvalidate = <T, K = void>(
8
+ fn: ({ data }: { data: T }) => Promise<K>,
9
+ queryKey: string[],
10
+ options?: Omit<UseMutationOptions<K, Error, T>, 'mutationFn' | 'onSettled'>,
11
+ ) => {
12
+ const queryClient = useQueryClient();
13
+ return useMutation<K, Error, T>({
14
+ mutationFn: (data) => fn({ data }),
15
+ // Здесь важно ждать invalidateQueries, чтобы mutateAsync завершался по результату
16
+ // не только мутации, но и загрузки новых данных
17
+ onSettled: async (_, error) => {
18
+ if (!error && queryKey.length)
19
+ await queryClient.invalidateQueries({ queryKey });
20
+ },
21
+ ...options,
22
+ });
23
+ };
@@ -1,26 +1,66 @@
1
1
  /** biome-ignore-all assist/source/organizeImports: <> */
2
- export { Conversation, type ConversationProps, useChatMessage, } from './ai/ui/conversation';
3
- export { type Accept, PromptInput, type PromptInputProps, } from './ai/ui/promptInput';
2
+
3
+ //* AI *//
4
+ export {
5
+ Conversation,
6
+ type ConversationProps,
7
+ useChatMessage,
8
+ } from './ai/ui/conversation';
9
+ export {
10
+ type Accept,
11
+ PromptInput,
12
+ type PromptInputProps,
13
+ } from './ai/ui/promptInput';
4
14
  export { convertFileUIPartBlobToDataURL } from './ai/utils/convertFileUIPartBlobToDataURL';
5
15
  export { parseAiMessagePart } from './ai/utils/parseAiMessagePart';
16
+
17
+ //* APP *//
6
18
  export { DefaultApp } from './app/DefaultApp';
7
19
  export { defaultRequestMiddlewares } from './app/defaultRequestMiddlewares';
8
20
  export { defaultTheme } from './app/defaultTheme';
21
+
22
+ //* FUNCTIONS *//
9
23
  export { getCookie } from './functions/getCookie';
10
24
  export { setCookie } from './functions/setCookie';
11
25
  export { setCookies } from './functions/setCookies';
26
+
27
+ //* HOOKS *//
12
28
  export { useMutation } from './hooks/useMutation';
13
29
  export { useMutationWithInvalidate } from './hooks/useMutationWithInvalidate';
30
+
31
+ //* SURREAL *//
14
32
  export { getDB } from './surreal/connection';
15
33
  export { surrealDeleteFn, surrealUnsubscribeFn } from './surreal/deafaultCrud';
16
34
  export { deserialize } from './surreal/deserialize';
17
35
  export { encryptionFn } from './surreal/encryption';
36
+
37
+ //* UI *//
18
38
  export { Editor, useEditor } from './ui/editor';
19
- export { DefaultError, DefaultNotFound, defaultErrorNotification, Forbidden, } from './ui/error';
39
+ export {
40
+ DefaultError,
41
+ DefaultNotFound,
42
+ defaultErrorNotification,
43
+ Forbidden,
44
+ } from './ui/error';
20
45
  export { AnimatedChevron } from './ui/AnimatedChevron';
21
- export { useAppForm, useFieldContext, withForm, blurOnError, fieldsSchema, } from './ui/form';
46
+ export {
47
+ useAppForm,
48
+ useFieldContext,
49
+ withForm,
50
+ blurOnError,
51
+ fieldsSchema,
52
+ } from './ui/form';
22
53
  export { HoverPaper, usePaperHover } from './ui/hoverPaper';
23
54
  export { JsonInput } from './ui/JsonInput';
24
55
  export { RouterLink } from './ui/RouterLink';
25
56
  export { SaveInput } from './ui/saveInput';
26
- export { ScrollArea, useScrollArea, type ScrollAreaContextValue, type ScrollAreaHook, type ScrollAreaProps, type ScrollAreaState, type ScrollButtonProps, type ScrollPosition, } from './ui/scrollArea';
57
+ export {
58
+ ScrollArea,
59
+ useScrollArea,
60
+ type ScrollAreaContextValue,
61
+ type ScrollAreaHook,
62
+ type ScrollAreaProps,
63
+ type ScrollAreaState,
64
+ type ScrollButtonProps,
65
+ type ScrollPosition,
66
+ } from './ui/scrollArea';