1import { TextInputWrapper } from "expo-paste-input";
2import { useImperativeHandle, useRef } from "react";
3import { TextInput, type TextInputInstance } from "react-native";
4
5import { useFontFamily } from "../lib/useFontFamily";
6import { useScaledTextRole } from "../features/settings/appearance/useScaledTextRole";
7import { useNativePaste } from "../lib/useNativePaste";
8import type { ComposerEditorProps } from "./T3ComposerEditor.types";
9
10export function ComposerEditor({
11 ref,
12 skills: _skills,
13 selection,
14 onPasteImages,
15 onPasteText: _onPasteText,
16 style,
17 textStyle,
18 contentInsetVertical = 0,
19 singleLineCentered: _singleLineCentered,
20 enterBehavior: _enterBehavior,
21 readOnly = false,
22 ...props
23}: ComposerEditorProps) {
24 const inputRef = useRef<TextInputInstance>(null);
25 const bodyText = useScaledTextRole("body");
26 const fontFamily = useFontFamily("regular");
27 const handlePaste = useNativePaste((uris) => onPasteImages?.(uris));
28
29 useImperativeHandle(
30 ref,
31 () => ({
32 focus: () => inputRef.current?.focus(),
33 blur: () => inputRef.current?.blur(),
34 setSelection: (nextSelection) =>
35 inputRef.current?.setSelection(nextSelection.start, nextSelection.end),
36 }),
37 [],
38 );
39
40 return (
41 <TextInputWrapper onPaste={handlePaste} style={[{ minHeight: 0 }, style]}>
42 <TextInput
43 ref={inputRef}
44 {...props}
45 editable={(props.editable ?? true) && !readOnly}
46 selection={selection}
47 onSelectionChange={(event) => props.onSelectionChange?.(event.nativeEvent.selection)}
48 multiline={props.multiline ?? true}
49 placeholderTextColorClassName={"accent-placeholder"}
50 className="text-foreground"
51 style={[
52 {
53 flex: 1,
54 minHeight: 0,
55 fontFamily,
56 ...bodyText,
57 paddingVertical: contentInsetVertical,
58 },
59 textStyle,
60 ]}
61 />
62 </TextInputWrapper>
63 );
64}
65
66export type {
67 ComposerEditorHandle,
68 ComposerEditorProps,
69 ComposerEditorSelection,
70 ComposerTextPaste,
71} from "./T3ComposerEditor.types";