react-native-earl-accessory-view 1.0.0
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/LICENSE +21 -0
- package/README.md +453 -0
- package/dist/AccessoryView.d.ts +33 -0
- package/dist/AccessoryView.d.ts.map +1 -0
- package/dist/AccessoryView.js +321 -0
- package/dist/AccessoryView.js.map +1 -0
- package/dist/ActionButton.d.ts +22 -0
- package/dist/ActionButton.d.ts.map +1 -0
- package/dist/ActionButton.js +81 -0
- package/dist/ActionButton.js.map +1 -0
- package/dist/CharacterCounter.d.ts +8 -0
- package/dist/CharacterCounter.d.ts.map +1 -0
- package/dist/CharacterCounter.js +78 -0
- package/dist/CharacterCounter.js.map +1 -0
- package/dist/DismissButton.d.ts +10 -0
- package/dist/DismissButton.d.ts.map +1 -0
- package/dist/DismissButton.js +73 -0
- package/dist/DismissButton.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.d.ts +173 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +184 -0
- package/dist/styles.js.map +1 -0
- package/dist/types.d.ts +229 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/useKeyboardAccessory.d.ts +18 -0
- package/dist/useKeyboardAccessory.d.ts.map +1 -0
- package/dist/useKeyboardAccessory.js +102 -0
- package/dist/useKeyboardAccessory.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ORDOVEZ, E,R
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
# react-native-earl-accessory-view
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/react-native-earl-accessory-view)
|
|
4
|
+
[](https://github.com/ordovez-er/react-native-earl-accessory-view/blob/main/LICENSE)
|
|
5
|
+
[]()
|
|
6
|
+
|
|
7
|
+
A **keyboard input preview bar** for React Native. When the keyboard covers your input field, this bar sits above the keyboard showing what the user is typing in real-time — so they never lose sight of their input.
|
|
8
|
+
|
|
9
|
+
Fully customizable with **action buttons**, smooth animations, and cross-platform support on **iOS**, **Android**, and **Web**.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## The Problem
|
|
14
|
+
|
|
15
|
+
On mobile, the soft keyboard frequently covers `TextInput` fields — especially inputs near the bottom of the screen. Users end up typing blind, unsure what they've entered.
|
|
16
|
+
|
|
17
|
+
## The Solution
|
|
18
|
+
|
|
19
|
+
`react-native-earl-accessory-view` adds a slim bar above the keyboard that **mirrors what the user is typing** in real-time. When the keyboard goes away, the bar animates out smoothly.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Live input preview** — shows the current value above the keyboard in real-time
|
|
26
|
+
- **Action buttons** — add send, attach, navigate, or any custom buttons with icons
|
|
27
|
+
- **Fully customizable** — colors, fonts, height, borders, shadows, padding — everything
|
|
28
|
+
- **Smooth animations** — fade + slide transitions synced with keyboard events
|
|
29
|
+
- **Text positioning** — place preview text on the left or right
|
|
30
|
+
- **Dismiss button** — auto-positions opposite to the text, fully styleable, or hide it
|
|
31
|
+
- **Field label** — optional label like "Email" or "Password" next to the preview
|
|
32
|
+
- **Character counter** — built-in with warning/error color thresholds
|
|
33
|
+
- **Cross-platform** — iOS `InputAccessoryView`, Android absolute positioning, Web fallback
|
|
34
|
+
- **Safe area aware** — respects bottom safe areas on notched devices
|
|
35
|
+
- **Custom children** — override the default layout with any React Native content
|
|
36
|
+
- **TypeScript first** — full type definitions with JSDoc
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm install react-native-earl-accessory-view
|
|
44
|
+
# or
|
|
45
|
+
yarn add react-native-earl-accessory-view
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
> **Peer dependencies:** `react >= 16.8.0` and `react-native >= 0.60.0`
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Quick Start
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import React, { useState } from "react";
|
|
56
|
+
import { TextInput, View } from "react-native";
|
|
57
|
+
import { AccessoryView } from "react-native-earl-accessory-view";
|
|
58
|
+
|
|
59
|
+
export default function App() {
|
|
60
|
+
const [text, setText] = useState("");
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<View style={{ flex: 1, justifyContent: "flex-end", padding: 20 }}>
|
|
64
|
+
<TextInput
|
|
65
|
+
value={text}
|
|
66
|
+
onChangeText={setText}
|
|
67
|
+
placeholder="Type something..."
|
|
68
|
+
style={{
|
|
69
|
+
borderWidth: 1,
|
|
70
|
+
borderColor: "#ccc",
|
|
71
|
+
padding: 12,
|
|
72
|
+
borderRadius: 8,
|
|
73
|
+
}}
|
|
74
|
+
/>
|
|
75
|
+
|
|
76
|
+
{/* This bar appears above the keyboard, previewing what you type */}
|
|
77
|
+
<AccessoryView value={text} onValueChange={setText} />
|
|
78
|
+
</View>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Usage Examples
|
|
86
|
+
|
|
87
|
+
### Basic Preview
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
const [text, setText] = useState("");
|
|
91
|
+
|
|
92
|
+
<TextInput value={text} onChangeText={setText} />
|
|
93
|
+
<AccessoryView value={text} onValueChange={setText} />
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Send Button
|
|
97
|
+
|
|
98
|
+
Replace the dismiss button with a send action:
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
<AccessoryView
|
|
102
|
+
value={text}
|
|
103
|
+
onValueChange={setText}
|
|
104
|
+
actionButtons={[
|
|
105
|
+
{
|
|
106
|
+
id: "send",
|
|
107
|
+
content: "Send",
|
|
108
|
+
onPress: () => {
|
|
109
|
+
console.log("Sending:", text);
|
|
110
|
+
setText("");
|
|
111
|
+
},
|
|
112
|
+
disabled: !text.trim(),
|
|
113
|
+
position: "right",
|
|
114
|
+
},
|
|
115
|
+
]}
|
|
116
|
+
/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Send with Custom Icon
|
|
120
|
+
|
|
121
|
+
Use any icon library (lucide-react-native, @expo/vector-icons, etc.):
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
import { Send } from "lucide-react-native";
|
|
125
|
+
|
|
126
|
+
<AccessoryView
|
|
127
|
+
value={text}
|
|
128
|
+
onValueChange={setText}
|
|
129
|
+
actionButtons={[
|
|
130
|
+
{
|
|
131
|
+
id: "send",
|
|
132
|
+
content: <Send size={20} color="#007AFF" />,
|
|
133
|
+
onPress: handleSend,
|
|
134
|
+
disabled: !text.trim(),
|
|
135
|
+
},
|
|
136
|
+
]}
|
|
137
|
+
/>;
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Switch Between Inputs (Prev / Next)
|
|
141
|
+
|
|
142
|
+
Navigate between form fields with any icon library:
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
import { ChevronLeft, ChevronRight } from "lucide-react-native";
|
|
146
|
+
|
|
147
|
+
<AccessoryView
|
|
148
|
+
value={currentValue}
|
|
149
|
+
onValueChange={setCurrentValue}
|
|
150
|
+
label={currentField === "email" ? "Email" : "Password"}
|
|
151
|
+
actionButtons={[
|
|
152
|
+
{
|
|
153
|
+
id: "prev",
|
|
154
|
+
content: <ChevronLeft size={20} color="#6366F1" />,
|
|
155
|
+
onPress: () => emailRef.current?.focus(),
|
|
156
|
+
disabled: currentField === "email",
|
|
157
|
+
position: "left",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: "next",
|
|
161
|
+
content: <ChevronRight size={20} color="#6366F1" />,
|
|
162
|
+
onPress: () => passwordRef.current?.focus(),
|
|
163
|
+
disabled: currentField === "password",
|
|
164
|
+
position: "right",
|
|
165
|
+
},
|
|
166
|
+
]}
|
|
167
|
+
showDismissButton={true}
|
|
168
|
+
/>;
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Multi-Action Bar (Attach + Camera + Send)
|
|
172
|
+
|
|
173
|
+
Combine multiple actions — `content` accepts **any ReactNode** and `onPress` accepts **any function**:
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import { Paperclip, Camera, Send } from "lucide-react-native";
|
|
177
|
+
|
|
178
|
+
<AccessoryView
|
|
179
|
+
value={text}
|
|
180
|
+
onValueChange={setText}
|
|
181
|
+
actionButtons={[
|
|
182
|
+
{
|
|
183
|
+
id: "attach",
|
|
184
|
+
content: <Paperclip size={20} color="#6B7280" />,
|
|
185
|
+
onPress: openFilePicker,
|
|
186
|
+
position: "left",
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: "camera",
|
|
190
|
+
content: <Camera size={20} color="#6B7280" />,
|
|
191
|
+
onPress: openCamera,
|
|
192
|
+
position: "left",
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
id: "send",
|
|
196
|
+
content: <Send size={20} color="#007AFF" />,
|
|
197
|
+
onPress: handleSend,
|
|
198
|
+
disabled: !text.trim(),
|
|
199
|
+
position: "right",
|
|
200
|
+
},
|
|
201
|
+
]}
|
|
202
|
+
/>;
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Right-Aligned Text
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
<AccessoryView
|
|
209
|
+
value={text}
|
|
210
|
+
onValueChange={setText}
|
|
211
|
+
textPosition="right"
|
|
212
|
+
placeholder="Waiting for input..."
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### No Dismiss Button
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
<AccessoryView value={text} onValueChange={setText} showDismissButton={false} />
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### With a Field Label
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
<AccessoryView value={text} onValueChange={setText} label="Email" />
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Character Counter
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
<AccessoryView
|
|
232
|
+
value={text}
|
|
233
|
+
onValueChange={setText}
|
|
234
|
+
charCount={text.length}
|
|
235
|
+
maxCharCount={280}
|
|
236
|
+
charCountWarningThreshold={0.8}
|
|
237
|
+
/>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Custom Dismiss Icon (any icon library)
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
import { X } from "lucide-react-native";
|
|
244
|
+
|
|
245
|
+
<AccessoryView
|
|
246
|
+
value={text}
|
|
247
|
+
onValueChange={setText}
|
|
248
|
+
dismissButtonContent={<X size={18} color="#666" />}
|
|
249
|
+
/>;
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Dark Theme
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
<AccessoryView
|
|
256
|
+
value={text}
|
|
257
|
+
onValueChange={setText}
|
|
258
|
+
backgroundColor="#1A1A2E"
|
|
259
|
+
valueStyle={{ color: "#FFFFFF" }}
|
|
260
|
+
placeholderStyle={{ color: "#555577" }}
|
|
261
|
+
dismissButtonTextStyle={{ color: "#888899" }}
|
|
262
|
+
borderTopColor="#2A2A44"
|
|
263
|
+
/>
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Custom Children (Full Control)
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
<AccessoryView backgroundColor="#FFFFFF" height={50}>
|
|
270
|
+
<View
|
|
271
|
+
style={{
|
|
272
|
+
flexDirection: "row",
|
|
273
|
+
alignItems: "center",
|
|
274
|
+
paddingHorizontal: 16,
|
|
275
|
+
flex: 1,
|
|
276
|
+
}}
|
|
277
|
+
>
|
|
278
|
+
<Text style={{ color: "#aaa", fontSize: 11, fontWeight: "700" }}>
|
|
279
|
+
PREVIEW
|
|
280
|
+
</Text>
|
|
281
|
+
<Text style={{ flex: 1, marginLeft: 8 }}>
|
|
282
|
+
{text || "Nothing yet..."}
|
|
283
|
+
</Text>
|
|
284
|
+
<Text style={{ color: "#bbb" }}>{text.length}</Text>
|
|
285
|
+
</View>
|
|
286
|
+
</AccessoryView>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### iOS InputAccessoryView Connection
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
import { ACCESSORY_VIEW_NATIVE_ID } from "react-native-earl-accessory-view";
|
|
293
|
+
|
|
294
|
+
<TextInput inputAccessoryViewID={ACCESSORY_VIEW_NATIVE_ID} />
|
|
295
|
+
<AccessoryView value={text} onValueChange={setText} />
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
## API Reference
|
|
301
|
+
|
|
302
|
+
### `<AccessoryView />` Props
|
|
303
|
+
|
|
304
|
+
#### Preview Content
|
|
305
|
+
|
|
306
|
+
| Prop | Type | Default | Description |
|
|
307
|
+
| ------------------ | ------------------- | --------------------- | --------------------------------------------- |
|
|
308
|
+
| `value` | `string` | — | Current input value to preview (primary prop) |
|
|
309
|
+
| `placeholder` | `string` | `'Type something...'` | Shown when value is empty |
|
|
310
|
+
| `valueStyle` | `TextStyle` | — | Style for the preview text |
|
|
311
|
+
| `placeholderStyle` | `TextStyle` | — | Style for the placeholder |
|
|
312
|
+
| `editable` | `boolean` | `true` | Allow editing/pasting in the preview bar |
|
|
313
|
+
| `onValueChange` | `(value) => void` | — | Called when preview value changes |
|
|
314
|
+
| `onPress` | `() => void` | — | Called when non-editable preview is tapped |
|
|
315
|
+
| `label` | `string` | — | Optional label (e.g. "Email") |
|
|
316
|
+
| `labelStyle` | `TextStyle` | — | Style for the label |
|
|
317
|
+
| `textPosition` | `'left' \| 'right'` | `'left'` | Preview text side |
|
|
318
|
+
| `textStyle` | `TextStyle` | — | Style for the text |
|
|
319
|
+
| `children` | `ReactNode` | — | Custom content (overrides default layout) |
|
|
320
|
+
|
|
321
|
+
#### Action Buttons
|
|
322
|
+
|
|
323
|
+
| Prop | Type | Default | Description |
|
|
324
|
+
| --------------- | ------------------------- | ------- | ------------------------------------------------------------------------ |
|
|
325
|
+
| `actionButtons` | `AccessoryActionButton[]` | — | Array of action buttons (send, switch input, etc.). See below for shape. |
|
|
326
|
+
|
|
327
|
+
**`AccessoryActionButton` shape:**
|
|
328
|
+
|
|
329
|
+
| Field | Type | Default | Description |
|
|
330
|
+
| -------------------- | --------------------- | --------- | ---------------------------------------------------------- |
|
|
331
|
+
| `id` | `string` | — | Unique key (required) |
|
|
332
|
+
| `onPress` | `() => void` | — | **Any** function — send, attach, navigate, etc. (required) |
|
|
333
|
+
| `content` | `ReactNode \| string` | — | **Any** icon, component, image, or text (required) |
|
|
334
|
+
| `position` | `'left' \| 'right'` | `'right'` | Where to place the button |
|
|
335
|
+
| `disabled` | `boolean` | `false` | Disable the button |
|
|
336
|
+
| `style` | `ViewStyle` | — | Container style override |
|
|
337
|
+
| `textStyle` | `TextStyle` | — | Text style (when `content` is a string) |
|
|
338
|
+
| `accessibilityLabel` | `string` | — | Accessibility label |
|
|
339
|
+
| `testID` | `string` | — | Test ID |
|
|
340
|
+
|
|
341
|
+
> **Note:** When `actionButtons` is provided, the dismiss button is automatically hidden unless `showDismissButton` is explicitly set to `true`.
|
|
342
|
+
|
|
343
|
+
#### Dismiss Button
|
|
344
|
+
|
|
345
|
+
| Prop | Type | Default | Description |
|
|
346
|
+
| ------------------------ | ----------------------------- | ------------------ | -------------------------------------------- |
|
|
347
|
+
| `showDismissButton` | `boolean` | `true` \* | Show/hide the close button |
|
|
348
|
+
| `dismissButtonPosition` | `'auto' \| 'left' \| 'right'` | `'auto'` | Button position (`auto` = opposite of text) |
|
|
349
|
+
| `onDismiss` | `() => void` | `Keyboard.dismiss` | Dismiss callback |
|
|
350
|
+
| `dismissButtonContent` | `ReactNode` | `✕` text | Custom button content (use any icon library) |
|
|
351
|
+
| `dismissButtonStyle` | `ViewStyle` | — | Button container style |
|
|
352
|
+
| `dismissButtonTextStyle` | `TextStyle` | — | Default ✕ text style |
|
|
353
|
+
|
|
354
|
+
\* Defaults to `false` when `actionButtons` is provided.
|
|
355
|
+
|
|
356
|
+
#### Character Counter
|
|
357
|
+
|
|
358
|
+
| Prop | Type | Default | Description |
|
|
359
|
+
| --------------------------- | ------------------------------- | ----------- | ----------------------- |
|
|
360
|
+
| `charCount` | `number` | — | Current count |
|
|
361
|
+
| `maxCharCount` | `number` | — | Max count |
|
|
362
|
+
| `charCountPosition` | `'left' \| 'right' \| 'center'` | `'right'` | Counter position |
|
|
363
|
+
| `charCountWarningThreshold` | `number` | `0.9` | Warning threshold (0–1) |
|
|
364
|
+
| `charCountWarningColor` | `string` | `'#FF9800'` | Warning color |
|
|
365
|
+
| `charCountErrorColor` | `string` | `'#F44336'` | Over-limit color |
|
|
366
|
+
|
|
367
|
+
#### Appearance
|
|
368
|
+
|
|
369
|
+
| Prop | Type | Default | Description |
|
|
370
|
+
| ----------------------- | ----------- | --------------- | ---------------- |
|
|
371
|
+
| `backgroundColor` | `string` | `'#FFFFFF'` | Background color |
|
|
372
|
+
| `height` | `number` | `44` | Bar height |
|
|
373
|
+
| `borderTopWidth` | `number` | `hairlineWidth` | Top border |
|
|
374
|
+
| `borderTopColor` | `string` | `'#E0E0E0'` | Border color |
|
|
375
|
+
| `elevation` | `number` | `4` | Shadow depth |
|
|
376
|
+
| `containerStyle` | `ViewStyle` | — | Outer style |
|
|
377
|
+
| `contentContainerStyle` | `ViewStyle` | — | Inner style |
|
|
378
|
+
|
|
379
|
+
#### Behavior & Animation
|
|
380
|
+
|
|
381
|
+
| Prop | Type | Default | Description |
|
|
382
|
+
| ------------------- | --------- | ------- | ----------------------------- |
|
|
383
|
+
| `animationEnabled` | `boolean` | `true` | Animate transitions |
|
|
384
|
+
| `animationDuration` | `number` | `250` | Duration (ms) |
|
|
385
|
+
| `alwaysVisible` | `boolean` | `false` | Keep visible without keyboard |
|
|
386
|
+
| `safeAreaEnabled` | `boolean` | `true` | Respect safe area (iOS) |
|
|
387
|
+
|
|
388
|
+
#### Callbacks
|
|
389
|
+
|
|
390
|
+
| Prop | Type | Description |
|
|
391
|
+
| ----------------- | ------------------ | ------------------ |
|
|
392
|
+
| `onKeyboardShow` | `(height) => void` | Keyboard appeared |
|
|
393
|
+
| `onKeyboardHide` | `() => void` | Keyboard dismissed |
|
|
394
|
+
| `onAccessoryShow` | `() => void` | Bar appeared |
|
|
395
|
+
| `onAccessoryHide` | `() => void` | Bar hidden |
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
### `<ActionButton />` Component
|
|
400
|
+
|
|
401
|
+
A standalone action button component you can also use independently:
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
import { ActionButton } from "react-native-earl-accessory-view";
|
|
405
|
+
|
|
406
|
+
<ActionButton
|
|
407
|
+
id="send"
|
|
408
|
+
content="Send"
|
|
409
|
+
onPress={handleSend}
|
|
410
|
+
disabled={!text.trim()}
|
|
411
|
+
/>;
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
### `useKeyboardAccessory(options?)` Hook
|
|
417
|
+
|
|
418
|
+
Use this hook directly for custom keyboard-aware UIs.
|
|
419
|
+
|
|
420
|
+
```tsx
|
|
421
|
+
const { keyboardVisible, keyboardHeight } = useKeyboardAccessory({
|
|
422
|
+
onKeyboardShow: (height) => console.log("Keyboard height:", height),
|
|
423
|
+
onKeyboardHide: () => console.log("Keyboard hidden"),
|
|
424
|
+
});
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
### Constants
|
|
430
|
+
|
|
431
|
+
| Constant | Usage |
|
|
432
|
+
| -------------------------- | ----------------------------------------------- |
|
|
433
|
+
| `ACCESSORY_VIEW_NATIVE_ID` | Pass to `TextInput.inputAccessoryViewID` on iOS |
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Showcase
|
|
438
|
+
|
|
439
|
+
A ready-to-use demo screen is included at [`example/showcase.tsx`](example/showcase.tsx). Drop it into your app to try every feature interactively — including send buttons, input switching, and multi-action bars.
|
|
440
|
+
|
|
441
|
+
> The showcase uses [lucide-react-native](https://lucide.dev/) for icons. Install it with:
|
|
442
|
+
>
|
|
443
|
+
> ```bash
|
|
444
|
+
> npm install lucide-react-native react-native-svg
|
|
445
|
+
> ```
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## License
|
|
450
|
+
|
|
451
|
+
MIT © [ORDOVEZ, E,R](https://github.com/ordovez-er)
|
|
452
|
+
|
|
453
|
+
**Author:** ORDOVEZ, E,R
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { AccessoryViewProps } from "./types";
|
|
3
|
+
declare const ACCESSORY_NATIVE_ID = "earl-accessory-view-native";
|
|
4
|
+
/**
|
|
5
|
+
* AccessoryView — a keyboard input preview bar for React Native.
|
|
6
|
+
*
|
|
7
|
+
* Shows a live preview of what the user is typing above the keyboard,
|
|
8
|
+
* so the input is always visible even when the text field is obscured.
|
|
9
|
+
* The preview is interactive — paste directly or edit the text right
|
|
10
|
+
* in the bar. Changes sync back via onValueChange.
|
|
11
|
+
*
|
|
12
|
+
* Works on iOS, Android, and Web.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const [text, setText] = useState('');
|
|
17
|
+
*
|
|
18
|
+
* <TextInput value={text} onChangeText={setText} />
|
|
19
|
+
* <AccessoryView value={text} onValueChange={setText} />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const AccessoryView: React.FC<AccessoryViewProps>;
|
|
23
|
+
/**
|
|
24
|
+
* The nativeID to use on iOS TextInput for connecting to this accessory view.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* import { ACCESSORY_VIEW_NATIVE_ID } from 'react-native-earl-accessory-view';
|
|
29
|
+
* <TextInput inputAccessoryViewID={ACCESSORY_VIEW_NATIVE_ID} />
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export { ACCESSORY_NATIVE_ID as ACCESSORY_VIEW_NATIVE_ID };
|
|
33
|
+
//# sourceMappingURL=AccessoryView.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccessoryView.d.ts","sourceRoot":"","sources":["../src/AccessoryView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AAaf,OAAO,EAAE,kBAAkB,EAAmC,MAAM,SAAS,CAAC;AAQ9E,QAAA,MAAM,mBAAmB,+BAA+B,CAAC;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CA8ZtD,CAAC;AAEF;;;;;;;;GAQG;AACH,OAAO,EAAE,mBAAmB,IAAI,wBAAwB,EAAE,CAAC"}
|