@rolder/kit 3.0.0-alpha-7 → 3.0.0-alpha-9

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 (58) hide show
  1. package/dist/ai/index.d.ts +2 -0
  2. package/dist/ai/index.js +2 -0
  3. package/dist/ai/ui/conversation/ConversationContext.d.ts +7 -0
  4. package/dist/ai/ui/conversation/ConversationContext.js +8 -0
  5. package/dist/ai/ui/conversation/ConversationProvider.d.ts +2 -0
  6. package/dist/ai/ui/conversation/ConversationProvider.js +14 -0
  7. package/dist/ai/ui/conversation/Empty.d.ts +1 -0
  8. package/dist/ai/ui/conversation/Empty.js +21 -0
  9. package/dist/ai/ui/conversation/File.d.ts +4 -0
  10. package/dist/ai/ui/conversation/File.js +42 -0
  11. package/dist/ai/ui/conversation/FileIcon.d.ts +3 -0
  12. package/dist/ai/ui/conversation/FileIcon.js +43 -0
  13. package/dist/ai/ui/conversation/Loader.d.ts +2 -0
  14. package/dist/ai/ui/conversation/Loader.js +12 -0
  15. package/dist/ai/ui/conversation/Message.d.ts +4 -0
  16. package/dist/ai/ui/conversation/Message.js +25 -0
  17. package/dist/ai/ui/conversation/Root.d.ts +2 -0
  18. package/dist/ai/ui/conversation/Root.js +26 -0
  19. package/dist/ai/ui/conversation/index.d.ts +13 -0
  20. package/dist/ai/ui/conversation/index.js +15 -0
  21. package/dist/ai/ui/conversation/types.d.ts +7 -0
  22. package/dist/ai/ui/conversation/types.js +0 -0
  23. package/dist/ai/ui/conversation/useChatMessage.d.ts +2 -0
  24. package/dist/ai/ui/conversation/useChatMessage.js +12 -0
  25. package/dist/ai/ui/index.d.ts +2 -0
  26. package/dist/ai/ui/index.js +2 -0
  27. package/dist/ai/ui/promptInput/File.d.ts +2 -0
  28. package/dist/ai/ui/promptInput/File.js +69 -0
  29. package/dist/ai/ui/promptInput/FileIcon.d.ts +3 -0
  30. package/dist/ai/ui/promptInput/FileIcon.js +43 -0
  31. package/dist/ai/ui/promptInput/Footer.d.ts +2 -0
  32. package/dist/ai/ui/promptInput/Footer.js +8 -0
  33. package/dist/ai/ui/promptInput/PromptInputContext.d.ts +12 -0
  34. package/dist/ai/ui/promptInput/PromptInputContext.js +8 -0
  35. package/dist/ai/ui/promptInput/PromptInputProvider.d.ts +2 -0
  36. package/dist/ai/ui/promptInput/PromptInputProvider.js +50 -0
  37. package/dist/ai/ui/promptInput/Root.d.ts +3 -0
  38. package/dist/ai/ui/promptInput/Root.js +18 -0
  39. package/dist/ai/ui/promptInput/Submit.d.ts +2 -0
  40. package/dist/ai/ui/promptInput/Submit.js +21 -0
  41. package/dist/ai/ui/promptInput/Textarea.d.ts +2 -0
  42. package/dist/ai/ui/promptInput/Textarea.js +34 -0
  43. package/dist/ai/ui/promptInput/index.d.ts +8 -0
  44. package/dist/ai/ui/promptInput/index.js +14 -0
  45. package/dist/ai/ui/promptInput/styles.module.js +7 -0
  46. package/dist/ai/ui/promptInput/styles_module.css +24 -0
  47. package/dist/ai/ui/promptInput/types.d.ts +11 -0
  48. package/dist/ai/ui/promptInput/types.js +0 -0
  49. package/dist/ai/utils/convertFileUIPartBlobToDataURL.d.ts +5 -0
  50. package/dist/ai/utils/convertFileUIPartBlobToDataURL.js +21 -0
  51. package/dist/ai/utils/index.d.ts +2 -0
  52. package/dist/ai/utils/index.js +2 -0
  53. package/dist/ai/utils/parseAiMessagePart.d.ts +2 -0
  54. package/dist/ai/utils/parseAiMessagePart.js +12 -0
  55. package/dist/app/defaultTheme.d.ts +7 -7
  56. package/dist/index.d.ts +1 -0
  57. package/dist/index.js +1 -0
  58. package/package.json +7 -3
