react-native-richify 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 +231 -0
- package/lib/commonjs/components/OverlayText.d.js +6 -0
- package/lib/commonjs/components/OverlayText.d.js.map +1 -0
- package/lib/commonjs/components/OverlayText.js +45 -0
- package/lib/commonjs/components/OverlayText.js.map +1 -0
- package/lib/commonjs/components/RichTextInput.d.js +6 -0
- package/lib/commonjs/components/RichTextInput.d.js.map +1 -0
- package/lib/commonjs/components/RichTextInput.js +160 -0
- package/lib/commonjs/components/RichTextInput.js.map +1 -0
- package/lib/commonjs/components/Toolbar.d.js +6 -0
- package/lib/commonjs/components/Toolbar.d.js.map +1 -0
- package/lib/commonjs/components/Toolbar.js +99 -0
- package/lib/commonjs/components/Toolbar.js.map +1 -0
- package/lib/commonjs/components/ToolbarButton.d.js +6 -0
- package/lib/commonjs/components/ToolbarButton.d.js.map +1 -0
- package/lib/commonjs/components/ToolbarButton.js +63 -0
- package/lib/commonjs/components/ToolbarButton.js.map +1 -0
- package/lib/commonjs/constants/defaultStyles.d.js +6 -0
- package/lib/commonjs/constants/defaultStyles.d.js.map +1 -0
- package/lib/commonjs/constants/defaultStyles.js +172 -0
- package/lib/commonjs/constants/defaultStyles.js.map +1 -0
- package/lib/commonjs/context/RichTextContext.d.js +6 -0
- package/lib/commonjs/context/RichTextContext.d.js.map +1 -0
- package/lib/commonjs/context/RichTextContext.js +61 -0
- package/lib/commonjs/context/RichTextContext.js.map +1 -0
- package/lib/commonjs/hooks/useFormatting.d.js +6 -0
- package/lib/commonjs/hooks/useFormatting.d.js.map +1 -0
- package/lib/commonjs/hooks/useFormatting.js +82 -0
- package/lib/commonjs/hooks/useFormatting.js.map +1 -0
- package/lib/commonjs/hooks/useRichText.d.js +6 -0
- package/lib/commonjs/hooks/useRichText.d.js.map +1 -0
- package/lib/commonjs/hooks/useRichText.js +136 -0
- package/lib/commonjs/hooks/useRichText.js.map +1 -0
- package/lib/commonjs/hooks/useSelection.d.js +6 -0
- package/lib/commonjs/hooks/useSelection.d.js.map +1 -0
- package/lib/commonjs/hooks/useSelection.js +39 -0
- package/lib/commonjs/hooks/useSelection.js.map +1 -0
- package/lib/commonjs/index.d.js +186 -0
- package/lib/commonjs/index.d.js.map +1 -0
- package/lib/commonjs/index.js +186 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/types/index.d.js +6 -0
- package/lib/commonjs/types/index.d.js.map +1 -0
- package/lib/commonjs/types/index.js +6 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/utils/formatter.d.js +13 -0
- package/lib/commonjs/utils/formatter.d.js.map +1 -0
- package/lib/commonjs/utils/formatter.js +229 -0
- package/lib/commonjs/utils/formatter.js.map +1 -0
- package/lib/commonjs/utils/parser.d.js +6 -0
- package/lib/commonjs/utils/parser.d.js.map +1 -0
- package/lib/commonjs/utils/parser.js +221 -0
- package/lib/commonjs/utils/parser.js.map +1 -0
- package/lib/commonjs/utils/styleMapper.d.js +6 -0
- package/lib/commonjs/utils/styleMapper.d.js.map +1 -0
- package/lib/commonjs/utils/styleMapper.js +87 -0
- package/lib/commonjs/utils/styleMapper.js.map +1 -0
- package/lib/module/components/OverlayText.d.js +4 -0
- package/lib/module/components/OverlayText.d.js.map +1 -0
- package/lib/module/components/OverlayText.js +41 -0
- package/lib/module/components/OverlayText.js.map +1 -0
- package/lib/module/components/RichTextInput.d.js +4 -0
- package/lib/module/components/RichTextInput.d.js.map +1 -0
- package/lib/module/components/RichTextInput.js +155 -0
- package/lib/module/components/RichTextInput.js.map +1 -0
- package/lib/module/components/Toolbar.d.js +4 -0
- package/lib/module/components/Toolbar.d.js.map +1 -0
- package/lib/module/components/Toolbar.js +95 -0
- package/lib/module/components/Toolbar.js.map +1 -0
- package/lib/module/components/ToolbarButton.d.js +4 -0
- package/lib/module/components/ToolbarButton.d.js.map +1 -0
- package/lib/module/components/ToolbarButton.js +59 -0
- package/lib/module/components/ToolbarButton.js.map +1 -0
- package/lib/module/constants/defaultStyles.d.js +4 -0
- package/lib/module/constants/defaultStyles.d.js.map +1 -0
- package/lib/module/constants/defaultStyles.js +168 -0
- package/lib/module/constants/defaultStyles.js.map +1 -0
- package/lib/module/context/RichTextContext.d.js +4 -0
- package/lib/module/context/RichTextContext.d.js.map +1 -0
- package/lib/module/context/RichTextContext.js +55 -0
- package/lib/module/context/RichTextContext.js.map +1 -0
- package/lib/module/hooks/useFormatting.d.js +11 -0
- package/lib/module/hooks/useFormatting.d.js.map +1 -0
- package/lib/module/hooks/useFormatting.js +78 -0
- package/lib/module/hooks/useFormatting.js.map +1 -0
- package/lib/module/hooks/useRichText.d.js +4 -0
- package/lib/module/hooks/useRichText.d.js.map +1 -0
- package/lib/module/hooks/useRichText.js +132 -0
- package/lib/module/hooks/useRichText.js.map +1 -0
- package/lib/module/hooks/useSelection.d.js +4 -0
- package/lib/module/hooks/useSelection.d.js.map +1 -0
- package/lib/module/hooks/useSelection.js +35 -0
- package/lib/module/hooks/useSelection.js.map +1 -0
- package/lib/module/index.d.js +15 -0
- package/lib/module/index.d.js.map +1 -0
- package/lib/module/index.js +25 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types/index.d.js +4 -0
- package/lib/module/types/index.d.js.map +1 -0
- package/lib/module/types/index.js +4 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/utils/formatter.d.js +30 -0
- package/lib/module/utils/formatter.d.js.map +1 -0
- package/lib/module/utils/formatter.js +217 -0
- package/lib/module/utils/formatter.js.map +1 -0
- package/lib/module/utils/parser.d.js +4 -0
- package/lib/module/utils/parser.d.js.map +1 -0
- package/lib/module/utils/parser.js +211 -0
- package/lib/module/utils/parser.js.map +1 -0
- package/lib/module/utils/styleMapper.d.js +4 -0
- package/lib/module/utils/styleMapper.d.js.map +1 -0
- package/lib/module/utils/styleMapper.js +82 -0
- package/lib/module/utils/styleMapper.js.map +1 -0
- package/lib/typescript/src/components/OverlayText.d.ts +11 -0
- package/lib/typescript/src/components/OverlayText.d.ts.map +1 -0
- package/lib/typescript/src/components/RichTextInput.d.ts +21 -0
- package/lib/typescript/src/components/RichTextInput.d.ts.map +1 -0
- package/lib/typescript/src/components/Toolbar.d.ts +13 -0
- package/lib/typescript/src/components/Toolbar.d.ts.map +1 -0
- package/lib/typescript/src/components/ToolbarButton.d.ts +8 -0
- package/lib/typescript/src/components/ToolbarButton.d.ts.map +1 -0
- package/lib/typescript/src/constants/defaultStyles.d.ts +46 -0
- package/lib/typescript/src/constants/defaultStyles.d.ts.map +1 -0
- package/lib/typescript/src/context/RichTextContext.d.ts +31 -0
- package/lib/typescript/src/context/RichTextContext.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useFormatting.d.ts +26 -0
- package/lib/typescript/src/hooks/useFormatting.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useRichText.d.ts +17 -0
- package/lib/typescript/src/hooks/useRichText.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useSelection.d.ts +14 -0
- package/lib/typescript/src/hooks/useSelection.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +16 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +245 -0
- package/lib/typescript/src/types/index.d.ts.map +1 -0
- package/lib/typescript/src/utils/formatter.d.ts +29 -0
- package/lib/typescript/src/utils/formatter.d.ts.map +1 -0
- package/lib/typescript/src/utils/parser.d.ts +46 -0
- package/lib/typescript/src/utils/parser.d.ts.map +1 -0
- package/lib/typescript/src/utils/styleMapper.d.ts +16 -0
- package/lib/typescript/src/utils/styleMapper.d.ts.map +1 -0
- package/package.json +83 -0
- package/src/components/OverlayText.d.ts +10 -0
- package/src/components/OverlayText.tsx +46 -0
- package/src/components/RichTextInput.d.ts +20 -0
- package/src/components/RichTextInput.tsx +174 -0
- package/src/components/Toolbar.d.ts +12 -0
- package/src/components/Toolbar.tsx +100 -0
- package/src/components/ToolbarButton.d.ts +7 -0
- package/src/components/ToolbarButton.tsx +65 -0
- package/src/constants/defaultStyles.d.ts +45 -0
- package/src/constants/defaultStyles.ts +144 -0
- package/src/context/RichTextContext.d.ts +30 -0
- package/src/context/RichTextContext.tsx +63 -0
- package/src/hooks/useFormatting.d.ts +25 -0
- package/src/hooks/useFormatting.ts +135 -0
- package/src/hooks/useRichText.d.ts +16 -0
- package/src/hooks/useRichText.ts +171 -0
- package/src/hooks/useSelection.d.ts +13 -0
- package/src/hooks/useSelection.ts +40 -0
- package/src/index.d.ts +15 -0
- package/src/index.ts +68 -0
- package/src/types/index.d.ts +244 -0
- package/src/types/index.ts +295 -0
- package/src/utils/formatter.d.ts +28 -0
- package/src/utils/formatter.ts +276 -0
- package/src/utils/parser.d.ts +45 -0
- package/src/utils/parser.ts +252 -0
- package/src/utils/styleMapper.d.ts +15 -0
- package/src/utils/styleMapper.ts +92 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 react-native-richify contributors
|
|
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,231 @@
|
|
|
1
|
+
# react-native-richify
|
|
2
|
+
|
|
3
|
+
A production-grade, fully customizable React Native Rich Text Input using the **Overlay Technique** — no WebView required.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/react-native-richify)
|
|
6
|
+
[](https://github.com/soumya-99/react-native-richify/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🚀 **No WebView** — Pure React Native components (TextInput + Text overlay)
|
|
11
|
+
- 📝 **Rich Formatting** — Bold, italic, underline, strikethrough, code
|
|
12
|
+
- 🎨 **Text & Background Colors** — Full color customization
|
|
13
|
+
- 📐 **Font Sizes & Headings** — H1, H2, H3 presets + custom sizes
|
|
14
|
+
- 🔧 **Fully Customizable Toolbar** — Default toolbar + render props for full control
|
|
15
|
+
- 🎭 **Theming** — Complete theme system with plug-and-play defaults
|
|
16
|
+
- 💾 **Serialization** — Export/import as JSON
|
|
17
|
+
- 📦 **TypeScript First** — Full type definitions out of the box
|
|
18
|
+
- 🪝 **Headless Hook** — `useRichText` for building custom UIs
|
|
19
|
+
- 🌐 **Context API** — `RichTextProvider` for nested component access
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install react-native-richify
|
|
25
|
+
# or
|
|
26
|
+
yarn add react-native-richify
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
No native dependencies required. Works with Expo and bare React Native.
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import React from 'react';
|
|
35
|
+
import { View } from 'react-native';
|
|
36
|
+
import { RichTextInput } from 'react-native-richify';
|
|
37
|
+
|
|
38
|
+
export default function App() {
|
|
39
|
+
return (
|
|
40
|
+
<View style={{ flex: 1, padding: 16 }}>
|
|
41
|
+
<RichTextInput
|
|
42
|
+
placeholder="Start typing..."
|
|
43
|
+
showToolbar
|
|
44
|
+
onChangeText={(text) => console.log('Plain text:', text)}
|
|
45
|
+
onChangeSegments={(segments) => console.log('Segments:', segments)}
|
|
46
|
+
/>
|
|
47
|
+
</View>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
That's it! You get a fully functional rich text editor with default styling.
|
|
53
|
+
|
|
54
|
+
## API Reference
|
|
55
|
+
|
|
56
|
+
### `<RichTextInput />`
|
|
57
|
+
|
|
58
|
+
The main component. Drop it in and it works.
|
|
59
|
+
|
|
60
|
+
| Prop | Type | Default | Description |
|
|
61
|
+
|------|------|---------|-------------|
|
|
62
|
+
| `initialSegments` | `StyledSegment[]` | `[]` | Initial content |
|
|
63
|
+
| `onChangeSegments` | `(segments: StyledSegment[]) => void` | — | Called when content changes |
|
|
64
|
+
| `onChangeText` | `(text: string) => void` | — | Called with plain text |
|
|
65
|
+
| `placeholder` | `string` | `"Start typing..."` | Placeholder text |
|
|
66
|
+
| `editable` | `boolean` | `true` | Whether input is editable |
|
|
67
|
+
| `maxLength` | `number` | — | Max character length |
|
|
68
|
+
| `showToolbar` | `boolean` | `true` | Show formatting toolbar |
|
|
69
|
+
| `toolbarPosition` | `'top' \| 'bottom'` | `'top'` | Toolbar position |
|
|
70
|
+
| `toolbarItems` | `ToolbarItem[]` | Default items | Custom toolbar items |
|
|
71
|
+
| `theme` | `RichTextTheme` | Default theme | Theme overrides |
|
|
72
|
+
| `multiline` | `boolean` | `true` | Enable multiline |
|
|
73
|
+
| `minHeight` | `number` | `120` | Minimum editor height |
|
|
74
|
+
| `maxHeight` | `number` | — | Maximum editor height |
|
|
75
|
+
| `autoFocus` | `boolean` | `false` | Auto-focus on mount |
|
|
76
|
+
| `renderToolbar` | `(props) => ReactElement` | — | Custom toolbar renderer |
|
|
77
|
+
| `onReady` | `(actions: RichTextActions) => void` | — | Called with action methods |
|
|
78
|
+
|
|
79
|
+
### `useRichText(options?)`
|
|
80
|
+
|
|
81
|
+
Headless hook for building custom UIs.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { useRichText } from 'react-native-richify';
|
|
85
|
+
|
|
86
|
+
function MyEditor() {
|
|
87
|
+
const { state, actions } = useRichText({
|
|
88
|
+
onChangeText: (text) => console.log(text),
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
<Button title="Bold" onPress={() => actions.toggleFormat('bold')} />
|
|
94
|
+
<TextInput
|
|
95
|
+
value={actions.getPlainText()}
|
|
96
|
+
onChangeText={actions.handleTextChange}
|
|
97
|
+
onSelectionChange={(e) =>
|
|
98
|
+
actions.handleSelectionChange(e.nativeEvent.selection)
|
|
99
|
+
}
|
|
100
|
+
/>
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `<RichTextProvider>` & `useRichTextContext()`
|
|
107
|
+
|
|
108
|
+
Share state across the component tree:
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
import { RichTextProvider, useRichTextContext } from 'react-native-richify';
|
|
112
|
+
|
|
113
|
+
function CustomToolbar() {
|
|
114
|
+
const { state, actions } = useRichTextContext();
|
|
115
|
+
return <Button title="B" onPress={() => actions.toggleFormat('bold')} />;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function App() {
|
|
119
|
+
return (
|
|
120
|
+
<RichTextProvider onChangeText={console.log}>
|
|
121
|
+
<CustomToolbar />
|
|
122
|
+
<RichTextInput showToolbar={false} />
|
|
123
|
+
</RichTextProvider>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Actions
|
|
129
|
+
|
|
130
|
+
| Method | Description |
|
|
131
|
+
|--------|-------------|
|
|
132
|
+
| `toggleFormat(format)` | Toggle bold/italic/underline/strikethrough/code |
|
|
133
|
+
| `setColor(color)` | Set text color |
|
|
134
|
+
| `setBackgroundColor(color)` | Set highlight color |
|
|
135
|
+
| `setFontSize(size)` | Set font size |
|
|
136
|
+
| `setHeading(level)` | Set heading (h1/h2/h3/none) |
|
|
137
|
+
| `handleTextChange(text)` | Process text input changes |
|
|
138
|
+
| `handleSelectionChange(sel)` | Process selection changes |
|
|
139
|
+
| `getPlainText()` | Get plain text content |
|
|
140
|
+
| `exportJSON()` | Export segments as JSON |
|
|
141
|
+
| `importJSON(segments)` | Import segments from JSON |
|
|
142
|
+
| `clear()` | Clear all content |
|
|
143
|
+
|
|
144
|
+
## Theming
|
|
145
|
+
|
|
146
|
+
Customize every aspect of the editor:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<RichTextInput
|
|
150
|
+
theme={{
|
|
151
|
+
colors: {
|
|
152
|
+
primary: '#8B5CF6',
|
|
153
|
+
background: '#1F2937',
|
|
154
|
+
text: '#F9FAFB',
|
|
155
|
+
placeholder: '#6B7280',
|
|
156
|
+
toolbarBackground: '#374151',
|
|
157
|
+
toolbarBorder: '#4B5563',
|
|
158
|
+
cursor: '#8B5CF6',
|
|
159
|
+
},
|
|
160
|
+
containerStyle: {
|
|
161
|
+
borderRadius: 16,
|
|
162
|
+
borderWidth: 2,
|
|
163
|
+
borderColor: '#4B5563',
|
|
164
|
+
},
|
|
165
|
+
toolbarButtonActiveStyle: {
|
|
166
|
+
backgroundColor: '#4C1D95',
|
|
167
|
+
},
|
|
168
|
+
}}
|
|
169
|
+
/>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Custom Toolbar
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
<RichTextInput
|
|
176
|
+
toolbarItems={[
|
|
177
|
+
{ id: 'bold', label: 'B', format: 'bold' },
|
|
178
|
+
{ id: 'italic', label: 'I', format: 'italic' },
|
|
179
|
+
{
|
|
180
|
+
id: 'custom',
|
|
181
|
+
label: '🎨',
|
|
182
|
+
onPress: () => showColorPicker(),
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: 'render',
|
|
186
|
+
label: 'Custom',
|
|
187
|
+
renderButton: ({ active, onPress }) => (
|
|
188
|
+
<MyCustomButton active={active} onPress={onPress} />
|
|
189
|
+
),
|
|
190
|
+
},
|
|
191
|
+
]}
|
|
192
|
+
/>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Data Model
|
|
196
|
+
|
|
197
|
+
Content is stored as an array of `StyledSegment` objects:
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
interface StyledSegment {
|
|
201
|
+
text: string;
|
|
202
|
+
styles: {
|
|
203
|
+
bold?: boolean;
|
|
204
|
+
italic?: boolean;
|
|
205
|
+
underline?: boolean;
|
|
206
|
+
strikethrough?: boolean;
|
|
207
|
+
code?: boolean;
|
|
208
|
+
color?: string;
|
|
209
|
+
backgroundColor?: string;
|
|
210
|
+
fontSize?: number;
|
|
211
|
+
heading?: 'h1' | 'h2' | 'h3' | 'none';
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## How It Works
|
|
217
|
+
|
|
218
|
+
The **Overlay Technique** layers two components:
|
|
219
|
+
|
|
220
|
+
1. **Bottom**: A `<Text>` component renders the styled/formatted text
|
|
221
|
+
2. **Top**: A transparent `<TextInput>` captures user input and selection
|
|
222
|
+
|
|
223
|
+
Both layers use identical font metrics so text aligns perfectly. The user sees the formatted text from the bottom layer while typing into the invisible top layer.
|
|
224
|
+
|
|
225
|
+
## Contributing
|
|
226
|
+
|
|
227
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT © react-native-richify contributors
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["components/OverlayText.d.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.OverlayText = void 0;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _styleMapper = require("@/utils/styleMapper");
|
|
10
|
+
var _defaultStyles = require("@/constants/defaultStyles");
|
|
11
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
/**
|
|
14
|
+
* OverlayText renders the styled text segments as a `<Text>` component tree.
|
|
15
|
+
*
|
|
16
|
+
* This component is positioned behind the transparent TextInput to create
|
|
17
|
+
* the overlay effect — the user types into the TextInput while seeing
|
|
18
|
+
* the formatted rendering from this component.
|
|
19
|
+
*/
|
|
20
|
+
const OverlayText = exports.OverlayText = /*#__PURE__*/_react.default.memo(({
|
|
21
|
+
segments,
|
|
22
|
+
baseTextStyle,
|
|
23
|
+
theme
|
|
24
|
+
}) => {
|
|
25
|
+
const resolvedTheme = theme ?? _defaultStyles.DEFAULT_THEME;
|
|
26
|
+
const overlayStyle = resolvedTheme.overlayContainerStyle ?? _defaultStyles.DEFAULT_THEME.overlayContainerStyle;
|
|
27
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
28
|
+
style: overlayStyle,
|
|
29
|
+
pointerEvents: "none",
|
|
30
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
31
|
+
children: segments.map((segment, index) => {
|
|
32
|
+
if (segment.text.length === 0 && segments.length > 1) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const textStyle = (0, _styleMapper.segmentToTextStyle)(segment, resolvedTheme);
|
|
36
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
37
|
+
style: [baseTextStyle, textStyle],
|
|
38
|
+
children: segment.text
|
|
39
|
+
}, `${index}-${segment.text.slice(0, 8)}`);
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
OverlayText.displayName = 'OverlayText';
|
|
45
|
+
//# sourceMappingURL=OverlayText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireDefault","require","_reactNative","_styleMapper","_defaultStyles","_jsxRuntime","e","__esModule","default","OverlayText","exports","React","memo","segments","baseTextStyle","theme","resolvedTheme","DEFAULT_THEME","overlayStyle","overlayContainerStyle","jsx","View","style","pointerEvents","children","Text","map","segment","index","text","length","textStyle","segmentToTextStyle","slice","displayName"],"sourceRoot":"..\\..\\..\\src","sources":["components/OverlayText.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,YAAA,GAAAD,OAAA;AAEA,IAAAE,YAAA,GAAAF,OAAA;AACA,IAAAG,cAAA,GAAAH,OAAA;AAA0D,IAAAI,WAAA,GAAAJ,OAAA;AAAA,SAAAD,uBAAAM,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE1D;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMG,WAAuC,GAAAC,OAAA,CAAAD,WAAA,gBAAGE,cAAK,CAACC,IAAI,CAC/D,CAAC;EAAEC,QAAQ;EAAEC,aAAa;EAAEC;AAAM,CAAC,KAAK;EACtC,MAAMC,aAAa,GAAGD,KAAK,IAAIE,4BAAa;EAC5C,MAAMC,YAAY,GAChBF,aAAa,CAACG,qBAAqB,IACnCF,4BAAa,CAACE,qBAAqB;EAErC,oBACE,IAAAd,WAAA,CAAAe,GAAA,EAAClB,YAAA,CAAAmB,IAAI;IAACC,KAAK,EAAEJ,YAAa;IAACK,aAAa,EAAC,MAAM;IAAAC,QAAA,eAC7C,IAAAnB,WAAA,CAAAe,GAAA,EAAClB,YAAA,CAAAuB,IAAI;MAAAD,QAAA,EACFX,QAAQ,CAACa,GAAG,CAAC,CAACC,OAAO,EAAEC,KAAK,KAAK;QAChC,IAAID,OAAO,CAACE,IAAI,CAACC,MAAM,KAAK,CAAC,IAAIjB,QAAQ,CAACiB,MAAM,GAAG,CAAC,EAAE;UACpD,OAAO,IAAI;QACb;QAEA,MAAMC,SAAS,GAAG,IAAAC,+BAAkB,EAACL,OAAO,EAAEX,aAAa,CAAC;QAE5D,oBACE,IAAAX,WAAA,CAAAe,GAAA,EAAClB,YAAA,CAAAuB,IAAI;UAEHH,KAAK,EAAE,CAACR,aAAa,EAAEiB,SAAS,CAAE;UAAAP,QAAA,EAEjCG,OAAO,CAACE;QAAI,GAHR,GAAGD,KAAK,IAAID,OAAO,CAACE,IAAI,CAACI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAIrC,CAAC;MAEX,CAAC;IAAC,CACE;EAAC,CACH,CAAC;AAEX,CACF,CAAC;AAEDxB,WAAW,CAACyB,WAAW,GAAG,aAAa","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["components/RichTextInput.d.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.RichTextInput = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _defaultStyles = require("@/constants/defaultStyles");
|
|
10
|
+
var _parser = require("@/utils/parser");
|
|
11
|
+
var _useRichText = require("@/hooks/useRichText");
|
|
12
|
+
var _OverlayText = require("@/components/OverlayText");
|
|
13
|
+
var _Toolbar = require("@/components/Toolbar");
|
|
14
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
16
|
+
/**
|
|
17
|
+
* RichTextInput — The main rich text editor component.
|
|
18
|
+
*
|
|
19
|
+
* Uses the Overlay Technique:
|
|
20
|
+
* - A transparent `TextInput` on top captures user input and selection
|
|
21
|
+
* - A styled `<Text>` layer behind it renders the formatted content
|
|
22
|
+
* - Both share identical font metrics for pixel-perfect alignment
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <RichTextInput
|
|
27
|
+
* placeholder="Start typing..."
|
|
28
|
+
* showToolbar
|
|
29
|
+
* onChangeSegments={(segments) => console.log(segments)}
|
|
30
|
+
* />
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
const RichTextInput = ({
|
|
34
|
+
initialSegments,
|
|
35
|
+
onChangeSegments,
|
|
36
|
+
onChangeText,
|
|
37
|
+
placeholder = 'Start typing...',
|
|
38
|
+
editable = true,
|
|
39
|
+
maxLength,
|
|
40
|
+
showToolbar = true,
|
|
41
|
+
toolbarPosition = 'top',
|
|
42
|
+
toolbarItems,
|
|
43
|
+
theme,
|
|
44
|
+
multiline = true,
|
|
45
|
+
minHeight = 120,
|
|
46
|
+
maxHeight,
|
|
47
|
+
autoFocus = false,
|
|
48
|
+
textInputProps,
|
|
49
|
+
renderToolbar,
|
|
50
|
+
onReady
|
|
51
|
+
}) => {
|
|
52
|
+
const resolvedTheme = theme ?? _defaultStyles.DEFAULT_THEME;
|
|
53
|
+
const {
|
|
54
|
+
state,
|
|
55
|
+
actions
|
|
56
|
+
} = (0, _useRichText.useRichText)({
|
|
57
|
+
initialSegments,
|
|
58
|
+
onChangeSegments,
|
|
59
|
+
onChangeText
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Expose actions via onReady callback
|
|
63
|
+
(0, _react.useEffect)(() => {
|
|
64
|
+
onReady?.(actions);
|
|
65
|
+
}, [onReady, actions]);
|
|
66
|
+
|
|
67
|
+
// Build plain text for the TextInput value
|
|
68
|
+
const plainText = (0, _parser.segmentsToPlainText)(state.segments);
|
|
69
|
+
|
|
70
|
+
// Handle selection change from TextInput
|
|
71
|
+
const onSelectionChange = (0, _react.useCallback)(e => {
|
|
72
|
+
const {
|
|
73
|
+
start,
|
|
74
|
+
end
|
|
75
|
+
} = e.nativeEvent.selection;
|
|
76
|
+
actions.handleSelectionChange({
|
|
77
|
+
start,
|
|
78
|
+
end
|
|
79
|
+
});
|
|
80
|
+
}, [actions]);
|
|
81
|
+
|
|
82
|
+
// Container style
|
|
83
|
+
const containerStyle = [resolvedTheme.containerStyle ?? _defaultStyles.DEFAULT_THEME.containerStyle];
|
|
84
|
+
|
|
85
|
+
// Input area style
|
|
86
|
+
const inputAreaStyle = [styles.inputArea, {
|
|
87
|
+
minHeight
|
|
88
|
+
}, maxHeight ? {
|
|
89
|
+
maxHeight
|
|
90
|
+
} : undefined];
|
|
91
|
+
|
|
92
|
+
// Input style
|
|
93
|
+
const inputStyle = [styles.textInput, resolvedTheme.inputStyle ?? _defaultStyles.DEFAULT_THEME.inputStyle];
|
|
94
|
+
|
|
95
|
+
// Toolbar component
|
|
96
|
+
const toolbarComponent = showToolbar ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbar.Toolbar, {
|
|
97
|
+
actions: actions,
|
|
98
|
+
state: state,
|
|
99
|
+
items: toolbarItems,
|
|
100
|
+
theme: resolvedTheme,
|
|
101
|
+
renderToolbar: renderToolbar
|
|
102
|
+
}) : null;
|
|
103
|
+
|
|
104
|
+
// Toolbar border
|
|
105
|
+
const toolbarBorderStyle = toolbarPosition === 'top' ? {
|
|
106
|
+
borderBottomWidth: 1,
|
|
107
|
+
borderBottomColor: resolvedTheme.colors?.toolbarBorder ?? _defaultStyles.DEFAULT_THEME.colors?.toolbarBorder
|
|
108
|
+
} : {
|
|
109
|
+
borderTopWidth: 1,
|
|
110
|
+
borderTopColor: resolvedTheme.colors?.toolbarBorder ?? _defaultStyles.DEFAULT_THEME.colors?.toolbarBorder
|
|
111
|
+
};
|
|
112
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
113
|
+
style: containerStyle,
|
|
114
|
+
children: [toolbarPosition === 'top' && toolbarComponent && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
115
|
+
style: toolbarBorderStyle,
|
|
116
|
+
children: toolbarComponent
|
|
117
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
118
|
+
style: inputAreaStyle,
|
|
119
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_OverlayText.OverlayText, {
|
|
120
|
+
segments: state.segments,
|
|
121
|
+
baseTextStyle: resolvedTheme.baseTextStyle,
|
|
122
|
+
theme: resolvedTheme
|
|
123
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
|
|
124
|
+
...textInputProps,
|
|
125
|
+
style: inputStyle,
|
|
126
|
+
value: plainText,
|
|
127
|
+
onChangeText: actions.handleTextChange,
|
|
128
|
+
onSelectionChange: onSelectionChange,
|
|
129
|
+
multiline: multiline,
|
|
130
|
+
placeholder: placeholder,
|
|
131
|
+
placeholderTextColor: resolvedTheme.colors?.placeholder ?? _defaultStyles.DEFAULT_THEME.colors?.placeholder,
|
|
132
|
+
editable: editable,
|
|
133
|
+
maxLength: maxLength,
|
|
134
|
+
autoFocus: autoFocus,
|
|
135
|
+
selectionColor: resolvedTheme.colors?.cursor ?? _defaultStyles.DEFAULT_THEME.colors?.cursor,
|
|
136
|
+
textAlignVertical: "top",
|
|
137
|
+
scrollEnabled: true
|
|
138
|
+
})]
|
|
139
|
+
}), toolbarPosition === 'bottom' && toolbarComponent && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
140
|
+
style: toolbarBorderStyle,
|
|
141
|
+
children: toolbarComponent
|
|
142
|
+
})]
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
exports.RichTextInput = RichTextInput;
|
|
146
|
+
RichTextInput.displayName = 'RichTextInput';
|
|
147
|
+
const styles = _reactNative.StyleSheet.create({
|
|
148
|
+
inputArea: {
|
|
149
|
+
position: 'relative'
|
|
150
|
+
},
|
|
151
|
+
textInput: {
|
|
152
|
+
// The TextInput must be transparent so the overlay text shows through.
|
|
153
|
+
// Only the caret/cursor and selection highlight are visible.
|
|
154
|
+
color: 'transparent',
|
|
155
|
+
// Ensure it matches the overlay text positioning exactly.
|
|
156
|
+
position: 'relative',
|
|
157
|
+
zIndex: 1
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
//# sourceMappingURL=RichTextInput.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_defaultStyles","_parser","_useRichText","_OverlayText","_Toolbar","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","RichTextInput","initialSegments","onChangeSegments","onChangeText","placeholder","editable","maxLength","showToolbar","toolbarPosition","toolbarItems","theme","multiline","minHeight","maxHeight","autoFocus","textInputProps","renderToolbar","onReady","resolvedTheme","DEFAULT_THEME","state","actions","useRichText","useEffect","plainText","segmentsToPlainText","segments","onSelectionChange","useCallback","start","end","nativeEvent","selection","handleSelectionChange","containerStyle","inputAreaStyle","styles","inputArea","undefined","inputStyle","textInput","toolbarComponent","jsx","Toolbar","items","toolbarBorderStyle","borderBottomWidth","borderBottomColor","colors","toolbarBorder","borderTopWidth","borderTopColor","jsxs","View","style","children","OverlayText","baseTextStyle","TextInput","value","handleTextChange","placeholderTextColor","selectionColor","cursor","textAlignVertical","scrollEnabled","exports","displayName","StyleSheet","create","position","color","zIndex"],"sourceRoot":"..\\..\\..\\src","sources":["components/RichTextInput.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["components/Toolbar.d.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Toolbar = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
var _defaultStyles = require("@/constants/defaultStyles");
|
|
10
|
+
var _ToolbarButton = require("@/components/ToolbarButton");
|
|
11
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
13
|
+
/**
|
|
14
|
+
* Formatting toolbar for the rich text editor.
|
|
15
|
+
*
|
|
16
|
+
* Supports:
|
|
17
|
+
* - Default toolbar items (bold, italic, underline, etc.)
|
|
18
|
+
* - Custom toolbar items via the `items` prop
|
|
19
|
+
* - Fully custom rendering via `renderToolbar`
|
|
20
|
+
* - Horizontal scrolling for overflow
|
|
21
|
+
*/
|
|
22
|
+
const Toolbar = exports.Toolbar = /*#__PURE__*/_react.default.memo(({
|
|
23
|
+
actions,
|
|
24
|
+
state,
|
|
25
|
+
items,
|
|
26
|
+
theme,
|
|
27
|
+
visible = true,
|
|
28
|
+
renderToolbar
|
|
29
|
+
}) => {
|
|
30
|
+
const resolvedTheme = theme ?? _defaultStyles.DEFAULT_THEME;
|
|
31
|
+
const toolbarItems = items ?? _defaultStyles.DEFAULT_TOOLBAR_ITEMS;
|
|
32
|
+
|
|
33
|
+
// Compute active state for each item
|
|
34
|
+
const enrichedItems = (0, _react.useMemo)(() => {
|
|
35
|
+
return toolbarItems.map(item => {
|
|
36
|
+
let isActive = false;
|
|
37
|
+
if (item.format) {
|
|
38
|
+
// Check if the format is currently active
|
|
39
|
+
const {
|
|
40
|
+
activeStyles
|
|
41
|
+
} = state;
|
|
42
|
+
isActive = !!activeStyles[item.format];
|
|
43
|
+
}
|
|
44
|
+
if (item.heading) {
|
|
45
|
+
isActive = state.activeStyles.heading === item.heading;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
...item,
|
|
49
|
+
active: item.active ?? isActive
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
}, [toolbarItems, state]);
|
|
53
|
+
|
|
54
|
+
// Custom render
|
|
55
|
+
if (renderToolbar) {
|
|
56
|
+
return renderToolbar({
|
|
57
|
+
items: enrichedItems,
|
|
58
|
+
state,
|
|
59
|
+
actions
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (!visible) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
const toolbarStyle = [resolvedTheme.toolbarStyle ?? _defaultStyles.DEFAULT_THEME.toolbarStyle];
|
|
66
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
67
|
+
style: toolbarStyle,
|
|
68
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
|
|
69
|
+
horizontal: true,
|
|
70
|
+
showsHorizontalScrollIndicator: false,
|
|
71
|
+
keyboardShouldPersistTaps: "always",
|
|
72
|
+
contentContainerStyle: styles.scrollContent,
|
|
73
|
+
children: enrichedItems.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)(_ToolbarButton.ToolbarButton, {
|
|
74
|
+
label: item.label,
|
|
75
|
+
active: !!item.active,
|
|
76
|
+
theme: resolvedTheme,
|
|
77
|
+
renderButton: item.renderButton,
|
|
78
|
+
onPress: () => {
|
|
79
|
+
if (item.onPress) {
|
|
80
|
+
item.onPress();
|
|
81
|
+
} else if (item.format) {
|
|
82
|
+
actions.toggleFormat(item.format);
|
|
83
|
+
} else if (item.heading) {
|
|
84
|
+
actions.setHeading(item.heading);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}, item.id))
|
|
88
|
+
})
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
Toolbar.displayName = 'Toolbar';
|
|
92
|
+
const styles = _reactNative.StyleSheet.create({
|
|
93
|
+
scrollContent: {
|
|
94
|
+
flexDirection: 'row',
|
|
95
|
+
alignItems: 'center',
|
|
96
|
+
gap: 2
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=Toolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_defaultStyles","_ToolbarButton","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","Toolbar","exports","React","memo","actions","state","items","theme","visible","renderToolbar","resolvedTheme","DEFAULT_THEME","toolbarItems","DEFAULT_TOOLBAR_ITEMS","enrichedItems","useMemo","map","item","isActive","format","activeStyles","heading","active","toolbarStyle","jsx","View","style","children","ScrollView","horizontal","showsHorizontalScrollIndicator","keyboardShouldPersistTaps","contentContainerStyle","styles","scrollContent","ToolbarButton","label","renderButton","onPress","toggleFormat","setHeading","id","displayName","StyleSheet","create","flexDirection","alignItems","gap"],"sourceRoot":"..\\..\\..\\src","sources":["components/Toolbar.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"..\\..\\..\\src","sources":["components/ToolbarButton.d.ts"],"mappings":"","ignoreList":[]}
|