react-native-highlight-text-view 0.1.6 → 0.1.7

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/README.md CHANGED
@@ -50,15 +50,42 @@ export default function App() {
50
50
  | `verticalAlign` | `'top' \| 'center' \| 'middle' \| 'bottom'` | - | Vertical alignment (iOS only). Alternative to using combined `textAlign` values |
51
51
  | `fontFamily` | `string` | - | Font family name |
52
52
  | `fontSize` | `string` | `32` | Font size in points |
53
- | `padding` | `string` | `4` | Padding around each character highlight |
53
+ | `lineHeight` | `string` | - | Line height override |
54
+ | `highlightBorderRadius` | `string` | `4` | Border radius for the highlight background |
55
+ | `padding` | `string` | `4` | Padding around each character highlight (expands background outward) |
54
56
  | `paddingLeft` | `string` | - | Left padding for character highlight |
55
57
  | `paddingRight` | `string` | - | Right padding for character highlight |
56
58
  | `paddingTop` | `string` | - | Top padding for character highlight |
57
59
  | `paddingBottom` | `string` | - | Bottom padding for character highlight |
60
+ | `backgroundInsetTop` | `string` | `0` | Shrinks background from top (useful for fonts with large vertical metrics) |
61
+ | `backgroundInsetBottom` | `string` | `0` | Shrinks background from bottom (useful for fonts with large vertical metrics) |
62
+ | `backgroundInsetLeft` | `string` | `0` | Shrinks background from left |
63
+ | `backgroundInsetRight` | `string` | `0` | Shrinks background from right |
58
64
  | `text` | `string` | - | Controlled text value |
59
65
  | `isEditable` | `boolean` | `true` | Whether the text is editable |
60
66
  | `onChange` | `(event: { nativeEvent: { text: string } }) => void` | - | Callback fired when text changes |
61
67
 
68
+ ### Understanding Padding vs Background Insets
69
+
70
+ - **Padding props** (`paddingTop`, `paddingBottom`, etc.): Expand the background **outward** from the text, adding extra colored area around glyphs.
71
+ - **Background inset props** (`backgroundInsetTop`, `backgroundInsetBottom`, etc.): Shrink the background **inward** from the font's line box, creating tighter wrapping around actual glyphs.
72
+
73
+ **Use case for background insets:** Some fonts (like Eczar, Georgia, etc.) have large built-in vertical metrics (ascender/descender), making highlights appear too tall. Use `backgroundInsetTop` and `backgroundInsetBottom` to create a tighter fit around the visible glyphs.
74
+
75
+ **Example with large-metric font:**
76
+ ```jsx
77
+ <HighlightTextView
78
+ fontFamily="Eczar"
79
+ fontSize="32"
80
+ paddingLeft="8"
81
+ paddingRight="8"
82
+ paddingTop="4"
83
+ paddingBottom="4"
84
+ backgroundInsetTop="6"
85
+ backgroundInsetBottom="6"
86
+ text="Tight Background"
87
+ />
88
+ ```
62
89
 
63
90
  **Note:** Vertical alignment is currently supported on iOS only. On Android, text will use default vertical positioning.
64
91
 
@@ -22,6 +22,10 @@ class RoundedBackgroundSpan(
22
22
  private val paddingRight: Float,
23
23
  private val paddingTop: Float,
24
24
  private val paddingBottom: Float,
25
+ private val backgroundInsetTop: Float,
26
+ private val backgroundInsetBottom: Float,
27
+ private val backgroundInsetLeft: Float,
28
+ private val backgroundInsetRight: Float,
25
29
  private val cornerRadius: Float,
26
30
  private val isFirstInGroup: Boolean = false,
27
31
  private val isLastInGroup: Boolean = false
@@ -61,7 +65,7 @@ class RoundedBackgroundSpan(
61
65
 
62
66
  val width = paint.measureText(text, start, end)
63
67
 
64
- // Use font metrics for consistent height instead of character bounds
68
+ // Use font metrics for consistent height (matches iOS behavior)
65
69
  val fontMetrics = paint.fontMetrics
66
70
  val textHeight = fontMetrics.descent - fontMetrics.ascent
67
71
  val textTop = y + fontMetrics.ascent
@@ -70,17 +74,21 @@ class RoundedBackgroundSpan(
70
74
  val leftPad = if (isFirstInGroup) paddingLeft else 0f
71
75
  val rightPad = if (isLastInGroup) paddingRight else 0f
72
76
 
73
- // Extend background slightly to overlap and eliminate gaps
74
- val overlapExtension = 1f
77
+ // Extend background to overlap and eliminate gaps between characters
78
+ val overlapExtension = 2f
75
79
  val leftExtension = if (!isFirstInGroup) overlapExtension else 0f
76
80
  val rightExtension = if (!isLastInGroup) overlapExtension else 0f
77
81
 
78
- // Calculate proper bounds with padding using consistent font metrics
82
+ // Apply background insets first (shrinks from line box)
83
+ val insetTop = textTop + backgroundInsetTop
84
+ val insetHeight = textHeight - (backgroundInsetTop + backgroundInsetBottom)
85
+
86
+ // Calculate proper bounds with insets then padding
79
87
  val rect = RectF(
80
- x - leftExtension,
81
- textTop - paddingTop,
82
- x + width + leftPad + rightPad + rightExtension,
83
- textTop + textHeight + paddingBottom
88
+ x - leftExtension + backgroundInsetLeft,
89
+ insetTop - paddingTop,
90
+ x + width + leftPad + rightPad + rightExtension - backgroundInsetRight,
91
+ insetTop + insetHeight + paddingBottom
84
92
  )
85
93
 
86
94
  // Draw background with selective corner rounding
@@ -142,6 +150,10 @@ class HighlightTextView : AppCompatEditText {
142
150
  private var charPaddingRight: Float = 8f
143
151
  private var charPaddingTop: Float = 4f
144
152
  private var charPaddingBottom: Float = 4f
153
+ private var backgroundInsetTop: Float = 0f
154
+ private var backgroundInsetBottom: Float = 0f
155
+ private var backgroundInsetLeft: Float = 0f
156
+ private var backgroundInsetRight: Float = 0f
145
157
  private var isUpdatingText: Boolean = false
146
158
 
147
159
  var onTextChangeListener: ((String) -> Unit)? = null
@@ -224,6 +236,31 @@ class HighlightTextView : AppCompatEditText {
224
236
  charPaddingBottom = padding
225
237
  applyCharacterBackgrounds()
226
238
  }
239
+
240
+ fun setCornerRadius(radius: Float) {
241
+ cornerRadius = radius
242
+ applyCharacterBackgrounds()
243
+ }
244
+
245
+ fun setBackgroundInsetTop(inset: Float) {
246
+ backgroundInsetTop = inset
247
+ applyCharacterBackgrounds()
248
+ }
249
+
250
+ fun setBackgroundInsetBottom(inset: Float) {
251
+ backgroundInsetBottom = inset
252
+ applyCharacterBackgrounds()
253
+ }
254
+
255
+ fun setBackgroundInsetLeft(inset: Float) {
256
+ backgroundInsetLeft = inset
257
+ applyCharacterBackgrounds()
258
+ }
259
+
260
+ fun setBackgroundInsetRight(inset: Float) {
261
+ backgroundInsetRight = inset
262
+ applyCharacterBackgrounds()
263
+ }
227
264
 
228
265
  fun setTextProp(text: String) {
229
266
  if (this.text?.toString() != text) {
@@ -268,6 +305,10 @@ class HighlightTextView : AppCompatEditText {
268
305
  charPaddingRight,
269
306
  charPaddingTop,
270
307
  charPaddingBottom,
308
+ backgroundInsetTop,
309
+ backgroundInsetBottom,
310
+ backgroundInsetLeft,
311
+ backgroundInsetRight,
271
312
  cornerRadius,
272
313
  isFirst,
273
314
  isLast
@@ -145,6 +145,47 @@ class HighlightTextViewManager : SimpleViewManager<HighlightTextView>(),
145
145
  }
146
146
  }
147
147
 
148
+ @ReactProp(name = "lineHeight")
149
+ override fun setLineHeight(view: HighlightTextView?, value: String?) {
150
+ // Line height is handled differently on Android - this is a placeholder
151
+ // Android EditText doesn't directly support line height like iOS
152
+ }
153
+
154
+ @ReactProp(name = "highlightBorderRadius")
155
+ override fun setHighlightBorderRadius(view: HighlightTextView?, value: String?) {
156
+ value?.toFloatOrNull()?.let { radius ->
157
+ view?.setCornerRadius(radius)
158
+ }
159
+ }
160
+
161
+ @ReactProp(name = "backgroundInsetTop")
162
+ override fun setBackgroundInsetTop(view: HighlightTextView?, value: String?) {
163
+ value?.toFloatOrNull()?.let { inset ->
164
+ view?.setBackgroundInsetTop(inset)
165
+ }
166
+ }
167
+
168
+ @ReactProp(name = "backgroundInsetBottom")
169
+ override fun setBackgroundInsetBottom(view: HighlightTextView?, value: String?) {
170
+ value?.toFloatOrNull()?.let { inset ->
171
+ view?.setBackgroundInsetBottom(inset)
172
+ }
173
+ }
174
+
175
+ @ReactProp(name = "backgroundInsetLeft")
176
+ override fun setBackgroundInsetLeft(view: HighlightTextView?, value: String?) {
177
+ value?.toFloatOrNull()?.let { inset ->
178
+ view?.setBackgroundInsetLeft(inset)
179
+ }
180
+ }
181
+
182
+ @ReactProp(name = "backgroundInsetRight")
183
+ override fun setBackgroundInsetRight(view: HighlightTextView?, value: String?) {
184
+ value?.toFloatOrNull()?.let { inset ->
185
+ view?.setBackgroundInsetRight(inset)
186
+ }
187
+ }
188
+
148
189
  @ReactProp(name = "text")
149
190
  override fun setText(view: HighlightTextView?, value: String?) {
150
191
  view?.setTextProp(value ?: "")
@@ -15,6 +15,10 @@ NS_ASSUME_NONNULL_BEGIN
15
15
  @property (nonatomic, assign) CGFloat paddingBottom;
16
16
  @property (nonatomic, assign) CGFloat cornerRadius;
17
17
  @property (nonatomic, assign) CGFloat highlightBorderRadius;
18
+ @property (nonatomic, assign) CGFloat backgroundInsetTop;
19
+ @property (nonatomic, assign) CGFloat backgroundInsetBottom;
20
+ @property (nonatomic, assign) CGFloat backgroundInsetLeft;
21
+ @property (nonatomic, assign) CGFloat backgroundInsetRight;
18
22
  @end
19
23
 
20
24
  @interface HighlightTextView : RCTViewComponentView
@@ -11,7 +11,7 @@ using namespace facebook::react;
11
11
 
12
12
  @implementation RoundedBackgroundLayoutManager
13
13
 
14
- @synthesize backgroundColor, padding, paddingLeft, paddingRight, paddingTop, paddingBottom, cornerRadius, highlightBorderRadius;
14
+ @synthesize backgroundColor, padding, paddingLeft, paddingRight, paddingTop, paddingBottom, cornerRadius, highlightBorderRadius, backgroundInsetTop, backgroundInsetBottom, backgroundInsetLeft, backgroundInsetRight;
15
15
 
16
16
  - (void)drawBackgroundForGlyphRange:(NSRange)glyphsToShow atPoint:(CGPoint)origin {
17
17
  NSTextStorage *textStorage = self.textStorage;
@@ -41,7 +41,13 @@ using namespace facebook::react;
41
41
  if (boundingRect.size.width > 1.0 && boundingRect.size.height > 1.0 &&
42
42
  boundingRect.size.width < (textContainer.size.width * 0.8)) {
43
43
 
44
- // Apply individual padding values
44
+ // Apply background insets first (shrinks from line box)
45
+ boundingRect.origin.y += self.backgroundInsetTop;
46
+ boundingRect.size.height -= (self.backgroundInsetTop + self.backgroundInsetBottom);
47
+ boundingRect.origin.x += self.backgroundInsetLeft;
48
+ boundingRect.size.width -= (self.backgroundInsetLeft + self.backgroundInsetRight);
49
+
50
+ // Then apply padding (expands outward)
45
51
  boundingRect.origin.x += origin.x - self.paddingLeft;
46
52
  boundingRect.origin.y += origin.y - self.paddingTop;
47
53
  boundingRect.size.width += self.paddingLeft + self.paddingRight;
@@ -78,6 +84,10 @@ using namespace facebook::react;
78
84
  CGFloat _paddingBottom;
79
85
  CGFloat _cornerRadius;
80
86
  CGFloat _highlightBorderRadius;
87
+ CGFloat _backgroundInsetTop;
88
+ CGFloat _backgroundInsetBottom;
89
+ CGFloat _backgroundInsetLeft;
90
+ CGFloat _backgroundInsetRight;
81
91
  CGFloat _lineHeight;
82
92
  BOOL _isUpdatingText;
83
93
  NSString * _currentVerticalAlignment;
@@ -103,6 +113,10 @@ using namespace facebook::react;
103
113
  _paddingBottom = 4.0;
104
114
  _cornerRadius = 4.0;
105
115
  _highlightBorderRadius = 0.0;
116
+ _backgroundInsetTop = 0.0;
117
+ _backgroundInsetBottom = 0.0;
118
+ _backgroundInsetLeft = 0.0;
119
+ _backgroundInsetRight = 0.0;
106
120
  _lineHeight = 0.0; // 0 means use default line height
107
121
  _currentVerticalAlignment = nil;
108
122
  _currentHorizontalAlignment = NSTextAlignmentCenter;
@@ -118,6 +132,10 @@ using namespace facebook::react;
118
132
  _layoutManager.paddingBottom = _paddingBottom;
119
133
  _layoutManager.cornerRadius = _cornerRadius;
120
134
  _layoutManager.highlightBorderRadius = _highlightBorderRadius;
135
+ _layoutManager.backgroundInsetTop = _backgroundInsetTop;
136
+ _layoutManager.backgroundInsetBottom = _backgroundInsetBottom;
137
+ _layoutManager.backgroundInsetLeft = _backgroundInsetLeft;
138
+ _layoutManager.backgroundInsetRight = _backgroundInsetRight;
121
139
 
122
140
  [textStorage addLayoutManager:_layoutManager];
123
141
 
@@ -339,6 +357,46 @@ using namespace facebook::react;
339
357
  }
340
358
  }
341
359
 
360
+ if (oldViewProps.backgroundInsetTop != newViewProps.backgroundInsetTop) {
361
+ NSString *insetStr = [[NSString alloc] initWithUTF8String: newViewProps.backgroundInsetTop.c_str()];
362
+ CGFloat inset = [insetStr floatValue];
363
+ if (inset >= 0) {
364
+ _backgroundInsetTop = inset;
365
+ _layoutManager.backgroundInsetTop = _backgroundInsetTop;
366
+ [self applyCharacterBackgrounds];
367
+ }
368
+ }
369
+
370
+ if (oldViewProps.backgroundInsetBottom != newViewProps.backgroundInsetBottom) {
371
+ NSString *insetStr = [[NSString alloc] initWithUTF8String: newViewProps.backgroundInsetBottom.c_str()];
372
+ CGFloat inset = [insetStr floatValue];
373
+ if (inset >= 0) {
374
+ _backgroundInsetBottom = inset;
375
+ _layoutManager.backgroundInsetBottom = _backgroundInsetBottom;
376
+ [self applyCharacterBackgrounds];
377
+ }
378
+ }
379
+
380
+ if (oldViewProps.backgroundInsetLeft != newViewProps.backgroundInsetLeft) {
381
+ NSString *insetStr = [[NSString alloc] initWithUTF8String: newViewProps.backgroundInsetLeft.c_str()];
382
+ CGFloat inset = [insetStr floatValue];
383
+ if (inset >= 0) {
384
+ _backgroundInsetLeft = inset;
385
+ _layoutManager.backgroundInsetLeft = _backgroundInsetLeft;
386
+ [self applyCharacterBackgrounds];
387
+ }
388
+ }
389
+
390
+ if (oldViewProps.backgroundInsetRight != newViewProps.backgroundInsetRight) {
391
+ NSString *insetStr = [[NSString alloc] initWithUTF8String: newViewProps.backgroundInsetRight.c_str()];
392
+ CGFloat inset = [insetStr floatValue];
393
+ if (inset >= 0) {
394
+ _backgroundInsetRight = inset;
395
+ _layoutManager.backgroundInsetRight = _backgroundInsetRight;
396
+ [self applyCharacterBackgrounds];
397
+ }
398
+ }
399
+
342
400
  if (oldViewProps.text != newViewProps.text) {
343
401
  NSString *text = [[NSString alloc] initWithUTF8String: newViewProps.text.c_str()];
344
402
  if (![_textView.text isEqualToString:text]) {
@@ -53,6 +53,14 @@ export interface HighlightTextViewProps extends ViewProps {
53
53
  paddingRight?: string;
54
54
  paddingTop?: string;
55
55
  paddingBottom?: string;
56
+ /** Reduces background height from the top (shrinks inward from font line box) */
57
+ backgroundInsetTop?: string;
58
+ /** Reduces background height from the bottom (shrinks inward from font line box) */
59
+ backgroundInsetBottom?: string;
60
+ /** Reduces background width from the left (shrinks inward from glyph bounds) */
61
+ backgroundInsetLeft?: string;
62
+ /** Reduces background width from the right (shrinks inward from glyph bounds) */
63
+ backgroundInsetRight?: string;
56
64
  text?: string;
57
65
  isEditable?: boolean;
58
66
  onChange?: BubblingEventHandler<OnChangeEventData>;
@@ -35,6 +35,14 @@ export interface HighlightTextViewProps extends ViewProps {
35
35
  paddingRight?: string;
36
36
  paddingTop?: string;
37
37
  paddingBottom?: string;
38
+ /** Reduces background height from the top (shrinks inward from font line box) */
39
+ backgroundInsetTop?: string;
40
+ /** Reduces background height from the bottom (shrinks inward from font line box) */
41
+ backgroundInsetBottom?: string;
42
+ /** Reduces background width from the left (shrinks inward from glyph bounds) */
43
+ backgroundInsetLeft?: string;
44
+ /** Reduces background width from the right (shrinks inward from glyph bounds) */
45
+ backgroundInsetRight?: string;
38
46
  text?: string;
39
47
  isEditable?: boolean;
40
48
  onChange?: BubblingEventHandler<OnChangeEventData>;
@@ -1 +1 @@
1
- {"version":3,"file":"HighlightTextViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/HighlightTextViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,SAAS,GACT,YAAY,GACZ,UAAU,GACV,KAAK,GACL,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,WAAW,GACX,aAAa,GACb,eAAe,GACf,cAAc,CAAC;AAEnB,MAAM,WAAW,sBAAuB,SAAQ,SAAS;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;CACpD;;AAED,wBAEE"}
1
+ {"version":3,"file":"HighlightTextViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/HighlightTextViewNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,aAAa,GACrB,MAAM,GACN,QAAQ,GACR,OAAO,GACP,SAAS,GACT,YAAY,GACZ,UAAU,GACV,KAAK,GACL,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,WAAW,GACX,aAAa,GACb,eAAe,GACf,cAAc,CAAC;AAEnB,MAAM,WAAW,sBAAuB,SAAQ,SAAS;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iFAAiF;IACjF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gFAAgF;IAChF,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;CACpD;;AAED,wBAEE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-highlight-text-view",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "A native text input for React Native that supports inline text highlighting",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -53,6 +53,14 @@ export interface HighlightTextViewProps extends ViewProps {
53
53
  paddingRight?: string;
54
54
  paddingTop?: string;
55
55
  paddingBottom?: string;
56
+ /** Reduces background height from the top (shrinks inward from font line box) */
57
+ backgroundInsetTop?: string;
58
+ /** Reduces background height from the bottom (shrinks inward from font line box) */
59
+ backgroundInsetBottom?: string;
60
+ /** Reduces background width from the left (shrinks inward from glyph bounds) */
61
+ backgroundInsetLeft?: string;
62
+ /** Reduces background width from the right (shrinks inward from glyph bounds) */
63
+ backgroundInsetRight?: string;
56
64
  text?: string;
57
65
  isEditable?: boolean;
58
66
  onChange?: BubblingEventHandler<OnChangeEventData>;