@crafter/rn-ai-elements 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/chatbot/AIImage.js +126 -0
- package/lib/commonjs/chatbot/AIImage.js.map +1 -0
- package/lib/commonjs/chatbot/Attachments.js +317 -0
- package/lib/commonjs/chatbot/Attachments.js.map +1 -0
- package/lib/commonjs/chatbot/ChatErrorBoundary.js +201 -0
- package/lib/commonjs/chatbot/ChatErrorBoundary.js.map +1 -0
- package/lib/commonjs/chatbot/ChatMessageItem.js +169 -0
- package/lib/commonjs/chatbot/ChatMessageItem.js.map +1 -0
- package/lib/commonjs/chatbot/Conversation.js +415 -0
- package/lib/commonjs/chatbot/Conversation.js.map +1 -0
- package/lib/commonjs/chatbot/ConversationScrollButton.js +131 -0
- package/lib/commonjs/chatbot/ConversationScrollButton.js.map +1 -0
- package/lib/commonjs/chatbot/Message.js +203 -0
- package/lib/commonjs/chatbot/Message.js.map +1 -0
- package/lib/commonjs/chatbot/PromptInput.js +352 -0
- package/lib/commonjs/chatbot/PromptInput.js.map +1 -0
- package/lib/commonjs/chatbot/Reasoning.js +184 -0
- package/lib/commonjs/chatbot/Reasoning.js.map +1 -0
- package/lib/commonjs/chatbot/Shimmer.js +116 -0
- package/lib/commonjs/chatbot/Shimmer.js.map +1 -0
- package/lib/commonjs/chatbot/Sources.js +212 -0
- package/lib/commonjs/chatbot/Sources.js.map +1 -0
- package/lib/commonjs/chatbot/Suggestion.js +99 -0
- package/lib/commonjs/chatbot/Suggestion.js.map +1 -0
- package/lib/commonjs/chatbot/Tool.js +307 -0
- package/lib/commonjs/chatbot/Tool.js.map +1 -0
- package/lib/commonjs/chatbot/adapters/uiMessageAdapter.js +141 -0
- package/lib/commonjs/chatbot/adapters/uiMessageAdapter.js.map +1 -0
- package/lib/commonjs/chatbot/index.js +140 -0
- package/lib/commonjs/chatbot/index.js.map +1 -0
- package/lib/commonjs/chatbot/types.js +6 -0
- package/lib/commonjs/chatbot/types.js.map +1 -0
- package/lib/commonjs/hooks/index.js +34 -0
- package/lib/commonjs/hooks/index.js.map +1 -0
- package/lib/commonjs/hooks/useAutoScroll.js +39 -0
- package/lib/commonjs/hooks/useAutoScroll.js.map +1 -0
- package/lib/commonjs/hooks/useClipboard.js +44 -0
- package/lib/commonjs/hooks/useClipboard.js.map +1 -0
- package/lib/commonjs/hooks/useCollapsible.js +35 -0
- package/lib/commonjs/hooks/useCollapsible.js.map +1 -0
- package/lib/commonjs/hooks/useStickToBottom.js +68 -0
- package/lib/commonjs/hooks/useStickToBottom.js.map +1 -0
- package/lib/commonjs/index.js +257 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/primitives/Badge.js +119 -0
- package/lib/commonjs/primitives/Badge.js.map +1 -0
- package/lib/commonjs/primitives/Button.js +185 -0
- package/lib/commonjs/primitives/Button.js.map +1 -0
- package/lib/commonjs/primitives/Card.js +166 -0
- package/lib/commonjs/primitives/Card.js.map +1 -0
- package/lib/commonjs/primitives/Collapsible.js +137 -0
- package/lib/commonjs/primitives/Collapsible.js.map +1 -0
- package/lib/commonjs/primitives/ScrollArea.js +40 -0
- package/lib/commonjs/primitives/ScrollArea.js.map +1 -0
- package/lib/commonjs/primitives/index.js +83 -0
- package/lib/commonjs/primitives/index.js.map +1 -0
- package/lib/commonjs/streaming/StreamingMarkdown.js +252 -0
- package/lib/commonjs/streaming/StreamingMarkdown.js.map +1 -0
- package/lib/commonjs/streaming/index.js +13 -0
- package/lib/commonjs/streaming/index.js.map +1 -0
- package/lib/commonjs/streaming/parser.js +482 -0
- package/lib/commonjs/streaming/parser.js.map +1 -0
- package/lib/commonjs/streaming/renderers/BlockquoteRenderer.js +35 -0
- package/lib/commonjs/streaming/renderers/BlockquoteRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/CodeRenderer.js +128 -0
- package/lib/commonjs/streaming/renderers/CodeRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/HeadingRenderer.js +61 -0
- package/lib/commonjs/streaming/renderers/HeadingRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/ImageRenderer.js +53 -0
- package/lib/commonjs/streaming/renderers/ImageRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/LinkRenderer.js +49 -0
- package/lib/commonjs/streaming/renderers/LinkRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/ListRenderer.js +63 -0
- package/lib/commonjs/streaming/renderers/ListRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/TableRenderer.js +77 -0
- package/lib/commonjs/streaming/renderers/TableRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/TextRenderer.js +41 -0
- package/lib/commonjs/streaming/renderers/TextRenderer.js.map +1 -0
- package/lib/commonjs/streaming/renderers/index.js +76 -0
- package/lib/commonjs/streaming/renderers/index.js.map +1 -0
- package/lib/commonjs/streaming/renderers/renderInlineChildren.js +112 -0
- package/lib/commonjs/streaming/renderers/renderInlineChildren.js.map +1 -0
- package/lib/commonjs/streaming/renderers/renderNode.js +81 -0
- package/lib/commonjs/streaming/renderers/renderNode.js.map +1 -0
- package/lib/commonjs/theme/ThemeProvider.js +68 -0
- package/lib/commonjs/theme/ThemeProvider.js.map +1 -0
- package/lib/commonjs/theme/defaultTheme.js +96 -0
- package/lib/commonjs/theme/defaultTheme.js.map +1 -0
- package/lib/commonjs/theme/index.js +32 -0
- package/lib/commonjs/theme/index.js.map +1 -0
- package/lib/commonjs/theme/tokens.js +2 -0
- package/lib/commonjs/theme/tokens.js.map +1 -0
- package/lib/commonjs/types.d.js +2 -0
- package/lib/commonjs/types.d.js.map +1 -0
- package/lib/commonjs/voice/index.js +13 -0
- package/lib/commonjs/voice/index.js.map +1 -0
- package/lib/commonjs/voice/useSpeechRecognition.js +172 -0
- package/lib/commonjs/voice/useSpeechRecognition.js.map +1 -0
- package/lib/module/chatbot/AIImage.js +121 -0
- package/lib/module/chatbot/AIImage.js.map +1 -0
- package/lib/module/chatbot/Attachments.js +312 -0
- package/lib/module/chatbot/Attachments.js.map +1 -0
- package/lib/module/chatbot/ChatErrorBoundary.js +196 -0
- package/lib/module/chatbot/ChatErrorBoundary.js.map +1 -0
- package/lib/module/chatbot/ChatMessageItem.js +164 -0
- package/lib/module/chatbot/ChatMessageItem.js.map +1 -0
- package/lib/module/chatbot/Conversation.js +412 -0
- package/lib/module/chatbot/Conversation.js.map +1 -0
- package/lib/module/chatbot/ConversationScrollButton.js +126 -0
- package/lib/module/chatbot/ConversationScrollButton.js.map +1 -0
- package/lib/module/chatbot/Message.js +198 -0
- package/lib/module/chatbot/Message.js.map +1 -0
- package/lib/module/chatbot/PromptInput.js +347 -0
- package/lib/module/chatbot/PromptInput.js.map +1 -0
- package/lib/module/chatbot/Reasoning.js +179 -0
- package/lib/module/chatbot/Reasoning.js.map +1 -0
- package/lib/module/chatbot/Shimmer.js +111 -0
- package/lib/module/chatbot/Shimmer.js.map +1 -0
- package/lib/module/chatbot/Sources.js +207 -0
- package/lib/module/chatbot/Sources.js.map +1 -0
- package/lib/module/chatbot/Suggestion.js +94 -0
- package/lib/module/chatbot/Suggestion.js.map +1 -0
- package/lib/module/chatbot/Tool.js +303 -0
- package/lib/module/chatbot/Tool.js.map +1 -0
- package/lib/module/chatbot/adapters/uiMessageAdapter.js +137 -0
- package/lib/module/chatbot/adapters/uiMessageAdapter.js.map +1 -0
- package/lib/module/chatbot/index.js +39 -0
- package/lib/module/chatbot/index.js.map +1 -0
- package/lib/module/chatbot/types.js +4 -0
- package/lib/module/chatbot/types.js.map +1 -0
- package/lib/module/hooks/index.js +7 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/useAutoScroll.js +35 -0
- package/lib/module/hooks/useAutoScroll.js.map +1 -0
- package/lib/module/hooks/useClipboard.js +40 -0
- package/lib/module/hooks/useClipboard.js.map +1 -0
- package/lib/module/hooks/useCollapsible.js +31 -0
- package/lib/module/hooks/useCollapsible.js.map +1 -0
- package/lib/module/hooks/useStickToBottom.js +64 -0
- package/lib/module/hooks/useStickToBottom.js.map +1 -0
- package/lib/module/index.js +19 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/primitives/Badge.js +114 -0
- package/lib/module/primitives/Badge.js.map +1 -0
- package/lib/module/primitives/Button.js +180 -0
- package/lib/module/primitives/Button.js.map +1 -0
- package/lib/module/primitives/Card.js +156 -0
- package/lib/module/primitives/Card.js.map +1 -0
- package/lib/module/primitives/Collapsible.js +130 -0
- package/lib/module/primitives/Collapsible.js.map +1 -0
- package/lib/module/primitives/ScrollArea.js +35 -0
- package/lib/module/primitives/ScrollArea.js.map +1 -0
- package/lib/module/primitives/index.js +8 -0
- package/lib/module/primitives/index.js.map +1 -0
- package/lib/module/streaming/StreamingMarkdown.js +246 -0
- package/lib/module/streaming/StreamingMarkdown.js.map +1 -0
- package/lib/module/streaming/index.js +4 -0
- package/lib/module/streaming/index.js.map +1 -0
- package/lib/module/streaming/parser.js +477 -0
- package/lib/module/streaming/parser.js.map +1 -0
- package/lib/module/streaming/renderers/BlockquoteRenderer.js +30 -0
- package/lib/module/streaming/renderers/BlockquoteRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/CodeRenderer.js +123 -0
- package/lib/module/streaming/renderers/CodeRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/HeadingRenderer.js +56 -0
- package/lib/module/streaming/renderers/HeadingRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/ImageRenderer.js +48 -0
- package/lib/module/streaming/renderers/ImageRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/LinkRenderer.js +44 -0
- package/lib/module/streaming/renderers/LinkRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/ListRenderer.js +58 -0
- package/lib/module/streaming/renderers/ListRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/TableRenderer.js +72 -0
- package/lib/module/streaming/renderers/TableRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/TextRenderer.js +36 -0
- package/lib/module/streaming/renderers/TextRenderer.js.map +1 -0
- package/lib/module/streaming/renderers/index.js +13 -0
- package/lib/module/streaming/renderers/index.js.map +1 -0
- package/lib/module/streaming/renderers/renderInlineChildren.js +107 -0
- package/lib/module/streaming/renderers/renderInlineChildren.js.map +1 -0
- package/lib/module/streaming/renderers/renderNode.js +78 -0
- package/lib/module/streaming/renderers/renderNode.js.map +1 -0
- package/lib/module/theme/ThemeProvider.js +62 -0
- package/lib/module/theme/ThemeProvider.js.map +1 -0
- package/lib/module/theme/defaultTheme.js +92 -0
- package/lib/module/theme/defaultTheme.js.map +1 -0
- package/lib/module/theme/index.js +5 -0
- package/lib/module/theme/index.js.map +1 -0
- package/lib/module/theme/tokens.js +2 -0
- package/lib/module/theme/tokens.js.map +1 -0
- package/lib/module/types.d.js +2 -0
- package/lib/module/types.d.js.map +1 -0
- package/lib/module/voice/index.js +14 -0
- package/lib/module/voice/index.js.map +1 -0
- package/lib/module/voice/useSpeechRecognition.js +169 -0
- package/lib/module/voice/useSpeechRecognition.js.map +1 -0
- package/lib/typescript/src/chatbot/AIImage.d.ts +24 -0
- package/lib/typescript/src/chatbot/AIImage.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Attachments.d.ts +20 -0
- package/lib/typescript/src/chatbot/Attachments.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/ChatErrorBoundary.d.ts +57 -0
- package/lib/typescript/src/chatbot/ChatErrorBoundary.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/ChatMessageItem.d.ts +45 -0
- package/lib/typescript/src/chatbot/ChatMessageItem.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Conversation.d.ts +94 -0
- package/lib/typescript/src/chatbot/Conversation.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/ConversationScrollButton.d.ts +62 -0
- package/lib/typescript/src/chatbot/ConversationScrollButton.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Message.d.ts +39 -0
- package/lib/typescript/src/chatbot/Message.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/PromptInput.d.ts +93 -0
- package/lib/typescript/src/chatbot/PromptInput.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Reasoning.d.ts +14 -0
- package/lib/typescript/src/chatbot/Reasoning.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Shimmer.d.ts +13 -0
- package/lib/typescript/src/chatbot/Shimmer.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Sources.d.ts +17 -0
- package/lib/typescript/src/chatbot/Sources.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Suggestion.d.ts +15 -0
- package/lib/typescript/src/chatbot/Suggestion.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/Tool.d.ts +30 -0
- package/lib/typescript/src/chatbot/Tool.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/adapters/uiMessageAdapter.d.ts +24 -0
- package/lib/typescript/src/chatbot/adapters/uiMessageAdapter.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/index.d.ts +29 -0
- package/lib/typescript/src/chatbot/index.d.ts.map +1 -0
- package/lib/typescript/src/chatbot/types.d.ts +49 -0
- package/lib/typescript/src/chatbot/types.d.ts.map +1 -0
- package/lib/typescript/src/hooks/index.d.ts +9 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useAutoScroll.d.ts +23 -0
- package/lib/typescript/src/hooks/useAutoScroll.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useClipboard.d.ts +22 -0
- package/lib/typescript/src/hooks/useClipboard.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useCollapsible.d.ts +28 -0
- package/lib/typescript/src/hooks/useCollapsible.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useStickToBottom.d.ts +39 -0
- package/lib/typescript/src/hooks/useStickToBottom.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +11 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Badge.d.ts +10 -0
- package/lib/typescript/src/primitives/Badge.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Button.d.ts +16 -0
- package/lib/typescript/src/primitives/Button.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Card.d.ts +33 -0
- package/lib/typescript/src/primitives/Card.d.ts.map +1 -0
- package/lib/typescript/src/primitives/Collapsible.d.ts +20 -0
- package/lib/typescript/src/primitives/Collapsible.d.ts.map +1 -0
- package/lib/typescript/src/primitives/ScrollArea.d.ts +10 -0
- package/lib/typescript/src/primitives/ScrollArea.d.ts.map +1 -0
- package/lib/typescript/src/primitives/index.d.ts +11 -0
- package/lib/typescript/src/primitives/index.d.ts.map +1 -0
- package/lib/typescript/src/streaming/StreamingMarkdown.d.ts +47 -0
- package/lib/typescript/src/streaming/StreamingMarkdown.d.ts.map +1 -0
- package/lib/typescript/src/streaming/index.d.ts +3 -0
- package/lib/typescript/src/streaming/index.d.ts.map +1 -0
- package/lib/typescript/src/streaming/parser.d.ts +41 -0
- package/lib/typescript/src/streaming/parser.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/BlockquoteRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/BlockquoteRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/CodeRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/CodeRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/HeadingRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/HeadingRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/ImageRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/ImageRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/LinkRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/LinkRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/ListRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/ListRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/TableRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/TableRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/TextRenderer.d.ts +7 -0
- package/lib/typescript/src/streaming/renderers/TextRenderer.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/index.d.ts +19 -0
- package/lib/typescript/src/streaming/renderers/index.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/renderInlineChildren.d.ts +12 -0
- package/lib/typescript/src/streaming/renderers/renderInlineChildren.d.ts.map +1 -0
- package/lib/typescript/src/streaming/renderers/renderNode.d.ts +8 -0
- package/lib/typescript/src/streaming/renderers/renderNode.d.ts.map +1 -0
- package/lib/typescript/src/theme/ThemeProvider.d.ts +14 -0
- package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -0
- package/lib/typescript/src/theme/defaultTheme.d.ts +4 -0
- package/lib/typescript/src/theme/defaultTheme.d.ts.map +1 -0
- package/lib/typescript/src/theme/index.d.ts +5 -0
- package/lib/typescript/src/theme/index.d.ts.map +1 -0
- package/lib/typescript/src/theme/tokens.d.ts +66 -0
- package/lib/typescript/src/theme/tokens.d.ts.map +1 -0
- package/lib/typescript/src/voice/index.d.ts +3 -0
- package/lib/typescript/src/voice/index.d.ts.map +1 -0
- package/lib/typescript/src/voice/useSpeechRecognition.d.ts +77 -0
- package/lib/typescript/src/voice/useSpeechRecognition.d.ts.map +1 -0
- package/package.json +132 -0
- package/src/chatbot/AIImage.tsx +166 -0
- package/src/chatbot/Attachments.tsx +382 -0
- package/src/chatbot/ChatErrorBoundary.tsx +230 -0
- package/src/chatbot/ChatMessageItem.tsx +195 -0
- package/src/chatbot/Conversation.tsx +537 -0
- package/src/chatbot/ConversationScrollButton.tsx +149 -0
- package/src/chatbot/Message.tsx +266 -0
- package/src/chatbot/PromptInput.tsx +532 -0
- package/src/chatbot/Reasoning.tsx +198 -0
- package/src/chatbot/Shimmer.tsx +146 -0
- package/src/chatbot/Sources.tsx +263 -0
- package/src/chatbot/Suggestion.tsx +123 -0
- package/src/chatbot/Tool.tsx +340 -0
- package/src/chatbot/adapters/uiMessageAdapter.ts +177 -0
- package/src/chatbot/index.ts +97 -0
- package/src/chatbot/types.ts +66 -0
- package/src/hooks/index.ts +17 -0
- package/src/hooks/useAutoScroll.ts +43 -0
- package/src/hooks/useClipboard.ts +46 -0
- package/src/hooks/useCollapsible.ts +42 -0
- package/src/hooks/useStickToBottom.ts +82 -0
- package/src/index.ts +139 -0
- package/src/primitives/Badge.tsx +119 -0
- package/src/primitives/Button.tsx +213 -0
- package/src/primitives/Card.tsx +221 -0
- package/src/primitives/Collapsible.tsx +168 -0
- package/src/primitives/ScrollArea.tsx +53 -0
- package/src/primitives/index.ts +36 -0
- package/src/streaming/StreamingMarkdown.tsx +282 -0
- package/src/streaming/index.ts +2 -0
- package/src/streaming/parser.ts +506 -0
- package/src/streaming/renderers/BlockquoteRenderer.tsx +42 -0
- package/src/streaming/renderers/CodeRenderer.tsx +158 -0
- package/src/streaming/renderers/HeadingRenderer.tsx +64 -0
- package/src/streaming/renderers/ImageRenderer.tsx +62 -0
- package/src/streaming/renderers/LinkRenderer.tsx +53 -0
- package/src/streaming/renderers/ListRenderer.tsx +65 -0
- package/src/streaming/renderers/TableRenderer.tsx +103 -0
- package/src/streaming/renderers/TextRenderer.tsx +39 -0
- package/src/streaming/renderers/index.ts +26 -0
- package/src/streaming/renderers/renderInlineChildren.tsx +115 -0
- package/src/streaming/renderers/renderNode.tsx +72 -0
- package/src/theme/ThemeProvider.tsx +77 -0
- package/src/theme/defaultTheme.ts +93 -0
- package/src/theme/index.ts +4 -0
- package/src/theme/tokens.ts +69 -0
- package/src/types.d.ts +71 -0
- package/src/voice/index.ts +15 -0
- package/src/voice/useSpeechRecognition.ts +230 -0
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useImperativeHandle,
|
|
5
|
+
useRef,
|
|
6
|
+
useState,
|
|
7
|
+
type ReactNode,
|
|
8
|
+
} from 'react';
|
|
9
|
+
import {
|
|
10
|
+
ActivityIndicator,
|
|
11
|
+
Platform,
|
|
12
|
+
Pressable,
|
|
13
|
+
StyleSheet,
|
|
14
|
+
TextInput,
|
|
15
|
+
View,
|
|
16
|
+
type NativeSyntheticEvent,
|
|
17
|
+
type TextInputContentSizeChangeEventData,
|
|
18
|
+
type TextInputProps,
|
|
19
|
+
type ViewProps,
|
|
20
|
+
} from 'react-native';
|
|
21
|
+
import { Plus, Mic, ArrowUp, Square, AlertCircle } from 'lucide-react-native';
|
|
22
|
+
import { KeyboardStickyView } from 'react-native-keyboard-controller';
|
|
23
|
+
import { GlassView } from 'expo-glass-effect';
|
|
24
|
+
import { useAIElementsTheme } from '../theme';
|
|
25
|
+
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Types
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Lifecycle status of the chat the PromptInput is attached to. Drives the
|
|
32
|
+
* shape of the right-side action button.
|
|
33
|
+
*
|
|
34
|
+
* - `'ready'` — idle. Right action shows mic (empty) or send (has text).
|
|
35
|
+
* - `'submitted'` — request just sent, awaiting first token. Right action
|
|
36
|
+
* shows a spinner.
|
|
37
|
+
* - `'streaming'` — assistant is generating. Right action shows a Stop
|
|
38
|
+
* button (calls `onStop` when pressed).
|
|
39
|
+
* - `'error'` — request failed. Right action shows an error icon; tap
|
|
40
|
+
* re-submits.
|
|
41
|
+
*
|
|
42
|
+
* Inspired by Vercel ai-elements `PromptInputSubmit.status`.
|
|
43
|
+
*/
|
|
44
|
+
export type PromptInputStatus = 'ready' | 'submitted' | 'streaming' | 'error';
|
|
45
|
+
|
|
46
|
+
/** Imperative handle exposed via ref. */
|
|
47
|
+
export interface PromptInputRef {
|
|
48
|
+
/** Focus the underlying TextInput. */
|
|
49
|
+
focus: () => void;
|
|
50
|
+
/** Blur the underlying TextInput. */
|
|
51
|
+
blur: () => void;
|
|
52
|
+
/** Clear the input value and reset the expanding-textarea height. */
|
|
53
|
+
clear: () => void;
|
|
54
|
+
/** Whether the underlying TextInput currently has focus. */
|
|
55
|
+
isFocused: () => boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface PromptInputProps extends Omit<ViewProps, 'children'> {
|
|
59
|
+
/** Current input text value (controlled). */
|
|
60
|
+
value: string;
|
|
61
|
+
/** Called when the input text changes. */
|
|
62
|
+
onChangeText: (text: string) => void;
|
|
63
|
+
/**
|
|
64
|
+
* Called when the user submits — either by tapping the send button or
|
|
65
|
+
* pressing enter/return on the keyboard.
|
|
66
|
+
*/
|
|
67
|
+
onSubmit: () => void;
|
|
68
|
+
/**
|
|
69
|
+
* Called when the user taps the Stop button while `status === 'streaming'`.
|
|
70
|
+
* If omitted, the Stop button still appears but does nothing on press.
|
|
71
|
+
*/
|
|
72
|
+
onStop?: () => void;
|
|
73
|
+
/**
|
|
74
|
+
* Lifecycle status. When omitted (or `'ready'`), the right-side action
|
|
75
|
+
* uses the legacy mic-or-send behavior driven by `disabled`.
|
|
76
|
+
*/
|
|
77
|
+
status?: PromptInputStatus;
|
|
78
|
+
/**
|
|
79
|
+
* Disables editing. Independent of `status` so callers can keep the bar
|
|
80
|
+
* editable while showing a loader, or vice-versa.
|
|
81
|
+
*/
|
|
82
|
+
disabled?: boolean;
|
|
83
|
+
/** Placeholder text. Default: `"Ask me anything..."` */
|
|
84
|
+
placeholder?: string;
|
|
85
|
+
/** Minimum pill height. Default `36`. */
|
|
86
|
+
minHeight?: number;
|
|
87
|
+
/** Maximum pill height before the textarea scrolls. Default `100`. */
|
|
88
|
+
maxHeight?: number;
|
|
89
|
+
/** Safe-area bottom inset — applied to the row and the keyboard offset. */
|
|
90
|
+
bottomInset?: number;
|
|
91
|
+
/** Slot above the input row (e.g. starter suggestions). */
|
|
92
|
+
suggestions?: ReactNode;
|
|
93
|
+
/** Optional override for the default left action (Plus circle). */
|
|
94
|
+
leftAction?: ReactNode;
|
|
95
|
+
/** Pressed when the default Plus button is tapped. */
|
|
96
|
+
onLeftActionPress?: () => void;
|
|
97
|
+
/** Optional override for the default right action (Mic / Send / Stop). */
|
|
98
|
+
rightAction?: ReactNode;
|
|
99
|
+
/**
|
|
100
|
+
* True while a speech-recognition session is active. When set, the
|
|
101
|
+
* default mic button flips to an "active" look (destructive tint +
|
|
102
|
+
* subtle pulsing) so the recording state is obvious. Pair with
|
|
103
|
+
* `onMicPress` to actually start/stop recognition.
|
|
104
|
+
*/
|
|
105
|
+
isListening?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Handler for the default mic button. When omitted (or when a custom
|
|
108
|
+
* `rightAction` is provided) the built-in mic is a no-op placeholder.
|
|
109
|
+
* Typically wired to a `useSpeechRecognition` hook's `toggle()`.
|
|
110
|
+
*/
|
|
111
|
+
onMicPress?: () => void;
|
|
112
|
+
/**
|
|
113
|
+
* iOS software keyboard appearance. Defaults to the current theme's mode
|
|
114
|
+
* (`'dark'` when the theme is dark, `'light'` otherwise). Pass `'default'`
|
|
115
|
+
* to fall back to the system setting, or force a specific value.
|
|
116
|
+
*
|
|
117
|
+
* Note: iOS only — Android ignores this.
|
|
118
|
+
*/
|
|
119
|
+
keyboardAppearance?: TextInputProps['keyboardAppearance'];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// Constants
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
const DEFAULT_MIN_HEIGHT = 36;
|
|
127
|
+
const DEFAULT_MAX_HEIGHT = 100;
|
|
128
|
+
const CIRCLE_BUTTON_SIZE = 36;
|
|
129
|
+
const ICON_SIZE = 18;
|
|
130
|
+
const isIOS = Platform.OS === 'ios';
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// CircleButton — lucide icon inside a native iOS glass circle.
|
|
134
|
+
// Uses `expo-glass-effect`'s GlassView, which renders a real
|
|
135
|
+
// UIVisualEffectView on iOS (liquid glass on iOS 26+) and degrades to a
|
|
136
|
+
// plain View on Android/web.
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
|
|
139
|
+
interface CircleButtonProps {
|
|
140
|
+
/** Icon node (any RN component — lucide, image, custom). */
|
|
141
|
+
icon: React.ReactNode;
|
|
142
|
+
/** Press handler. Skipped when undefined / disabled. */
|
|
143
|
+
onPress?: () => void;
|
|
144
|
+
/** Disables the button visually and prevents press events. */
|
|
145
|
+
isDisabled?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Optional tint color for the glass — used to make the active send
|
|
148
|
+
* button visually prominent. Hex string.
|
|
149
|
+
*/
|
|
150
|
+
tintColor?: string;
|
|
151
|
+
/** Drives the GlassView color scheme so the glass picks the right tone. */
|
|
152
|
+
dark: boolean;
|
|
153
|
+
/** Background color used on non-iOS where GlassView is a plain View. */
|
|
154
|
+
fallbackBackground: string;
|
|
155
|
+
/** Accessibility label for screen readers. */
|
|
156
|
+
accessibilityLabel?: string;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function CircleButton({
|
|
160
|
+
icon,
|
|
161
|
+
onPress,
|
|
162
|
+
isDisabled = false,
|
|
163
|
+
tintColor,
|
|
164
|
+
dark,
|
|
165
|
+
fallbackBackground,
|
|
166
|
+
accessibilityLabel,
|
|
167
|
+
}: CircleButtonProps) {
|
|
168
|
+
return (
|
|
169
|
+
<GlassView
|
|
170
|
+
glassEffectStyle={isIOS ? 'regular' : 'none'}
|
|
171
|
+
tintColor={tintColor}
|
|
172
|
+
isInteractive
|
|
173
|
+
colorScheme={dark ? 'dark' : 'light'}
|
|
174
|
+
style={[
|
|
175
|
+
styles.circleButton,
|
|
176
|
+
// On non-iOS GlassView is just a plain View, so paint the bg
|
|
177
|
+
// ourselves to keep the visible circle.
|
|
178
|
+
!isIOS && { backgroundColor: fallbackBackground },
|
|
179
|
+
]}
|
|
180
|
+
>
|
|
181
|
+
<Pressable
|
|
182
|
+
onPress={onPress}
|
|
183
|
+
disabled={isDisabled}
|
|
184
|
+
accessibilityLabel={accessibilityLabel}
|
|
185
|
+
accessibilityRole="button"
|
|
186
|
+
accessibilityState={{ disabled: isDisabled }}
|
|
187
|
+
style={({ pressed }) => [
|
|
188
|
+
styles.circleButtonInner,
|
|
189
|
+
{ opacity: pressed ? 0.6 : isDisabled ? 0.5 : 1 },
|
|
190
|
+
]}
|
|
191
|
+
>
|
|
192
|
+
{icon}
|
|
193
|
+
</Pressable>
|
|
194
|
+
</GlassView>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
CircleButton.displayName = 'PromptInput.CircleButton';
|
|
199
|
+
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// Component
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* The sticky bottom input bar for a chat. Owns its own expanding-textarea
|
|
206
|
+
* height state so keystrokes don't re-render the parent screen. Moves with
|
|
207
|
+
* the keyboard via `KeyboardStickyView` from `react-native-keyboard-controller`.
|
|
208
|
+
*
|
|
209
|
+
* The right-side action is computed from `status`:
|
|
210
|
+
* - `'submitted'` → spinner
|
|
211
|
+
* - `'streaming'` → Stop button (calls `onStop`)
|
|
212
|
+
* - `'error'` → error icon (tap re-submits)
|
|
213
|
+
* - otherwise → Mic (empty input) or Send (has input)
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```tsx
|
|
217
|
+
* <PromptInput
|
|
218
|
+
* value={input}
|
|
219
|
+
* onChangeText={setInput}
|
|
220
|
+
* onSubmit={sendMessage}
|
|
221
|
+
* onStop={stop}
|
|
222
|
+
* status={isStreaming ? 'streaming' : 'ready'}
|
|
223
|
+
* bottomInset={insets.bottom}
|
|
224
|
+
* suggestions={messages.length === 0 ? <Suggestions /> : null}
|
|
225
|
+
* />
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
const PromptInputImpl = forwardRef<PromptInputRef, PromptInputProps>(
|
|
229
|
+
function PromptInput(
|
|
230
|
+
{
|
|
231
|
+
value,
|
|
232
|
+
onChangeText,
|
|
233
|
+
onSubmit,
|
|
234
|
+
onStop,
|
|
235
|
+
status = 'ready',
|
|
236
|
+
disabled = false,
|
|
237
|
+
placeholder = 'Ask me anything...',
|
|
238
|
+
minHeight = DEFAULT_MIN_HEIGHT,
|
|
239
|
+
maxHeight = DEFAULT_MAX_HEIGHT,
|
|
240
|
+
bottomInset = 0,
|
|
241
|
+
suggestions,
|
|
242
|
+
leftAction,
|
|
243
|
+
onLeftActionPress,
|
|
244
|
+
rightAction,
|
|
245
|
+
isListening = false,
|
|
246
|
+
onMicPress,
|
|
247
|
+
keyboardAppearance,
|
|
248
|
+
style,
|
|
249
|
+
...viewProps
|
|
250
|
+
},
|
|
251
|
+
ref,
|
|
252
|
+
) {
|
|
253
|
+
const theme = useAIElementsTheme();
|
|
254
|
+
const textInputRef = useRef<TextInput>(null);
|
|
255
|
+
const [inputHeight, setInputHeight] = useState(minHeight);
|
|
256
|
+
|
|
257
|
+
// Default the iOS keyboard to match the current theme. An explicit prop
|
|
258
|
+
// from the caller still wins.
|
|
259
|
+
const effectiveKeyboardAppearance =
|
|
260
|
+
keyboardAppearance ?? (theme.dark ? 'dark' : 'light');
|
|
261
|
+
|
|
262
|
+
const hasText = value.trim().length > 0;
|
|
263
|
+
const canSubmit = hasText && !disabled && status === 'ready';
|
|
264
|
+
|
|
265
|
+
useImperativeHandle(
|
|
266
|
+
ref,
|
|
267
|
+
() => ({
|
|
268
|
+
focus: () => textInputRef.current?.focus(),
|
|
269
|
+
blur: () => textInputRef.current?.blur(),
|
|
270
|
+
clear: () => {
|
|
271
|
+
onChangeText('');
|
|
272
|
+
setInputHeight(minHeight);
|
|
273
|
+
},
|
|
274
|
+
isFocused: () => textInputRef.current?.isFocused() ?? false,
|
|
275
|
+
}),
|
|
276
|
+
[onChangeText, minHeight],
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const handleContentSizeChange = useCallback(
|
|
280
|
+
(e: NativeSyntheticEvent<TextInputContentSizeChangeEventData>) => {
|
|
281
|
+
const next = Math.min(
|
|
282
|
+
Math.max(e.nativeEvent.contentSize.height, minHeight),
|
|
283
|
+
maxHeight,
|
|
284
|
+
);
|
|
285
|
+
setInputHeight(next);
|
|
286
|
+
},
|
|
287
|
+
[minHeight, maxHeight],
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
const handleSubmit = useCallback(() => {
|
|
291
|
+
if (!canSubmit) return;
|
|
292
|
+
onSubmit();
|
|
293
|
+
setInputHeight(minHeight);
|
|
294
|
+
}, [canSubmit, onSubmit, minHeight]);
|
|
295
|
+
|
|
296
|
+
// --- Defaults -----------------------------------------------------------
|
|
297
|
+
// CircleButton wraps a lucide icon inside a real native iOS glass effect
|
|
298
|
+
// (UIVisualEffectView / liquid glass on iOS 26+). On Android/web it
|
|
299
|
+
// degrades to a flat themed circle so behavior is preserved.
|
|
300
|
+
|
|
301
|
+
const defaultLeftAction = (
|
|
302
|
+
<CircleButton
|
|
303
|
+
icon={<Plus size={ICON_SIZE} color={theme.colors.foreground} />}
|
|
304
|
+
onPress={onLeftActionPress}
|
|
305
|
+
dark={theme.dark}
|
|
306
|
+
fallbackBackground={theme.colors.secondary}
|
|
307
|
+
accessibilityLabel="More options"
|
|
308
|
+
/>
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
// The right-side action is a function of `status` first, then text content.
|
|
312
|
+
const defaultRightAction = (() => {
|
|
313
|
+
if (status === 'streaming') {
|
|
314
|
+
return (
|
|
315
|
+
<CircleButton
|
|
316
|
+
icon={
|
|
317
|
+
<Square
|
|
318
|
+
size={14}
|
|
319
|
+
color={theme.colors.background}
|
|
320
|
+
fill={theme.colors.background}
|
|
321
|
+
/>
|
|
322
|
+
}
|
|
323
|
+
onPress={onStop}
|
|
324
|
+
tintColor={theme.colors.foreground}
|
|
325
|
+
dark={theme.dark}
|
|
326
|
+
fallbackBackground={theme.colors.foreground}
|
|
327
|
+
accessibilityLabel="Stop generating"
|
|
328
|
+
/>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (status === 'submitted') {
|
|
333
|
+
return (
|
|
334
|
+
<CircleButton
|
|
335
|
+
icon={
|
|
336
|
+
<ActivityIndicator
|
|
337
|
+
size="small"
|
|
338
|
+
color={theme.colors.foreground}
|
|
339
|
+
/>
|
|
340
|
+
}
|
|
341
|
+
isDisabled
|
|
342
|
+
dark={theme.dark}
|
|
343
|
+
fallbackBackground={theme.colors.secondary}
|
|
344
|
+
accessibilityLabel="Sending"
|
|
345
|
+
/>
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (status === 'error') {
|
|
350
|
+
return (
|
|
351
|
+
<CircleButton
|
|
352
|
+
icon={
|
|
353
|
+
<AlertCircle size={ICON_SIZE} color={theme.colors.destructive} />
|
|
354
|
+
}
|
|
355
|
+
onPress={hasText && !disabled ? handleSubmit : undefined}
|
|
356
|
+
dark={theme.dark}
|
|
357
|
+
fallbackBackground={theme.colors.secondary}
|
|
358
|
+
accessibilityLabel="Send failed — tap to retry"
|
|
359
|
+
/>
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// status === 'ready' — original mic/send behavior.
|
|
364
|
+
if (hasText) {
|
|
365
|
+
return (
|
|
366
|
+
<CircleButton
|
|
367
|
+
icon={
|
|
368
|
+
<ArrowUp
|
|
369
|
+
size={ICON_SIZE}
|
|
370
|
+
color={
|
|
371
|
+
canSubmit
|
|
372
|
+
? theme.colors.background
|
|
373
|
+
: theme.colors.mutedForeground
|
|
374
|
+
}
|
|
375
|
+
/>
|
|
376
|
+
}
|
|
377
|
+
onPress={canSubmit ? handleSubmit : undefined}
|
|
378
|
+
isDisabled={!canSubmit}
|
|
379
|
+
// Tint the glass with the foreground color so the active send
|
|
380
|
+
// button reads as prominent against the muted plus/mic siblings.
|
|
381
|
+
tintColor={canSubmit ? theme.colors.foreground : undefined}
|
|
382
|
+
dark={theme.dark}
|
|
383
|
+
fallbackBackground={
|
|
384
|
+
canSubmit ? theme.colors.foreground : theme.colors.secondary
|
|
385
|
+
}
|
|
386
|
+
accessibilityLabel="Send message"
|
|
387
|
+
/>
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Empty input + not streaming → Mic (voice input).
|
|
392
|
+
// While listening, tint the glass with `destructive` and flip the
|
|
393
|
+
// icon color so the recording state is unmissable.
|
|
394
|
+
return (
|
|
395
|
+
<CircleButton
|
|
396
|
+
icon={
|
|
397
|
+
<Mic
|
|
398
|
+
size={ICON_SIZE}
|
|
399
|
+
color={
|
|
400
|
+
isListening
|
|
401
|
+
? theme.colors.destructiveForeground
|
|
402
|
+
: theme.colors.foreground
|
|
403
|
+
}
|
|
404
|
+
/>
|
|
405
|
+
}
|
|
406
|
+
onPress={onMicPress}
|
|
407
|
+
tintColor={isListening ? theme.colors.destructive : undefined}
|
|
408
|
+
dark={theme.dark}
|
|
409
|
+
fallbackBackground={
|
|
410
|
+
isListening ? theme.colors.destructive : theme.colors.secondary
|
|
411
|
+
}
|
|
412
|
+
accessibilityLabel={
|
|
413
|
+
isListening ? 'Stop voice input' : 'Start voice input'
|
|
414
|
+
}
|
|
415
|
+
/>
|
|
416
|
+
);
|
|
417
|
+
})();
|
|
418
|
+
|
|
419
|
+
return (
|
|
420
|
+
<KeyboardStickyView offset={{ opened: bottomInset, closed: 0 }}>
|
|
421
|
+
{suggestions}
|
|
422
|
+
|
|
423
|
+
<View
|
|
424
|
+
{...viewProps}
|
|
425
|
+
style={[
|
|
426
|
+
styles.row,
|
|
427
|
+
{
|
|
428
|
+
paddingHorizontal: theme.spacing.md,
|
|
429
|
+
paddingBottom: bottomInset + theme.spacing.sm,
|
|
430
|
+
},
|
|
431
|
+
style,
|
|
432
|
+
]}
|
|
433
|
+
>
|
|
434
|
+
{leftAction ?? defaultLeftAction}
|
|
435
|
+
|
|
436
|
+
<GlassView
|
|
437
|
+
glassEffectStyle={isIOS ? 'regular' : 'none'}
|
|
438
|
+
isInteractive
|
|
439
|
+
colorScheme={theme.dark ? 'dark' : 'light'}
|
|
440
|
+
style={[
|
|
441
|
+
styles.inputPill,
|
|
442
|
+
// On iOS, the glass provides its own subtle edge — no border.
|
|
443
|
+
// On Android/web fall back to the original tinted pill.
|
|
444
|
+
isIOS
|
|
445
|
+
? null
|
|
446
|
+
: {
|
|
447
|
+
backgroundColor: theme.colors.secondary,
|
|
448
|
+
borderWidth: 1,
|
|
449
|
+
borderColor: theme.dark
|
|
450
|
+
? 'transparent'
|
|
451
|
+
: theme.colors.border,
|
|
452
|
+
},
|
|
453
|
+
]}
|
|
454
|
+
>
|
|
455
|
+
<TextInput
|
|
456
|
+
ref={textInputRef}
|
|
457
|
+
value={value}
|
|
458
|
+
onChangeText={onChangeText}
|
|
459
|
+
placeholder={placeholder}
|
|
460
|
+
placeholderTextColor={theme.colors.mutedForeground}
|
|
461
|
+
multiline
|
|
462
|
+
editable={!disabled}
|
|
463
|
+
keyboardAppearance={effectiveKeyboardAppearance}
|
|
464
|
+
onContentSizeChange={handleContentSizeChange}
|
|
465
|
+
onSubmitEditing={handleSubmit}
|
|
466
|
+
blurOnSubmit={false}
|
|
467
|
+
accessibilityLabel="Message input"
|
|
468
|
+
style={[
|
|
469
|
+
styles.textInput,
|
|
470
|
+
{
|
|
471
|
+
height: inputHeight,
|
|
472
|
+
maxHeight,
|
|
473
|
+
color: theme.colors.foreground,
|
|
474
|
+
fontSize: theme.typography.fontSize.md,
|
|
475
|
+
fontFamily: theme.typography.fontFamily,
|
|
476
|
+
},
|
|
477
|
+
]}
|
|
478
|
+
/>
|
|
479
|
+
</GlassView>
|
|
480
|
+
|
|
481
|
+
{rightAction ?? defaultRightAction}
|
|
482
|
+
</View>
|
|
483
|
+
</KeyboardStickyView>
|
|
484
|
+
);
|
|
485
|
+
},
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
PromptInputImpl.displayName = 'PromptInput';
|
|
489
|
+
|
|
490
|
+
export const PromptInput = PromptInputImpl;
|
|
491
|
+
|
|
492
|
+
// ---------------------------------------------------------------------------
|
|
493
|
+
// Styles — static so they're not reallocated per render
|
|
494
|
+
// ---------------------------------------------------------------------------
|
|
495
|
+
|
|
496
|
+
const styles = StyleSheet.create({
|
|
497
|
+
row: {
|
|
498
|
+
flexDirection: 'row',
|
|
499
|
+
alignItems: 'flex-end',
|
|
500
|
+
gap: 8,
|
|
501
|
+
},
|
|
502
|
+
circleButton: {
|
|
503
|
+
width: CIRCLE_BUTTON_SIZE,
|
|
504
|
+
height: CIRCLE_BUTTON_SIZE,
|
|
505
|
+
borderRadius: CIRCLE_BUTTON_SIZE / 2,
|
|
506
|
+
// Clip the GlassView blur to the rounded shape on iOS, and the
|
|
507
|
+
// background fill on other platforms.
|
|
508
|
+
overflow: 'hidden',
|
|
509
|
+
alignItems: 'center',
|
|
510
|
+
justifyContent: 'center',
|
|
511
|
+
},
|
|
512
|
+
circleButtonInner: {
|
|
513
|
+
width: '100%',
|
|
514
|
+
height: '100%',
|
|
515
|
+
alignItems: 'center',
|
|
516
|
+
justifyContent: 'center',
|
|
517
|
+
},
|
|
518
|
+
inputPill: {
|
|
519
|
+
flex: 1,
|
|
520
|
+
borderRadius: 20,
|
|
521
|
+
paddingHorizontal: 14,
|
|
522
|
+
// Clip the GlassView blur (and the non-iOS background) to the rounded
|
|
523
|
+
// pill shape.
|
|
524
|
+
overflow: 'hidden',
|
|
525
|
+
},
|
|
526
|
+
textInput: {
|
|
527
|
+
textAlignVertical: 'top',
|
|
528
|
+
paddingTop: Platform.OS === 'ios' ? 8 : 6,
|
|
529
|
+
paddingBottom: Platform.OS === 'ios' ? 8 : 6,
|
|
530
|
+
paddingHorizontal: 0,
|
|
531
|
+
},
|
|
532
|
+
});
|