rn-rich-text-editor 0.0.13 → 0.0.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-rich-text-editor",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "A rich text editor component for React Native",
5
5
  "keywords": [
6
6
  "react-native",
package/src/RichEditor.js CHANGED
@@ -304,13 +304,17 @@ export default class RichTextEditor extends Component {
304
304
  // useContainer is an optional prop with default value of true
305
305
  // If set to true, it will use a View wrapper with styles and height.
306
306
  // If set to false, it will not use a View wrapper
307
- const { useContainer, style } = this.props;
307
+ const { useContainer, style, errorMessage } = this.props;
308
+ const errorStyle = errorMessage ? { borderWidth: 1, borderColor: '#d92d20' } : {};
309
+
308
310
  return useContainer ? (
309
- <View style={[style, { height }]} onLayout={this.onViewLayout}>
311
+ <View style={[style, { height }, errorStyle]} onLayout={this.onViewLayout}>
310
312
  {this.renderWebView()}
311
313
  </View>
312
314
  ) : (
313
- this.renderWebView()
315
+ <View style={errorStyle}>
316
+ {this.renderWebView()}
317
+ </View>
314
318
  );
315
319
  }
316
320
 
@@ -2,6 +2,13 @@ import React, { Component } from 'react';
2
2
  import { FlatList, Image, StyleSheet, TouchableOpacity, View } from 'react-native';
3
3
  import { actions } from './actions';
4
4
 
5
+ const ALIGN_ACTIONS = [
6
+ actions.alignLeft,
7
+ actions.alignCenter,
8
+ actions.alignRight,
9
+ // actions.alignFull,
10
+ ];
11
+
5
12
  export const defaultActions = [
6
13
  actions.keyboard,
7
14
  actions.setBold,
@@ -43,6 +50,7 @@ function getDefaultIcon() {
43
50
  texts[actions.alignCenter] = require('./img/justify_center.png');
44
51
  texts[actions.alignRight] = require('./img/justify_right.png');
45
52
  texts[actions.alignFull] = require('./img/justify_full.png');
53
+ texts[actions.align] = require('./img/justify_left.png');
46
54
  texts[actions.blockquote] = require('./img/blockquote.png');
47
55
  texts[actions.line] = require('./img/line.png');
48
56
  texts[actions.fontSize] = require('./img/fontSize.png');
@@ -65,6 +73,7 @@ export default class RichToolbar extends Component {
65
73
  this.editor = null;
66
74
  this.state = {
67
75
  items: [],
76
+ selectedAlign: null,
68
77
  };
69
78
  }
70
79
 
@@ -74,6 +83,7 @@ export default class RichToolbar extends Component {
74
83
  nextState.items !== that.state.items ||
75
84
  nextState.actions !== that.state.actions ||
76
85
  nextState.data !== that.state.data ||
86
+ nextState.selectedAlign !== that.state.selectedAlign ||
77
87
  nextProps.style !== that.props.style
78
88
  );
79
89
  }
@@ -81,10 +91,18 @@ export default class RichToolbar extends Component {
81
91
  static getDerivedStateFromProps(nextProps, prevState) {
82
92
  const { actions } = nextProps;
83
93
  if (actions !== prevState.actions) {
84
- let { items = [] } = prevState;
94
+ const items = prevState.items || [];
95
+ const isItemSelected = (action) =>
96
+ items.includes(action) || items.some(item => item && item.type === action);
85
97
  return {
86
98
  actions,
87
- data: actions.map(action => ({ action, selected: items.includes(action) })),
99
+ data: actions.map(action => ({
100
+ action,
101
+ selected:
102
+ action === actions.align
103
+ ? ALIGN_ACTIONS.some(a => isItemSelected(a))
104
+ : isItemSelected(action),
105
+ })),
88
106
  };
89
107
  }
90
108
  return null;
@@ -112,15 +130,26 @@ export default class RichToolbar extends Component {
112
130
  }
113
131
  };
114
132
 
133
+ _isItemSelected(items, action) {
134
+ return (
135
+ items.includes(action) || items.some(item => item && item.type === action)
136
+ );
137
+ }
138
+
115
139
  setSelectedItems(items) {
116
140
  const { items: selectedItems } = this.state;
117
141
  if (this.editor && items !== selectedItems) {
142
+ const selectedAlign = ALIGN_ACTIONS.find(a => this._isItemSelected(items, a)) || null;
118
143
  this.setState({
119
144
  items,
120
- data: this.state.actions.map(action => ({
121
- action,
122
- selected: items.includes(action) || items.some(item => item && item.type === action),
123
- })),
145
+ selectedAlign,
146
+ data: this.state.actions.map(action => {
147
+ const isAlignAction = action === actions.align;
148
+ const selected = isAlignAction
149
+ ? !!selectedAlign
150
+ : this._isItemSelected(items, action);
151
+ return { action, selected };
152
+ }),
124
153
  });
125
154
  }
126
155
  }
@@ -168,6 +197,23 @@ export default class RichToolbar extends Component {
168
197
  return;
169
198
  }
170
199
 
200
+ if (action === actions.align) {
201
+ const { selectedAlign } = this.state;
202
+ // Cycle through alignments: Left -> Center -> Right -> Justify -> Left
203
+ let nextAlignIndex = 0; // Default to Left
204
+ if (selectedAlign) {
205
+ const currentIndex = ALIGN_ACTIONS.indexOf(selectedAlign);
206
+ if (currentIndex >= 0) {
207
+ nextAlignIndex = (currentIndex + 1) % ALIGN_ACTIONS.length;
208
+ }
209
+ }
210
+ const nextAlign = ALIGN_ACTIONS[nextAlignIndex];
211
+ editor.showAndroidKeyboard();
212
+ editor.sendAction(nextAlign, 'result');
213
+ // The selectedAlign will be updated when setSelectedItems is called by the editor
214
+ return;
215
+ }
216
+
171
217
  switch (action) {
172
218
  case actions.insertLink:
173
219
  if (onInsertLink) return onInsertLink();
@@ -270,7 +316,57 @@ export default class RichToolbar extends Component {
270
316
  );
271
317
  }
272
318
 
319
+ _renderAlignButton(action, selected) {
320
+ const that = this;
321
+ const { iconSize, iconGap, disabled, itemStyle } = that.props;
322
+ const style = selected ? that._getButtonSelectedStyle() : that._getButtonUnselectedStyle();
323
+ const tintColor = disabled
324
+ ? that.props.disabledIconTint
325
+ : selected
326
+ ? that.props.selectedIconTint
327
+ : that.props.iconTint;
328
+ const { selectedAlign } = that.state;
329
+
330
+ // Use the icon for the current alignment, or default to alignLeft icon
331
+ const currentAlignAction = selectedAlign || actions.alignLeft;
332
+ const icon = that._getButtonIcon(currentAlignAction);
333
+
334
+ return (
335
+ <TouchableOpacity
336
+ key={action}
337
+ disabled={disabled}
338
+ style={[{ width: iconGap + iconSize }, styles.item, itemStyle, style]}
339
+ testID={'button_align'}
340
+ accessible={true}
341
+ onPress={() => that._onPress(action)}>
342
+ {icon ? (
343
+ typeof icon === 'function' ? (
344
+ icon({
345
+ selected,
346
+ disabled,
347
+ tintColor: tintColor,
348
+ iconSize,
349
+ iconGap,
350
+ })
351
+ ) : (
352
+ <Image
353
+ source={icon}
354
+ style={{
355
+ tintColor,
356
+ height: iconSize,
357
+ width: iconSize,
358
+ }}
359
+ />
360
+ )
361
+ ) : null}
362
+ </TouchableOpacity>
363
+ );
364
+ }
365
+
273
366
  _renderAction(action, selected) {
367
+ if (action === actions.align) {
368
+ return this._renderAlignButton(action, selected);
369
+ }
274
370
  return this.props.renderAction
275
371
  ? this.props.renderAction(action, selected)
276
372
  : this._defaultRenderAction(action, selected);
package/src/actions.js CHANGED
@@ -17,6 +17,7 @@ export const actions = {
17
17
  alignCenter: 'justifyCenter',
18
18
  alignRight: 'justifyRight',
19
19
  alignFull: 'justifyFull',
20
+ align: 'align', // Single icon with dropdown for all 4 align options
20
21
  insertBulletsList: 'unorderedList',
21
22
  insertOrderedList: 'orderedList',
22
23
  checkboxList: 'checkboxList',
package/src/index.d.ts CHANGED
@@ -59,6 +59,7 @@ export interface RichEditorProps {
59
59
  onCursorPosition?: (offsetY: number) => void;
60
60
  onLink?: (data: unknown) => void;
61
61
  onHeightChange?: (height: number) => void;
62
+ errorMessage?: string;
62
63
  [key: string]: unknown;
63
64
  }
64
65
 
@@ -109,6 +110,7 @@ export const actions: {
109
110
  alignCenter: string;
110
111
  alignRight: string;
111
112
  alignFull: string;
113
+ align: string;
112
114
  insertBulletsList: string;
113
115
  insertOrderedList: string;
114
116
  checkboxList: string;