@@ -0,0 +1,2 @@
1
+ export * from './ui';
2
+ export * from './utils';
@@ -0,0 +1,2 @@
1
+ export * from "./ui/index.js";
2
+ export * from "./utils/index.js";
@@ -0,0 +1,7 @@
1
+ export interface ConversationContext {
2
+ loading: boolean;
3
+ streaming: boolean;
4
+ empty: boolean;
5
+ }
6
+ export declare const ConversationContext: import("react").Context<ConversationContext | null>;
7
+ export declare const useConversation: () => ConversationContext;
@@ -0,0 +1,8 @@
1
+ import { createContext, useContext } from "react";
2
+ const ConversationContext = createContext(null);
3
+ const useConversation = ()=>{
4
+ const context = useContext(ConversationContext);
5
+ if (!context) throw new Error('useConversation must be used within a ConversationProvider');
6
+ return context;
7
+ };
8
+ export { ConversationContext, useConversation };
@@ -0,0 +1,2 @@
1
+ import type { ConversationProps } from './types';
2
+ export declare const Provider: ({ children, loading, streaming, empty, }: ConversationProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { ConversationContext } from "./ConversationContext.js";
3
+ const Provider = ({ children, loading, streaming, empty })=>{
4
+ const value = {
5
+ loading,
6
+ streaming,
7
+ empty
8
+ };
9
+ return /*#__PURE__*/ jsx(ConversationContext.Provider, {
10
+ value: value,
11
+ children: children
12
+ });
13
+ };
14
+ export { Provider };
@@ -0,0 +1 @@
1
+ export declare const Empty: () => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,21 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Stack, Text } from "@mantine/core";
3
+ import { useConversation } from "./ConversationContext.js";
4
+ const Empty = ()=>{
5
+ const { empty } = useConversation();
6
+ return empty ? null : /*#__PURE__*/ jsxs(Stack, {
7
+ align: "center",
8
+ gap: 0,
9
+ children: [
10
+ /*#__PURE__*/ jsx(Text, {
11
+ children: "Нет сообщений"
12
+ }),
13
+ /*#__PURE__*/ jsx(Text, {
14
+ size: "sm",
15
+ c: "dimmed",
16
+ children: "Начните общение, чтобы увидеть сообщения здесь"
17
+ })
18
+ ]
19
+ });
20
+ };
21
+ export { Empty };
@@ -0,0 +1,4 @@
1
+ import type { UIMessage } from 'ai';
2
+ export declare const File: <T extends UIMessage>({ message }: {
3
+ message: T;
4
+ }) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,42 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Image, Paper } from "@mantine/core";
3
+ import { FileIcon } from "./FileIcon.js";
4
+ const File = ({ message })=>{
5
+ const textFileType = message.id.split('-')[1];
6
+ const fileParts = message.parts?.filter((i)=>'file' === i.type);
7
+ const lastFilePart = fileParts[fileParts.length - 1];
8
+ const FileComponent = ()=>{
9
+ switch(textFileType){
10
+ case 'excel':
11
+ return /*#__PURE__*/ jsx(FileIcon, {
12
+ mimeType: "excel"
13
+ });
14
+ case 'word':
15
+ return /*#__PURE__*/ jsx(FileIcon, {
16
+ mimeType: "word"
17
+ });
18
+ case 'powerpoint':
19
+ return /*#__PURE__*/ jsx(FileIcon, {
20
+ mimeType: "powerpoint"
21
+ });
22
+ }
23
+ if (lastFilePart.mediaType.includes('image/')) return /*#__PURE__*/ jsx(Image, {
24
+ radius: "md",
25
+ h: 128,
26
+ src: lastFilePart.url,
27
+ alt: "Image Preview"
28
+ });
29
+ return /*#__PURE__*/ jsx(FileIcon, {
30
+ mimeType: lastFilePart.mediaType
31
+ });
32
+ };
33
+ return textFileType || lastFilePart ? /*#__PURE__*/ jsx(Paper, {
34
+ radius: "md",
35
+ px: "md",
36
+ py: "sm",
37
+ ml: "auto",
38
+ bg: "var(--mantine-color-default-hover)",
39
+ children: /*#__PURE__*/ jsx(FileComponent, {})
40
+ }) : null;
41
+ };
42
+ export { File };
@@ -0,0 +1,3 @@
1
+ export declare const FileIcon: ({ mimeType }: {
2
+ mimeType: string;
3
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,43 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { IconFile, IconFileTypeDoc, IconFileTypePdf, IconFileTypePpt, IconFileTypeXls, IconPhoto } from "@tabler/icons-react";
3
+ const FileIcon = ({ mimeType })=>{
4
+ switch(true){
5
+ case mimeType.includes('image/'):
6
+ return /*#__PURE__*/ jsx(IconPhoto, {
7
+ size: 36,
8
+ stroke: 1.5,
9
+ color: "var(--mantine-color-text)"
10
+ });
11
+ case mimeType.includes('application/pdf'):
12
+ return /*#__PURE__*/ jsx(IconFileTypePdf, {
13
+ size: 36,
14
+ stroke: 1.5,
15
+ color: "var(--mantine-color-text)"
16
+ });
17
+ case 'word' === mimeType:
18
+ return /*#__PURE__*/ jsx(IconFileTypeDoc, {
19
+ size: 36,
20
+ stroke: 1.5,
21
+ color: "var(--mantine-color-text)"
22
+ });
23
+ case 'excel' === mimeType:
24
+ return /*#__PURE__*/ jsx(IconFileTypeXls, {
25
+ size: 36,
26
+ stroke: 1.5,
27
+ color: "var(--mantine-color-text)"
28
+ });
29
+ case 'powerpoint' === mimeType:
30
+ return /*#__PURE__*/ jsx(IconFileTypePpt, {
31
+ size: 36,
32
+ stroke: 1.5,
33
+ color: "var(--mantine-color-text)"
34
+ });
35
+ default:
36
+ return /*#__PURE__*/ jsx(IconFile, {
37
+ size: 36,
38
+ stroke: 1.5,
39
+ color: "var(--mantine-color-text)"
40
+ });
41
+ }
42
+ };
43
+ export { FileIcon };
@@ -0,0 +1,2 @@
1
+ import { type LoaderProps } from '@mantine/core';
2
+ export declare const Loader: (props: LoaderProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,12 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Loader } from "@mantine/core";
3
+ import { useConversation } from "./ConversationContext.js";
4
+ const Loader_Loader = (props)=>{
5
+ const { loading } = useConversation();
6
+ return loading ? /*#__PURE__*/ jsx(Loader, {
7
+ size: 28,
8
+ type: "dots",
9
+ ...props
10
+ }) : null;
11
+ };
12
+ export { Loader_Loader as Loader };
@@ -0,0 +1,4 @@
1
+ import type { UIMessage } from 'ai';
2
+ export declare const Message: <T extends UIMessage>({ message }: {
3
+ message: T;
4
+ }) => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,25 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Paper } from "@mantine/core";
3
+ import { Streamdown } from "streamdown";
4
+ import { useConversation } from "./ConversationContext.js";
5
+ import { useChatMessage } from "./useChatMessage.js";
6
+ const Message = ({ message })=>{
7
+ const textParts = message?.parts?.filter((i)=>'text' === i.type);
8
+ const lastTextPart = textParts?.[textParts.length - 1];
9
+ const chatMessage = useChatMessage(lastTextPart);
10
+ const { streaming } = useConversation();
11
+ return chatMessage && 'system' !== message.role ? /*#__PURE__*/ jsx(Paper, {
12
+ radius: "md",
13
+ px: "md",
14
+ py: "sm",
15
+ maw: "80%",
16
+ ml: 'user' === message.role ? 'auto' : void 0,
17
+ bg: 'user' === message.role ? 'var(--mantine-color-default-hover)' : 'var(--mantine-primary-color-light)',
18
+ fz: "sm",
19
+ children: /*#__PURE__*/ jsx(Streamdown, {
20
+ isAnimating: streaming && 'assistant' === message.role,
21
+ children: chatMessage
22
+ })
23
+ }) : null;
24
+ };
25
+ export { Message };
@@ -0,0 +1,2 @@
1
+ import type { ConversationProps } from './types';
2
+ export declare const Root: ({ children, loading, streaming, empty, ...props }: ConversationProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Paper, Stack } from "@mantine/core";
3
+ import { ScrollArea } from "../../../ui/index.js";
4
+ import { Provider } from "./ConversationProvider.js";
5
+ const Root = ({ children, loading, streaming, empty, ...props })=>/*#__PURE__*/ jsx(Provider, {
6
+ loading: loading,
7
+ streaming: streaming,
8
+ empty: empty,
9
+ children: /*#__PURE__*/ jsx(Paper, {
10
+ withBorder: true,
11
+ radius: "md",
12
+ ...props,
13
+ children: /*#__PURE__*/ jsxs(ScrollArea, {
14
+ autoScroll: true,
15
+ scrollToBottomOnInit: true,
16
+ p: "md",
17
+ children: [
18
+ /*#__PURE__*/ jsx(Stack, {
19
+ children: children
20
+ }),
21
+ /*#__PURE__*/ jsx(ScrollArea.ScrollButton, {})
22
+ ]
23
+ })
24
+ })
25
+ });
26
+ export { Root };
@@ -0,0 +1,13 @@
1
+ export * from './types';
2
+ export * from './useChatMessage';
3
+ export declare const Conversation: {
4
+ Root: ({ children, loading, streaming, empty, ...props }: import("./types").ConversationProps) => import("react/jsx-runtime").JSX.Element;
5
+ Message: <T extends import("ai").UIMessage>({ message }: {
6
+ message: T;
7
+ }) => import("react/jsx-runtime").JSX.Element | null;
8
+ File: <T extends import("ai").UIMessage>({ message }: {
9
+ message: T;
10
+ }) => import("react/jsx-runtime").JSX.Element | null;
11
+ Loader: (props: import("@mantine/core").LoaderProps) => import("react/jsx-runtime").JSX.Element | null;
12
+ Empty: () => import("react/jsx-runtime").JSX.Element | null;
13
+ };
@@ -0,0 +1,15 @@
1
+ import { Empty } from "./Empty.js";
2
+ import { File } from "./File.js";
3
+ import { Loader } from "./Loader.js";
4
+ import { Message } from "./Message.js";
5
+ import { Root } from "./Root.js";
6
+ export * from "./types.js";
7
+ export * from "./useChatMessage.js";
8
+ const Conversation = {
9
+ Root: Root,
10
+ Message: Message,
11
+ File: File,
12
+ Loader: Loader,
13
+ Empty: Empty
14
+ };
15
+ export { Conversation };
@@ -0,0 +1,7 @@
1
+ import type { PaperProps } from '@mantine/core';
2
+ export interface ConversationProps extends PaperProps {
3
+ children?: React.ReactNode;
4
+ loading: boolean;
5
+ streaming: boolean;
6
+ empty: boolean;
7
+ }
File without changes
@@ -0,0 +1,2 @@
1
+ import type { TextUIPart } from 'ai';
2
+ export declare const useChatMessage: (part: TextUIPart) => string;
@@ -0,0 +1,12 @@
1
+ import { useEffect, useState } from "react";
2
+ import { parseAiMessagePart } from "../../utils/index.js";
3
+ const useChatMessage = (part)=>{
4
+ const [parsedText, setParsedText] = useState('');
5
+ useEffect(()=>{
6
+ parseAiMessagePart(part).then((i)=>setParsedText(i.text));
7
+ }, [
8
+ part
9
+ ]);
10
+ return parsedText;
11
+ };
12
+ export { useChatMessage };
@@ -0,0 +1,2 @@
1
+ export * from './conversation';
2
+ export * from './promptInput';
@@ -0,0 +1,2 @@
1
+ export * from "./conversation/index.js";
2
+ export * from "./promptInput/index.js";
@@ -0,0 +1,2 @@
1
+ import { type FileButtonProps } from '@mantine/core';
2
+ export declare const File: (props: Omit<FileButtonProps, "onChange" | "children">) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,69 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { ActionIcon, FileButton, Tooltip } from "@mantine/core";
3
+ import { IconPaperclip, IconTrash } from "@tabler/icons-react";
4
+ import { useRef } from "react";
5
+ import { FileIcon } from "./FileIcon.js";
6
+ import { usePromptInput } from "./PromptInputContext.js";
7
+ import styles_module from "./styles.module.js";
8
+ const File = (props)=>{
9
+ const resetRef = useRef(null);
10
+ const { file, setFile, accept, submiting, uploading } = usePromptInput();
11
+ return /*#__PURE__*/ jsx(FileButton, {
12
+ resetRef: resetRef,
13
+ onChange: async (file)=>{
14
+ if (file) setFile(file);
15
+ },
16
+ accept: accept,
17
+ disabled: submiting || uploading,
18
+ ...props,
19
+ children: (props)=>/*#__PURE__*/ jsxs(ActionIcon.Group, {
20
+ children: [
21
+ /*#__PURE__*/ jsx(ActionIcon, {
22
+ size: "lg",
23
+ variant: "default",
24
+ disabled: submiting,
25
+ loading: uploading,
26
+ classNames: {
27
+ root: styles_module.fileActionAction
28
+ },
29
+ ...props,
30
+ children: /*#__PURE__*/ jsx(IconPaperclip, {
31
+ size: 24,
32
+ stroke: 1.5
33
+ })
34
+ }),
35
+ file && /*#__PURE__*/ jsxs(Fragment, {
36
+ children: [
37
+ /*#__PURE__*/ jsx(Tooltip, {
38
+ label: file.name,
39
+ openDelay: 500,
40
+ children: /*#__PURE__*/ jsx(ActionIcon.GroupSection, {
41
+ variant: "default",
42
+ size: "lg",
43
+ children: /*#__PURE__*/ jsx(FileIcon, {
44
+ mimeType: file.type
45
+ })
46
+ })
47
+ }),
48
+ /*#__PURE__*/ jsx(ActionIcon, {
49
+ size: "lg",
50
+ variant: "default",
51
+ classNames: {
52
+ root: styles_module.fileActionAction
53
+ },
54
+ onClick: ()=>{
55
+ resetRef.current?.();
56
+ setFile(void 0);
57
+ },
58
+ children: /*#__PURE__*/ jsx(IconTrash, {
59
+ size: 24,
60
+ stroke: 1.5
61
+ })
62
+ })
63
+ ]
64
+ })
65
+ ]
66
+ })
67
+ });
68
+ };
69
+ export { File };
@@ -0,0 +1,3 @@
1
+ export declare const FileIcon: ({ mimeType }: {
2
+ mimeType: string;
3
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,43 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { IconFile, IconFileTypeDoc, IconFileTypePdf, IconFileTypePpt, IconFileTypeXls, IconPhoto } from "@tabler/icons-react";
3
+ const FileIcon = ({ mimeType })=>{
4
+ switch(true){
5
+ case mimeType.includes('image/'):
6
+ return /*#__PURE__*/ jsx(IconPhoto, {
7
+ size: 24,
8
+ stroke: 1.5,
9
+ color: "var(--mantine-color-dimmed)"
10
+ });
11
+ case mimeType.includes('application/pdf'):
12
+ return /*#__PURE__*/ jsx(IconFileTypePdf, {
13
+ size: 24,
14
+ stroke: 1.5,
15
+ color: "var(--mantine-color-dimmed)"
16
+ });
17
+ case mimeType.includes('application/vnd.openxmlformats-officedocument.wordprocessingml.document'):
18
+ return /*#__PURE__*/ jsx(IconFileTypeDoc, {
19
+ size: 24,
20
+ stroke: 1.5,
21
+ color: "var(--mantine-color-dimmed)"
22
+ });
23
+ case mimeType.includes('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'):
24
+ return /*#__PURE__*/ jsx(IconFileTypeXls, {
25
+ size: 24,
26
+ stroke: 1.5,
27
+ color: "var(--mantine-color-dimmed)"
28
+ });
29
+ case mimeType.includes('application/vnd.openxmlformats-officedocument.presentationml.presentation'):
30
+ return /*#__PURE__*/ jsx(IconFileTypePpt, {
31
+ size: 24,
32
+ stroke: 1.5,
33
+ color: "var(--mantine-color-dimmed)"
34
+ });
35
+ default:
36
+ return /*#__PURE__*/ jsx(IconFile, {
37
+ size: 24,
38
+ stroke: 1.5,
39
+ color: "var(--mantine-color-dimmed)"
40
+ });
41
+ }
42
+ };
43
+ export { FileIcon };
@@ -0,0 +1,2 @@
1
+ import { type GroupProps } from '@mantine/core';
2
+ export declare const Footer: (props: GroupProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Group } from "@mantine/core";
3
+ const Footer = (props)=>/*#__PURE__*/ jsx(Group, {
4
+ justify: "space-between",
5
+ p: "xs",
6
+ ...props
7
+ });
8
+ export { Footer };
@@ -0,0 +1,12 @@
1
+ export interface PromptInputContext {
2
+ text: string;
3
+ setText: (text: string) => void;
4
+ file?: File;
5
+ setFile: (file?: File) => void;
6
+ onSubmit: () => void;
7
+ submiting: boolean;
8
+ uploading: boolean;
9
+ accept?: string;
10
+ }
11
+ export declare const PromptInputContext: import("react").Context<PromptInputContext | null>;
12
+ export declare const usePromptInput: () => PromptInputContext;
@@ -0,0 +1,8 @@
1
+ import { createContext, useContext } from "react";
2
+ const PromptInputContext = createContext(null);
3
+ const usePromptInput = ()=>{
4
+ const context = useContext(PromptInputContext);
5
+ if (!context) throw new Error('usePromptInput must be used within a PromptInputProvider');
6
+ return context;
7
+ };
8
+ export { PromptInputContext, usePromptInput };
@@ -0,0 +1,2 @@
1
+ import type { PromptInputProps } from './types';
2
+ export declare const Provider: ({ children, onSubmit, submiting, uploading, accept, }: PromptInputProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,50 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { PromptInputContext } from "./PromptInputContext.js";
4
+ const Provider = ({ children, onSubmit, submiting, uploading, accept = [
5
+ 'text',
6
+ 'image',
7
+ 'pdf'
8
+ ] })=>{
9
+ const [text, setText] = useState('');
10
+ const [file, setFile] = useState();
11
+ const value = {
12
+ text,
13
+ setText,
14
+ file,
15
+ setFile,
16
+ onSubmit: ()=>{
17
+ if (text.trim()) {
18
+ onSubmit({
19
+ text: text.trim(),
20
+ file
21
+ });
22
+ setText('');
23
+ setFile(void 0);
24
+ }
25
+ },
26
+ submiting,
27
+ uploading,
28
+ accept: accept.map((type)=>{
29
+ switch(type){
30
+ case 'text':
31
+ return 'text/plain';
32
+ case 'image':
33
+ return 'image/*';
34
+ case 'pdf':
35
+ return 'application/pdf';
36
+ case 'excel':
37
+ return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
38
+ case 'word':
39
+ return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
40
+ default:
41
+ return type;
42
+ }
43
+ }).join(',')
44
+ };
45
+ return /*#__PURE__*/ jsx(PromptInputContext.Provider, {
46
+ value: value,
47
+ children: children
48
+ });
49
+ };
50
+ export { Provider };
@@ -0,0 +1,3 @@
1
+ import { type PaperProps } from '@mantine/core';
2
+ import type { PromptInputProps } from './types';
3
+ export declare const Root: ({ className, onSubmit, submiting, uploading, accept, ...props }: PaperProps & PromptInputProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Paper } from "@mantine/core";
3
+ import clsx from "clsx";
4
+ import { Provider } from "./PromptInputProvider.js";
5
+ import styles_module from "./styles.module.js";
6
+ const Root = ({ className, onSubmit, submiting, uploading, accept, ...props })=>/*#__PURE__*/ jsx(Provider, {
7
+ onSubmit: onSubmit,
8
+ submiting: submiting,
9
+ uploading: uploading,
10
+ accept: accept,
11
+ children: /*#__PURE__*/ jsx(Paper, {
12
+ radius: "md",
13
+ withBorder: true,
14
+ className: clsx(styles_module.root, className),
15
+ ...props
16
+ })
17
+ });
18
+ export { Root };
@@ -0,0 +1,2 @@
1
+ import { type ActionIconProps } from '@mantine/core';
2
+ export declare const Submit: ({ children, ...props }: ActionIconProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { ActionIcon } from "@mantine/core";
3
+ import { IconArrowBigUp } from "@tabler/icons-react";
4
+ import { usePromptInput } from "./PromptInputContext.js";
5
+ const Submit = ({ children, ...props })=>{
6
+ const Icon = /*#__PURE__*/ jsx(IconArrowBigUp, {
7
+ strokeWidth: 1.5
8
+ });
9
+ const { onSubmit, submiting, uploading } = usePromptInput();
10
+ return /*#__PURE__*/ jsx(ActionIcon, {
11
+ "aria-label": "Submit",
12
+ variant: "light",
13
+ size: "lg",
14
+ onClick: onSubmit,
15
+ disabled: uploading,
16
+ loading: submiting,
17
+ ...props,
18
+ children: children ?? Icon
19
+ });
20
+ };
21
+ export { Submit };
@@ -0,0 +1,2 @@
1
+ import { type TextareaProps } from '@mantine/core';
2
+ export declare const Textarea: (props: TextareaProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,34 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Textarea } from "@mantine/core";
3
+ import { useState } from "react";
4
+ import { usePromptInput } from "./PromptInputContext.js";
5
+ import styles_module from "./styles.module.js";
6
+ const Textarea_Textarea = (props)=>{
7
+ const { text, setText, onSubmit, submiting, uploading } = usePromptInput();
8
+ const [isComposing, setIsComposing] = useState(false);
9
+ const handleKeyDown = (e)=>{
10
+ if ('Enter' === e.key) {
11
+ if (isComposing || e.nativeEvent.isComposing) return;
12
+ if (e.shiftKey) return;
13
+ e.preventDefault();
14
+ onSubmit();
15
+ }
16
+ };
17
+ return /*#__PURE__*/ jsx(Textarea, {
18
+ w: "100%",
19
+ size: "md",
20
+ rows: 3,
21
+ classNames: {
22
+ input: styles_module.textarea
23
+ },
24
+ placeholder: "Напишите сообщение",
25
+ onCompositionEnd: ()=>setIsComposing(false),
26
+ onCompositionStart: ()=>setIsComposing(true),
27
+ onKeyDown: handleKeyDown,
28
+ value: text,
29
+ onChange: (e)=>setText(e.target.value),
30
+ disabled: submiting || uploading,
31
+ ...props
32
+ });
33
+ };
34
+ export { Textarea_Textarea as Textarea };
@@ -0,0 +1,8 @@
1
+ export * from './types';
2
+ export declare const PromptInput: {
3
+ Root: ({ className, onSubmit, submiting, uploading, accept, ...props }: import("@mantine/core").PaperProps & import("./types").PromptInputProps) => import("react/jsx-runtime").JSX.Element;
4
+ Textarea: (props: import("@mantine/core").TextareaProps) => import("react/jsx-runtime").JSX.Element;
5
+ Footer: (props: import("@mantine/core").GroupProps) => import("react/jsx-runtime").JSX.Element;
6
+ Submit: ({ children, ...props }: import("@mantine/core").ActionIconProps) => import("react/jsx-runtime").JSX.Element;
7
+ File: (props: Omit<import("@mantine/core").FileButtonProps, "onChange" | "children">) => import("react/jsx-runtime").JSX.Element;
8
+ };
@@ -0,0 +1,14 @@
1
+ import { File } from "./File.js";
2
+ import { Footer } from "./Footer.js";
3
+ import { Root } from "./Root.js";
4
+ import { Submit } from "./Submit.js";
5
+ import { Textarea } from "./Textarea.js";
6
+ export * from "./types.js";
7
+ const PromptInput = {
8
+ Root: Root,
9
+ Textarea: Textarea,
10
+ Footer: Footer,
11
+ Submit: Submit,
12
+ File: File
13
+ };
14
+ export { PromptInput };
@@ -0,0 +1,7 @@
1
+ import "./styles_module.css";
2
+ const styles_module = {
3
+ root: "root-gmXOO2",
4
+ textarea: "textarea-f3Dbtf",
5
+ fileActionAction: "fileActionAction-w3KPzA"
6
+ };
7
+ export { styles_module as default };
@@ -0,0 +1,24 @@
1
+ .root-gmXOO2 {
2
+ background-color: light-dark(var(--mantine-color-white), var(--mantine-color-dark-6));
3
+
4
+ &:focus-within {
5
+ border-color: var(--mantine-primary-color-filled);
6
+ border-color: var(--mantine-primary-color-filled);
7
+ outline: none;
8
+ }
9
+ }
10
+
11
+ .textarea-f3Dbtf {
12
+ border: 0;
13
+ border-radius: 8px;
14
+ overflow: hidden;
15
+ }
16
+
17
+ .fileActionAction-w3KPzA {
18
+ color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1));
19
+
20
+ &[data-disabled] {
21
+ color: light-dark(var(--mantine-color-gray-5), var(--mantine-color-dark-3));
22
+ }
23
+ }
24
+
@@ -0,0 +1,11 @@
1
+ export type Accept = 'text' | 'image' | 'pdf' | 'excel' | 'word';
2
+ export interface PromptInputProps {
3
+ children: React.ReactNode;
4
+ onSubmit: ({ text, file }: {
5
+ text: string;
6
+ file?: File;
7
+ }) => void;
8
+ submiting: boolean;
9
+ uploading: boolean;
10
+ accept?: Accept[];
11
+ }
File without changes
@@ -0,0 +1,5 @@
1
+ import type { FileUIPart } from 'ai';
2
+ /**
3
+ * Converts FileUIPart array with blob URLs to data URLs
4
+ */
5
+ export declare function convertFileUIPartBlobToDataURL(file: FileUIPart): Promise<FileUIPart>;
@@ -0,0 +1,21 @@
1
+ async function blobToDataURL(blobUrl) {
2
+ const response = await fetch(blobUrl);
3
+ const blob = await response.blob();
4
+ return new Promise((resolve, reject)=>{
5
+ const reader = new FileReader();
6
+ reader.onload = ()=>resolve(reader.result);
7
+ reader.onerror = reject;
8
+ reader.readAsDataURL(blob);
9
+ });
10
+ }
11
+ async function convertFileUIPartBlobToDataURL(file) {
12
+ if (file.url.startsWith('blob:')) {
13
+ const dataUrl = await blobToDataURL(file.url);
14
+ return {
15
+ ...file,
16
+ url: dataUrl
17
+ };
18
+ }
19
+ return file;
20
+ }
21
+ export { convertFileUIPartBlobToDataURL };
@@ -0,0 +1,2 @@
1
+ export * from './convertFileUIPartBlobToDataURL';
2
+ export * from './parseAiMessagePart';
@@ -0,0 +1,2 @@
1
+ export * from "./convertFileUIPartBlobToDataURL.js";
2
+ export * from "./parseAiMessagePart.js";
@@ -0,0 +1,2 @@
1
+ import { type TextUIPart } from 'ai';
2
+ export declare const parseAiMessagePart: <T extends TextUIPart>(part: T) => Promise<T>;
@@ -0,0 +1,12 @@
1
+ import { parsePartialJson } from "ai";
2
+ const parseAiMessagePart = async (part)=>{
3
+ if (!part.text.startsWith('{')) return part;
4
+ try {
5
+ const result = await parsePartialJson(part.text);
6
+ return result?.value || part;
7
+ } catch (error) {
8
+ console.error('Error parsing partial JSON:', error);
9
+ return part;
10
+ }
11
+ };
12
+ export { parseAiMessagePart };
@@ -7,19 +7,19 @@ export declare const defaultTheme: {
7
7
  colors?: {
8
8
  [x: string & {}]: import("@mantine/core").MantineColorsTuple | undefined;
9
9
  dark?: import("@mantine/core").MantineColorsTuple | undefined;
10
+ gray?: import("@mantine/core").MantineColorsTuple | undefined;
11
+ red?: import("@mantine/core").MantineColorsTuple | undefined;
12
+ pink?: import("@mantine/core").MantineColorsTuple | undefined;
13
+ grape?: import("@mantine/core").MantineColorsTuple | undefined;
14
+ violet?: import("@mantine/core").MantineColorsTuple | undefined;
15
+ indigo?: import("@mantine/core").MantineColorsTuple | undefined;
10
16
  blue?: import("@mantine/core").MantineColorsTuple | undefined;
11
17
  cyan?: import("@mantine/core").MantineColorsTuple | undefined;
12
- gray?: import("@mantine/core").MantineColorsTuple | undefined;
13
18
  green?: import("@mantine/core").MantineColorsTuple | undefined;
14
- indigo?: import("@mantine/core").MantineColorsTuple | undefined;
15
19
  lime?: import("@mantine/core").MantineColorsTuple | undefined;
20
+ yellow?: import("@mantine/core").MantineColorsTuple | undefined;
16
21
  orange?: import("@mantine/core").MantineColorsTuple | undefined;
17
- pink?: import("@mantine/core").MantineColorsTuple | undefined;
18
- red?: import("@mantine/core").MantineColorsTuple | undefined;
19
22
  teal?: import("@mantine/core").MantineColorsTuple | undefined;
20
- violet?: import("@mantine/core").MantineColorsTuple | undefined;
21
- yellow?: import("@mantine/core").MantineColorsTuple | undefined;
22
- grape?: import("@mantine/core").MantineColorsTuple | undefined;
23
23
  } | undefined;
24
24
  primaryShade?: import("@mantine/core").MantineColorShade | {
25
25
  light?: import("@mantine/core").MantineColorShade | undefined;
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './ai';
1
2
  export * from './app';
2
3
  export * from './functions';
3
4
  export * from './hooks';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./ai/index.js";
1
2
  export * from "./app/index.js";
2
3
  export * from "./functions/index.js";
3
4
  export * from "./hooks/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rolder/kit",
3
- "version": "3.0.0-alpha-7",
3
+ "version": "3.0.0-alpha-9",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -57,10 +57,14 @@
57
57
  "js-cookie": "^3.0.5",
58
58
  "nanostores": "^1.1.0",
59
59
  "surrealdb": "^2.0.0-alpha.16",
60
- "omgopass": "^3.2.1"
60
+ "omgopass": "^3.2.1",
61
+ "ai": "^6.0.31"
61
62
  },
62
63
  "trustedDependencies": [
63
64
  "core-js",
64
65
  "esbuild"
65
- ]
66
+ ],
67
+ "dependencies": {
68
+ "streamdown": "^2.0.1"
69
+ }
66
70
  }