@apollohg/react-native-rich-text-editor 2.0.1 → 2.0.3

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.
Files changed (63) hide show
  1. package/README.md +29 -123
  2. package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +20 -6
  3. package/android/src/main/java/com/apollohg/editor/EditorEditTextClipboard.kt +181 -36
  4. package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +25 -0
  5. package/android/src/main/java/com/apollohg/editor/EditorEditTextSelection.kt +7 -0
  6. package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceInteraction.kt +31 -11
  7. package/android/src/main/java/com/apollohg/editor/EditorV2Adapter.kt +36 -0
  8. package/android/src/main/java/com/apollohg/editor/EditorV2Backend.kt +1 -0
  9. package/android/src/main/java/com/apollohg/editor/EditorV2Driver.kt +10 -0
  10. package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +1 -0
  11. package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +101 -33
  12. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +2 -0
  13. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewProperties.kt +4 -0
  14. package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +3 -0
  15. package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +15 -3
  16. package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +14 -0
  17. package/android/src/main/java/com/apollohg/editor/UniffiEditorV2Backend.kt +4 -0
  18. package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1 -1
  19. package/dist/EditorStyleSheetNormalization.js +1 -1
  20. package/dist/EditorStyleSheetTypes.d.ts +1 -1
  21. package/dist/NativeRichTextEditor.d.ts +1 -1
  22. package/dist/RichTextEditorNativeTypes.d.ts +2 -1
  23. package/dist/RichTextEditorTypes.d.ts +4 -0
  24. package/dist/index.d.ts +1 -1
  25. package/dist/useRichTextEditorPresentation.d.ts +1 -1
  26. package/dist/useRichTextEditorPresentation.js +2 -2
  27. package/dist/useRichTextEditorState.d.ts +5 -3
  28. package/dist/useRichTextEditorState.js +4 -3
  29. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  30. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  31. package/ios/EditorInteractionOverlays.swift +114 -122
  32. package/ios/EditorLayoutManager.swift +13 -3
  33. package/ios/EditorStyleSheet.swift +12 -1
  34. package/ios/EditorTextView+Images.swift +32 -10
  35. package/ios/EditorTextView+KeyboardInput.swift +299 -0
  36. package/ios/EditorTextView.swift +64 -44
  37. package/ios/EditorV2Adapter+Commands.swift +22 -0
  38. package/ios/EditorV2Adapter+RenderValidation.swift +2 -2
  39. package/ios/EditorV2Shadow.swift +12 -0
  40. package/ios/Generated_editor_core.swift +10 -0
  41. package/ios/NativeEditorExpoView+Properties.swift +4 -0
  42. package/ios/NativeEditorModule.swift +3 -0
  43. package/ios/NativeToolbar+ButtonStyle.swift +17 -5
  44. package/ios/NativeToolbar+Diagnostics.swift +15 -0
  45. package/ios/RenderBridge+Atoms.swift +0 -1
  46. package/ios/RenderBridge+Attachments.swift +0 -29
  47. package/ios/RichTextEditorView.swift +4 -12
  48. package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +3 -2
  49. package/ios/editor_coreFFI/editor_coreFFI.h +11 -0
  50. package/package.json +1 -1
  51. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  52. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  53. package/rust/android/x86/libeditor_core.so +0 -0
  54. package/rust/android/x86_64/libeditor_core.so +0 -0
  55. package/rust/bindings/kotlin/uniffi/editor_core/editor_core.kt +18 -0
  56. package/src/EditorStyleSheetNormalization.ts +1 -1
  57. package/src/EditorStyleSheetTypes.ts +1 -1
  58. package/src/NativeRichTextEditor.tsx +1 -0
  59. package/src/RichTextEditorNativeTypes.tsx +2 -0
  60. package/src/RichTextEditorTypes.tsx +5 -0
  61. package/src/index.ts +1 -0
  62. package/src/useRichTextEditorPresentation.tsx +3 -0
  63. package/src/useRichTextEditorState.tsx +5 -2
@@ -796,6 +796,42 @@ internal class EditorV2Adapter private constructor(
796
796
  )
797
797
  }
798
798
 
799
+ override fun clipboardJson(): String? {
800
+ if (destroyed) return null
801
+ return when (val result = backend.getClipboard(editorId)) {
802
+ is EditorV2CallResult.Ok -> result.value
803
+
804
+ is EditorV2CallResult.Err -> {
805
+ emit(result.error)
806
+ null
807
+ }
808
+ }
809
+ }
810
+
811
+ override fun pasteAtSelection(
812
+ fragment: String?,
813
+ html: String?,
814
+ text: String?,
815
+ plainText: Boolean,
816
+ anchor: Int,
817
+ head: Int,
818
+ preserveEngineSelection: Boolean
819
+ ): String? {
820
+ val command = JSONObject().put("type", "paste")
821
+ fragment?.let { command.put("fragment", it) }
822
+ html?.let { command.put("html", it) }
823
+ text?.let { command.put("text", it) }
824
+ if (plainText) command.put("plainText", true)
825
+ return performMutation(
826
+ preSelection = if (preserveEngineSelection) null else intArrayOf(anchor, head),
827
+ adoptEngineSelection = true
828
+ ) {
829
+ callWithEnvelope(JSONObject().put("command", command)) { requestJson ->
830
+ backend.applyCommand(editorId, requestJson)
831
+ }
832
+ }
833
+ }
834
+
799
835
  override fun toggleMark(markName: String, anchor: Int, head: Int): String? = commandAtSelection(
800
836
  JSONObject().put("type", "toggleMark").put("markType", markName),
801
837
  anchor,
@@ -37,6 +37,7 @@ internal interface EditorV2Backend {
37
37
  fun getDocumentJson(editorId: String): EditorV2CallResult<String>
38
38
  fun getDocumentHtml(editorId: String): EditorV2CallResult<String>
39
39
  fun getContentSnapshot(editorId: String): EditorV2CallResult<String>
40
+ fun getClipboard(editorId: String): EditorV2CallResult<String>
40
41
  fun applyInput(editorId: String, requestJson: String): EditorV2CallResult<String>
41
42
  fun applyCommand(editorId: String, requestJson: String): EditorV2CallResult<String>
42
43
  fun applyLocalApi(editorId: String, requestJson: String): EditorV2CallResult<String>
@@ -50,6 +50,16 @@ internal interface EditorV2Driver {
50
50
  fun insertNode(nodeType: String, anchor: Int, head: Int): String?
51
51
  fun insertContentHtmlAtSelection(html: String, anchor: Int, head: Int): String?
52
52
  fun insertContentJsonAtSelection(json: String, anchor: Int, head: Int): String?
53
+ fun clipboardJson(): String?
54
+ fun pasteAtSelection(
55
+ fragment: String?,
56
+ html: String?,
57
+ text: String?,
58
+ plainText: Boolean,
59
+ anchor: Int,
60
+ head: Int,
61
+ preserveEngineSelection: Boolean = false
62
+ ): String?
53
63
  fun toggleMark(markName: String, anchor: Int, head: Int): String?
54
64
  fun setMark(markName: String, attrsJson: String, anchor: Int, head: Int): String?
55
65
  fun unsetMark(markName: String, anchor: Int, head: Int): String?
@@ -141,6 +141,7 @@ private fun validMentionNodeStyle(value: Any?): Boolean {
141
141
  listOf("Top", "Right", "Bottom", "Left").map { "border${it}Color" }
142
142
  val nonnegative =
143
143
  listOf("Top", "Right", "Bottom", "Left").map { "border${it}Width" } +
144
+ listOf("Top", "Right", "Bottom", "Left").map { "padding$it" } +
144
145
  listOf("TopLeft", "TopRight", "BottomLeft", "BottomRight").map { "border${it}Radius" }
145
146
  val enums = mapOf(
146
147
  "fontWeight" to
@@ -30,8 +30,15 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
30
30
  val corner: Corner,
31
31
  val originalRect: RectF,
32
32
  val docPos: Int,
33
+ val span: BlockImageSpan,
34
+ val downX: Float,
35
+ val downY: Float,
36
+ val originalSize: Pair<Int, Int>,
37
+ val fixedWidthPx: Float,
38
+ val fixedHeightPx: Float,
33
39
  val maximumWidthPx: Float,
34
- var previewRect: RectF
40
+ var previewRect: RectF,
41
+ var previewContentSize: Pair<Float, Float>
35
42
  )
36
43
 
37
44
  private var editorView: RichTextEditorView? = null
@@ -73,7 +80,10 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
73
80
  cancelActiveResize()
74
81
  return
75
82
  }
76
- if (currentGeometry?.docPos != nextGeometry.docPos) cancelActiveResize()
83
+ val selectedSpan = editorView?.selectedImageSpanForResize()
84
+ if (currentGeometry?.docPos != nextGeometry.docPos ||
85
+ dragState?.span?.let { it !== selectedSpan } == true
86
+ ) cancelActiveResize()
77
87
  currentGeometry = nextGeometry
78
88
  visibility = VISIBLE
79
89
  bringToFront()
@@ -82,6 +92,7 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
82
92
  }
83
93
 
84
94
  fun cancelActiveResize() {
95
+ dragState?.let { state -> editorView?.restoreImageResizePreview(state.span) }
85
96
  dragState = null
86
97
  currentGeometry = null
87
98
  parent?.requestDisallowInterceptTouchEvent(false)
@@ -114,12 +125,20 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
114
125
  when (event.actionMasked) {
115
126
  MotionEvent.ACTION_DOWN -> {
116
127
  val corner = cornerAt(event.x, event.y, geometry.rect) ?: return false
128
+ val span = editorView?.selectedImageSpanForResize() ?: return false
117
129
  dragState = DragState(
118
130
  corner = corner,
119
131
  originalRect = RectF(geometry.rect),
120
132
  docPos = geometry.docPos,
133
+ span = span,
134
+ downX = event.x,
135
+ downY = event.y,
136
+ originalSize = span.currentSizePx(),
137
+ fixedWidthPx = geometry.rect.width() - span.currentSizePx().first,
138
+ fixedHeightPx = geometry.rect.height() - span.currentSizePx().second,
121
139
  maximumWidthPx = editorView?.maximumImageWidthPx() ?: geometry.rect.width(),
122
- previewRect = RectF(geometry.rect)
140
+ previewRect = RectF(geometry.rect),
141
+ previewContentSize = span.currentSizePx().let { it.first.toFloat() to it.second.toFloat() }
123
142
  )
124
143
  parent?.requestDisallowInterceptTouchEvent(true)
125
144
  return true
@@ -127,29 +146,24 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
127
146
 
128
147
  MotionEvent.ACTION_MOVE -> {
129
148
  val state = dragState ?: return false
130
- val nextRect = resizedRect(
131
- originalRect = state.originalRect,
132
- corner = state.corner,
133
- deltaX = event.x - handleCenter(state.corner, state.originalRect).x,
134
- deltaY = event.y - handleCenter(state.corner, state.originalRect).y,
135
- maximumWidthPx = state.maximumWidthPx
136
- )
137
- state.previewRect = RectF(nextRect)
138
- currentGeometry = EditorEditText.SelectedImageGeometry(state.docPos, nextRect)
139
- updateSystemGestureExclusionRects()
140
- invalidate()
149
+ updatePreview(state, event.x, event.y)
141
150
  return true
142
151
  }
143
152
 
144
153
  MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
145
154
  val state = dragState ?: return false
146
155
  if (event.actionMasked == MotionEvent.ACTION_UP) {
147
- editorView?.resizeImage(
148
- state.docPos,
149
- state.previewRect.width(),
150
- state.previewRect.height()
151
- )
152
- }
156
+ updatePreview(state, event.x, event.y)
157
+ val previewSize = state.span.currentSizePx()
158
+ if (previewSize != state.originalSize) {
159
+ editorView?.resizeImage(
160
+ state.docPos,
161
+ state.previewContentSize.first,
162
+ state.previewContentSize.second
163
+ )
164
+ }
165
+ editorView?.restoreImageResizePreview(state.span)
166
+ } else editorView?.restoreImageResizePreview(state.span)
153
167
  dragState = null
154
168
  parent?.requestDisallowInterceptTouchEvent(false)
155
169
  post { refresh() }
@@ -160,6 +174,51 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
160
174
  return false
161
175
  }
162
176
 
177
+ private fun updatePreview(state: DragState, x: Float, y: Float) {
178
+ val deltaX = x - state.downX
179
+ val deltaY = y - state.downY
180
+ if (deltaX == 0f && deltaY == 0f) {
181
+ val originalContentSize = state.originalSize.let {
182
+ it.first.toFloat() to it.second.toFloat()
183
+ }
184
+ if (state.previewContentSize == originalContentSize) return
185
+ val boundEditor = editorView ?: return
186
+ if (!boundEditor.previewImageResize(
187
+ state.span,
188
+ originalContentSize.first,
189
+ originalContentSize.second
190
+ )
191
+ ) return
192
+ state.previewRect = RectF(state.originalRect)
193
+ state.previewContentSize = originalContentSize
194
+ currentGeometry = boundEditor.selectedImageGeometry()
195
+ ?.takeIf { it.docPos == state.docPos }
196
+ ?: EditorEditText.SelectedImageGeometry(state.docPos, state.originalRect)
197
+ updateSystemGestureExclusionRects()
198
+ invalidate()
199
+ return
200
+ }
201
+ val (nextRect, contentSize) = resizedRect(
202
+ originalRect = state.originalRect,
203
+ originalContentSize = state.originalSize,
204
+ fixedWidthPx = state.fixedWidthPx,
205
+ fixedHeightPx = state.fixedHeightPx,
206
+ corner = state.corner,
207
+ deltaX = deltaX,
208
+ deltaY = deltaY,
209
+ maximumWidthPx = state.maximumWidthPx
210
+ )
211
+ val boundEditor = editorView ?: return
212
+ if (!boundEditor.previewImageResize(state.span, contentSize.first, contentSize.second)) return
213
+ state.previewRect = RectF(nextRect)
214
+ state.previewContentSize = contentSize
215
+ currentGeometry = boundEditor.selectedImageGeometry()
216
+ ?.takeIf { it.docPos == state.docPos }
217
+ ?: EditorEditText.SelectedImageGeometry(state.docPos, nextRect)
218
+ updateSystemGestureExclusionRects()
219
+ invalidate()
220
+ }
221
+
163
222
  override fun onDetachedFromWindow() {
164
223
  cancelActiveResize()
165
224
  super.onDetachedFromWindow()
@@ -217,12 +276,17 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
217
276
 
218
277
  private fun resizedRect(
219
278
  originalRect: RectF,
279
+ originalContentSize: Pair<Int, Int>,
280
+ fixedWidthPx: Float,
281
+ fixedHeightPx: Float,
220
282
  corner: Corner,
221
283
  deltaX: Float,
222
284
  deltaY: Float,
223
285
  maximumWidthPx: Float?
224
- ): RectF {
225
- val aspectRatio = max(originalRect.width() / max(originalRect.height(), 1f), 0.1f)
286
+ ): Pair<RectF, Pair<Float, Float>> {
287
+ val originalWidth = max(originalContentSize.first.toFloat(), 1f)
288
+ val originalHeight = max(originalContentSize.second.toFloat(), 1f)
289
+ val aspectRatio = max(originalWidth / originalHeight, 0.1f)
226
290
  val signedDx = if (corner == Corner.TOP_RIGHT ||
227
291
  corner == Corner.BOTTOM_RIGHT
228
292
  ) {
@@ -237,30 +301,34 @@ internal class ImageResizeOverlayView @JvmOverloads constructor(
237
301
  } else {
238
302
  -deltaY
239
303
  }
240
- val widthScale = (originalRect.width() + signedDx) / max(originalRect.width(), 1f)
241
- val heightScale = (originalRect.height() + signedDy) / max(originalRect.height(), 1f)
304
+ val projectedScale = 1f +
305
+ ((signedDx * originalWidth) + (signedDy * originalHeight)) /
306
+ ((originalWidth * originalWidth) + (originalHeight * originalHeight))
242
307
  val scale = max(
243
- max(widthScale, heightScale),
244
- minimumImageSizePx / max(originalRect.width(), 1f)
308
+ projectedScale,
309
+ max(minimumImageSizePx / originalWidth, minimumImageSizePx / originalHeight)
245
310
  )
246
- val unclampedWidth = max(minimumImageSizePx, originalRect.width() * scale)
311
+ val unclampedWidth = max(minimumImageSizePx, originalWidth * scale)
247
312
  val unclampedHeight = max(minimumImageSizePx / aspectRatio, unclampedWidth / aspectRatio)
248
313
  val (width, height) = editorView?.let { boundEditor ->
249
314
  maximumWidthPx?.let { maxWidth ->
250
315
  boundEditor.clampImageSize(
251
316
  widthPx = unclampedWidth,
252
317
  heightPx = unclampedHeight,
253
- maximumWidthPx = maxWidth
318
+ maximumWidthPx = (maxWidth - fixedWidthPx).coerceAtLeast(minimumImageSizePx)
254
319
  )
255
320
  } ?: boundEditor.clampImageSize(unclampedWidth, unclampedHeight)
256
321
  } ?: (unclampedWidth to unclampedHeight)
257
322
  val anchor = anchorPoint(corner, originalRect)
258
323
 
259
- return when (corner) {
260
- Corner.TOP_LEFT -> RectF(anchor.x - width, anchor.y - height, anchor.x, anchor.y)
261
- Corner.TOP_RIGHT -> RectF(anchor.x, anchor.y - height, anchor.x + width, anchor.y)
262
- Corner.BOTTOM_LEFT -> RectF(anchor.x - width, anchor.y, anchor.x, anchor.y + height)
263
- Corner.BOTTOM_RIGHT -> RectF(anchor.x, anchor.y, anchor.x + width, anchor.y + height)
324
+ val visualWidth = width + fixedWidthPx
325
+ val visualHeight = height + fixedHeightPx
326
+ val rect = when (corner) {
327
+ Corner.TOP_LEFT -> RectF(anchor.x - visualWidth, anchor.y - visualHeight, anchor.x, anchor.y)
328
+ Corner.TOP_RIGHT -> RectF(anchor.x, anchor.y - visualHeight, anchor.x + visualWidth, anchor.y)
329
+ Corner.BOTTOM_LEFT -> RectF(anchor.x - visualWidth, anchor.y, anchor.x, anchor.y + visualHeight)
330
+ Corner.BOTTOM_RIGHT -> RectF(anchor.x, anchor.y, anchor.x + visualWidth, anchor.y + visualHeight)
264
331
  }
332
+ return rect to (width to height)
265
333
  }
266
334
  }
@@ -388,6 +388,8 @@ class NativeEditorExpoView(context: Context, appContext: AppContext) :
388
388
 
389
389
  fun setEditable(editable: Boolean) = setEditableImpl(editable)
390
390
 
391
+ fun setPasteMode(rawPasteMode: String?) = setPasteModeImpl(rawPasteMode)
392
+
391
393
  fun beginExternalTextComposition(sessionId: String): String =
392
394
  beginExternalTextCompositionImpl(sessionId)
393
395
 
@@ -140,6 +140,10 @@ internal fun NativeEditorExpoView.setEditableImpl(editable: Boolean) {
140
140
  updateKeyboardToolbarVisibility()
141
141
  }
142
142
 
143
+ internal fun NativeEditorExpoView.setPasteModeImpl(rawPasteMode: String?) {
144
+ richTextView.editorEditText.pasteMode = EditorPasteMode.fromRaw(rawPasteMode)
145
+ }
146
+
143
147
  internal fun NativeEditorExpoView.setAccessibilityLabelImpl(label: String?) {
144
148
  richTextView.editorEditText.contentDescription = label
145
149
  }
@@ -520,6 +520,9 @@ class NativeEditorModule : Module() {
520
520
  Prop("editable") { view: NativeEditorExpoView, editable: Boolean ->
521
521
  view.setEditable(editable)
522
522
  }
523
+ Prop("pasteMode") { view: NativeEditorExpoView, pasteMode: String? ->
524
+ view.setPasteMode(pasteMode)
525
+ }
523
526
  Prop("accessibilityLabel") { view: NativeEditorExpoView, label: String? ->
524
527
  view.setAccessibilityLabel(label)
525
528
  }
@@ -74,6 +74,7 @@ internal class BlockImageSpan(
74
74
 
75
75
  @Volatile
76
76
  private var lastDrawRect: RectF? = null
77
+ private var temporarySizePx: Pair<Int, Int>? = null
77
78
 
78
79
  init {
79
80
  if (preparedSource != null) {
@@ -228,9 +229,6 @@ internal class BlockImageSpan(
228
229
  paint.color = Color.argb(24, 0, 0, 0)
229
230
  paint.style = Paint.Style.FILL
230
231
  canvas.drawRoundRect(rect, 16f * density, 16f * density, paint)
231
- paint.color = Color.argb(120, 0, 0, 0)
232
- val iconRadius = minOf(rect.width(), rect.height()) * 0.12f
233
- canvas.drawCircle(rect.centerX(), rect.centerY(), iconRadius, paint)
234
232
  paint.color = previousColor
235
233
  paint.style = previousStyle
236
234
  }
@@ -247,6 +245,7 @@ internal class BlockImageSpan(
247
245
  }
248
246
 
249
247
  internal fun currentSizePx(): Pair<Int, Int> {
248
+ temporarySizePx?.let { return it }
250
249
  val maxWidth = resolvedMaxWidth()
251
250
  val loadedBitmap = bitmapLease.get()?.bitmap
252
251
  val fallbackAspectRatio = if (loadedBitmap != null && loadedBitmap.width > 0 &&
@@ -299,6 +298,19 @@ internal class BlockImageSpan(
299
298
 
300
299
  internal fun currentDrawRect(): RectF? = lastDrawRect?.let(::RectF)
301
300
 
301
+ internal fun setTemporarySizePx(widthPx: Float, heightPx: Float): Boolean {
302
+ val next = checkedPositiveInt(widthPx) to checkedPositiveInt(heightPx)
303
+ if (temporarySizePx == next) return false
304
+ temporarySizePx = next
305
+ return true
306
+ }
307
+
308
+ internal fun clearTemporarySize(): Boolean {
309
+ if (temporarySizePx == null) return false
310
+ temporarySizePx = null
311
+ return true
312
+ }
313
+
302
314
  private fun resolvedMaxWidth(): Float {
303
315
  val host = hostRef.get()
304
316
  val hostWidth = host?.let {
@@ -943,6 +943,20 @@ class RichTextEditorView @JvmOverloads constructor(
943
943
  editorEditText.resizeImageAtDocPos(docPos, clampedWidth, clampedHeight)
944
944
  }
945
945
 
946
+ internal fun selectedImageSpanForResize(): BlockImageSpan? =
947
+ editorEditText.selectedImageSpanForResize()
948
+
949
+ internal fun previewImageResize(span: BlockImageSpan, widthPx: Float, heightPx: Float): Boolean {
950
+ if (!span.setTemporarySizePx(widthPx, heightPx)) return false
951
+ editorEditText.relayoutImageResizePreview(span)
952
+ return true
953
+ }
954
+
955
+ internal fun restoreImageResizePreview(span: BlockImageSpan) {
956
+ if (!span.clearTemporarySize()) return
957
+ editorEditText.relayoutImageResizePreview(span)
958
+ }
959
+
946
960
  private fun refreshOverlays() {
947
961
  layoutAtomHostViews()
948
962
  remoteSelectionOverlayView.refreshGeometry()
@@ -20,6 +20,7 @@ import uniffi.editor_core.editorV2CollaborationSocketOpen
20
20
  import uniffi.editor_core.editorV2Create
21
21
  import uniffi.editor_core.editorV2Destroy
22
22
  import uniffi.editor_core.editorV2DocToScalar
23
+ import uniffi.editor_core.editorV2GetClipboard
23
24
  import uniffi.editor_core.editorV2GetContentSnapshot
24
25
  import uniffi.editor_core.editorV2GetDocumentHtml
25
26
  import uniffi.editor_core.editorV2GetDocumentJson
@@ -77,6 +78,9 @@ internal object UniffiEditorV2Backend : EditorV2Backend {
77
78
  override fun getContentSnapshot(editorId: String): EditorV2CallResult<String> =
78
79
  normalize(editorV2GetContentSnapshot(editorId))
79
80
 
81
+ override fun getClipboard(editorId: String): EditorV2CallResult<String> =
82
+ normalize(editorV2GetClipboard(editorId))
83
+
80
84
  override fun applyInput(editorId: String, requestJson: String): EditorV2CallResult<String> =
81
85
  normalize(editorV2ApplyInput(editorId, requestJson))
82
86
 
@@ -1182,7 +1182,7 @@ internal class StaticLayoutAndroidProseLayoutEngine : AndroidProseLayoutEngine {
1182
1182
  )
1183
1183
  val width =
1184
1184
  max(
1185
- base.sizePx.toInt(),
1185
+ if (inline.nodeType == "mention") 0 else base.sizePx.toInt(),
1186
1186
  ceil(
1187
1187
  labelPaint.measureText(label) + atomInset.left + atomInset.right
1188
1188
  ).toInt()
@@ -63,7 +63,7 @@ const fields = {
63
63
  italic: inline,
64
64
  underline: inline,
65
65
  strike: inline,
66
- mention: [...inline, ...border],
66
+ mention: [...inline, ...border, ...spacing('padding')],
67
67
  placeholder: typography,
68
68
  };
69
69
  const enums = {
@@ -91,7 +91,7 @@ export interface EditorHorizontalRuleStyle extends EditorBorderStyle, EditorMarg
91
91
  backgroundColor?: string;
92
92
  height?: number;
93
93
  }
94
- export interface EditorMentionStyle extends EditorInlineStyle, EditorBorderStyle {
94
+ export interface EditorMentionStyle extends EditorInlineStyle, EditorBorderStyle, EditorPaddingStyle {
95
95
  }
96
96
  export interface EditorStyleMap {
97
97
  content: EditorSurfaceStyle;
@@ -1,3 +1,3 @@
1
- export { type RichTextEditorHeightBehavior, type RichTextEditorToolbarPlacement, type RichTextEditorValueJSONUpdateMode, type RichTextEditorAutoCapitalize, type RichTextEditorKeyboardType, type RichTextEditorAndroidInputOptions, type RemoteSelectionDecoration, type LinkRequestContext, type ImageRequestContext, type RichTextEditorProps, type RichTextEditorRef, type RichTextEditorCaretRect, type NativeRichTextEditorHeightBehavior, type NativeRichTextEditorToolbarPlacement, type NativeRichTextEditorValueJSONUpdateMode, type NativeRichTextEditorAutoCapitalize, type NativeRichTextEditorKeyboardType, type NativeRichTextEditorAndroidInputOptions, type NativeRichTextEditorProps, type NativeRichTextEditorRef, type NativeRichTextEditorCaretRect, } from './RichTextEditorTypes';
1
+ export { type RichTextEditorHeightBehavior, type RichTextEditorToolbarPlacement, type RichTextEditorValueJSONUpdateMode, type RichTextEditorPasteMode, type RichTextEditorAutoCapitalize, type RichTextEditorKeyboardType, type RichTextEditorAndroidInputOptions, type RemoteSelectionDecoration, type LinkRequestContext, type ImageRequestContext, type RichTextEditorProps, type RichTextEditorRef, type RichTextEditorCaretRect, type NativeRichTextEditorHeightBehavior, type NativeRichTextEditorToolbarPlacement, type NativeRichTextEditorValueJSONUpdateMode, type NativeRichTextEditorAutoCapitalize, type NativeRichTextEditorKeyboardType, type NativeRichTextEditorAndroidInputOptions, type NativeRichTextEditorProps, type NativeRichTextEditorRef, type NativeRichTextEditorCaretRect, } from './RichTextEditorTypes';
2
2
  export { RichTextEditor, NativeRichTextEditor } from './RichTextEditor';
3
3
  export type { NativeRichTextEditorFocusPreservingElement, NativeRichTextEditorFocusPreservingRef, NativeRichTextEditorFocusPreservingRefs, RichTextEditorFocusPreservingElement, RichTextEditorFocusPreservingRef, RichTextEditorFocusPreservingRefs, } from './useFocusPreservingFrames';
@@ -2,7 +2,7 @@ import { type ExternalTextCompositionManager, type NativeExternalTextComposition
2
2
  import { type ReactNode } from 'react';
3
3
  import { type NativeSyntheticEvent, type StyleProp, type ViewStyle } from 'react-native';
4
4
  import { type DocumentJSON, type NativeEditorDocumentHandle } from './NativeEditorBridge';
5
- import { type RichTextEditorAutoCapitalize, type RichTextEditorKeyboardType, type RichTextEditorToolbarPlacement, type RichTextEditorHeightBehavior } from './RichTextEditorTypes';
5
+ import { type RichTextEditorPasteMode, type RichTextEditorAutoCapitalize, type RichTextEditorKeyboardType, type RichTextEditorToolbarPlacement, type RichTextEditorHeightBehavior } from './RichTextEditorTypes';
6
6
  export interface NativeExternalTextCompositionEvent {
7
7
  editorId: string;
8
8
  resultJson: string;
@@ -21,6 +21,7 @@ export interface NativeEditorViewProps {
21
21
  editorId: string;
22
22
  placeholder?: string;
23
23
  editable: boolean;
24
+ pasteMode: RichTextEditorPasteMode;
24
25
  autoFocus: boolean;
25
26
  autoCapitalize?: RichTextEditorAutoCapitalize;
26
27
  autoCorrect?: boolean;
@@ -24,6 +24,8 @@ export type RichTextEditorToolbarPlacement = 'keyboard' | 'inline';
24
24
  * records one undoable step, `'reset'` clears history entirely.
25
25
  */
26
26
  export type RichTextEditorValueJSONUpdateMode = 'replace' | 'reset';
27
+ /** Controls native clipboard paste. Plain text keeps destination typing marks. */
28
+ export type RichTextEditorPasteMode = 'rich' | 'plainText' | 'disabled';
27
29
  /** Native keyboard auto-capitalization behavior. */
28
30
  export type RichTextEditorAutoCapitalize = 'none' | 'sentences' | 'words' | 'characters';
29
31
  /** Native keyboard layout. Values not supported by a platform fall back to its default. */
@@ -104,6 +106,8 @@ export interface RichTextEditorProps {
104
106
  placeholder?: string;
105
107
  /** Whether the editor is editable. Defaults to true. When false, every mutation ref method rejects with MUTATION_REJECTED; selection and controlled content still flow. */
106
108
  editable?: boolean;
109
+ /** Clipboard paste policy. Defaults to rich; updates apply immediately. */
110
+ pasteMode?: RichTextEditorPasteMode;
107
111
  /** Whether to auto-focus on mount. */
108
112
  autoFocus?: boolean;
109
113
  /** Controls native keyboard auto-capitalization. Defaults to sentences. */
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { RichTextEditor, type RichTextEditorProps, type RichTextEditorRef, type RichTextEditorCaretRect, type RichTextEditorHeightBehavior, type RichTextEditorToolbarPlacement, type RichTextEditorValueJSONUpdateMode, type RichTextEditorAutoCapitalize, type RichTextEditorKeyboardType, type RichTextEditorAndroidInputOptions, type RichTextEditorFocusPreservingElement, type RichTextEditorFocusPreservingRef, type RichTextEditorFocusPreservingRefs, type RemoteSelectionDecoration, type LinkRequestContext, type ImageRequestContext, NativeRichTextEditor, type NativeRichTextEditorProps, type NativeRichTextEditorRef, type NativeRichTextEditorCaretRect, type NativeRichTextEditorHeightBehavior, type NativeRichTextEditorToolbarPlacement, type NativeRichTextEditorValueJSONUpdateMode, type NativeRichTextEditorAutoCapitalize, type NativeRichTextEditorKeyboardType, type NativeRichTextEditorAndroidInputOptions, type NativeRichTextEditorFocusPreservingElement, type NativeRichTextEditorFocusPreservingRef, type NativeRichTextEditorFocusPreservingRefs, } from './NativeRichTextEditor';
1
+ export { RichTextEditor, type RichTextEditorProps, type RichTextEditorRef, type RichTextEditorCaretRect, type RichTextEditorHeightBehavior, type RichTextEditorToolbarPlacement, type RichTextEditorValueJSONUpdateMode, type RichTextEditorPasteMode, type RichTextEditorAutoCapitalize, type RichTextEditorKeyboardType, type RichTextEditorAndroidInputOptions, type RichTextEditorFocusPreservingElement, type RichTextEditorFocusPreservingRef, type RichTextEditorFocusPreservingRefs, type RemoteSelectionDecoration, type LinkRequestContext, type ImageRequestContext, NativeRichTextEditor, type NativeRichTextEditorProps, type NativeRichTextEditorRef, type NativeRichTextEditorCaretRect, type NativeRichTextEditorHeightBehavior, type NativeRichTextEditorToolbarPlacement, type NativeRichTextEditorValueJSONUpdateMode, type NativeRichTextEditorAutoCapitalize, type NativeRichTextEditorKeyboardType, type NativeRichTextEditorAndroidInputOptions, type NativeRichTextEditorFocusPreservingElement, type NativeRichTextEditorFocusPreservingRef, type NativeRichTextEditorFocusPreservingRefs, } from './NativeRichTextEditor';
2
2
  export type { ExternalTextCompositionEndCause, ExternalTextCompositionEndEvent, ExternalTextCompositionOptions, ExternalTextCompositionSession, } from './ExternalTextComposition';
3
3
  export { RichTextViewer, type RichTextViewerProps, type RichTextViewerAddons, type RichTextViewerBaseProps, type RichTextViewerMentionsConfig, type RichTextViewerLinkPressEvent, type RichTextViewerMentionPressEvent, type RichTextViewerErrorEvent, type RichTextViewerAtomAttrsUpdateEvent, NativeProseViewer, type NativeProseViewerProps, type NativeProseViewerAddons, type NativeProseViewerBaseProps, type NativeProseViewerMentionsConfig, type NativeProseViewerLinkPressEvent, type NativeProseViewerMentionPressEvent, type NativeProseViewerErrorEvent, type NativeProseViewerAtomAttrsUpdateEvent, } from './NativeProseViewer';
4
4
  export { EditorToolbar, DEFAULT_EDITOR_TOOLBAR_ITEMS, type EditorToolbarProps, type EditorToolbarItem, type EditorToolbarLeafItem, type EditorToolbarGroupChildItem, type EditorToolbarGroupItem, type EditorToolbarGroupPresentation, type EditorToolbarIcon, type EditorToolbarButtonStyle, type EditorToolbarDefaultIconId, type EditorToolbarSFSymbolIcon, type EditorToolbarMaterialIcon, type EditorToolbarCommand, type EditorToolbarHeadingLevel, type EditorToolbarListType, type EditorToolbarItemPlacement, } from './EditorToolbar';
@@ -2,4 +2,4 @@ import { type useRichTextEditorState } from './useRichTextEditorState';
2
2
  import { type useRichTextEditorMentions } from './useRichTextEditorMentions';
3
3
  import { type useRichTextEditorCommands } from './useRichTextEditorCommands';
4
4
  import { type useRichTextEditorEvents } from './useRichTextEditorEvents';
5
- export declare function useRichTextEditorPresentation(context: Pick<ReturnType<typeof useRichTextEditorState>, 'theme' | 'addons' | 'imageLoadingPolicy' | 'androidInputOptions' | 'remoteSelections' | 'atoms' | 'atomState' | 'atomComponents' | 'warnedUnknownAtomTypesRef' | 'atomContentWidth' | 'atomPositions' | 'atomViewport' | 'virtualizeAtoms' | 'nativeAtomViewport' | 'selectedKeys' | 'editable' | 'atomsInteractive' | 'documentHandle' | 'activeState' | 'onRequestLink' | 'onRequestImage' | 'toolbarItemsSerializationCacheRef' | 'toolbarItems' | 'document' | 'toolbarPlacement' | 'showToolbar' | 'containerStyle' | 'style' | 'heightBehavior' | 'autoGrowHeight' | 'pushedUpdate' | 'editorId' | 'registeredToolbarFrames' | 'suppliedFocusPreservingFrames' | 'isFocused' | 'nativeViewRef' | 'refreshFocusPreservingFrames' | 'accessibilityLabel' | 'accessibilityHint' | 'placeholder' | 'autoFocus' | 'autoCapitalize' | 'autoCorrect' | 'keyboardType' | 'allowImageResizing' | 'toolbarFrameOwnerId' | 'onToolbarAction'> & Pick<ReturnType<typeof useRichTextEditorMentions>, 'mentionSuggestionTheme' | 'handleAddonEvent'> & Pick<ReturnType<typeof useRichTextEditorCommands>, 'runAtomAction' | 'updateAtomAttrs' | 'atomOwnerRef' | 'commandToggleMark' | 'commandToggleList' | 'commandToggleHeading' | 'commandToggleBlockquote' | 'commandInsertNode' | 'commandIndentListItem' | 'commandOutdentListItem' | 'openLinkRequest' | 'openImageRequest'> & Pick<ReturnType<typeof useRichTextEditorEvents>, 'handleEditorUpdate' | 'handleEditorError' | 'handleExternalTextCompositionEnd' | 'handleSelectionChange' | 'handleFocusChange' | 'handleContentHeightChange' | 'handleAtomLayout' | 'handleToolbarAction'>): import("react/jsx-runtime").JSX.Element | null;
5
+ export declare function useRichTextEditorPresentation(context: Pick<ReturnType<typeof useRichTextEditorState>, 'theme' | 'addons' | 'imageLoadingPolicy' | 'androidInputOptions' | 'remoteSelections' | 'atoms' | 'atomState' | 'atomComponents' | 'warnedUnknownAtomTypesRef' | 'atomContentWidth' | 'atomPositions' | 'atomViewport' | 'virtualizeAtoms' | 'nativeAtomViewport' | 'selectedKeys' | 'editable' | 'atomsInteractive' | 'documentHandle' | 'activeState' | 'onRequestLink' | 'onRequestImage' | 'toolbarItemsSerializationCacheRef' | 'toolbarItems' | 'document' | 'toolbarPlacement' | 'showToolbar' | 'containerStyle' | 'style' | 'heightBehavior' | 'autoGrowHeight' | 'pushedUpdate' | 'editorId' | 'registeredToolbarFrames' | 'suppliedFocusPreservingFrames' | 'isFocused' | 'nativeViewRef' | 'refreshFocusPreservingFrames' | 'accessibilityLabel' | 'accessibilityHint' | 'placeholder' | 'autoFocus' | 'pasteMode' | 'autoCapitalize' | 'autoCorrect' | 'keyboardType' | 'allowImageResizing' | 'toolbarFrameOwnerId' | 'onToolbarAction'> & Pick<ReturnType<typeof useRichTextEditorMentions>, 'mentionSuggestionTheme' | 'handleAddonEvent'> & Pick<ReturnType<typeof useRichTextEditorCommands>, 'runAtomAction' | 'updateAtomAttrs' | 'atomOwnerRef' | 'commandToggleMark' | 'commandToggleList' | 'commandToggleHeading' | 'commandToggleBlockquote' | 'commandInsertNode' | 'commandIndentListItem' | 'commandOutdentListItem' | 'openLinkRequest' | 'openImageRequest'> & Pick<ReturnType<typeof useRichTextEditorEvents>, 'handleEditorUpdate' | 'handleEditorError' | 'handleExternalTextCompositionEnd' | 'handleSelectionChange' | 'handleFocusChange' | 'handleContentHeightChange' | 'handleAtomLayout' | 'handleToolbarAction'>): import("react/jsx-runtime").JSX.Element | null;
@@ -17,7 +17,7 @@ const EditorToolbar_1 = require("./EditorToolbar");
17
17
  const RichTextEditorSerialization_1 = require("./RichTextEditorSerialization");
18
18
  const RichTextEditorNativeView_1 = require("./RichTextEditorNativeView");
19
19
  function useRichTextEditorPresentation(context) {
20
- const { theme, mentionSuggestionTheme, addons, imageLoadingPolicy, androidInputOptions, remoteSelections, atoms, atomState, atomComponents, warnedUnknownAtomTypesRef, runAtomAction, updateAtomAttrs, atomOwnerRef, atomContentWidth, atomPositions, atomViewport, virtualizeAtoms, nativeAtomViewport, selectedKeys, editable, atomsInteractive, documentHandle, activeState, onRequestLink, onRequestImage, toolbarItemsSerializationCacheRef, toolbarItems, document, toolbarPlacement, showToolbar, containerStyle, style, heightBehavior, autoGrowHeight, pushedUpdate, editorId, registeredToolbarFrames, suppliedFocusPreservingFrames, isFocused, nativeViewRef, refreshFocusPreservingFrames, accessibilityLabel, accessibilityHint, placeholder, autoFocus, autoCapitalize, autoCorrect, keyboardType, allowImageResizing, handleEditorUpdate, handleEditorError, handleExternalTextCompositionEnd, handleSelectionChange, handleFocusChange, handleContentHeightChange, handleAtomLayout, handleToolbarAction, handleAddonEvent, toolbarFrameOwnerId, commandToggleMark, commandToggleList, commandToggleHeading, commandToggleBlockquote, commandInsertNode, commandIndentListItem, commandOutdentListItem, openLinkRequest, openImageRequest, onToolbarAction, } = context;
20
+ const { theme, mentionSuggestionTheme, addons, imageLoadingPolicy, androidInputOptions, remoteSelections, atoms, atomState, atomComponents, warnedUnknownAtomTypesRef, runAtomAction, updateAtomAttrs, atomOwnerRef, atomContentWidth, atomPositions, atomViewport, virtualizeAtoms, nativeAtomViewport, selectedKeys, editable, atomsInteractive, documentHandle, activeState, onRequestLink, onRequestImage, toolbarItemsSerializationCacheRef, toolbarItems, document, toolbarPlacement, showToolbar, containerStyle, style, heightBehavior, autoGrowHeight, pushedUpdate, editorId, registeredToolbarFrames, suppliedFocusPreservingFrames, isFocused, nativeViewRef, refreshFocusPreservingFrames, accessibilityLabel, accessibilityHint, placeholder, autoFocus, pasteMode, autoCapitalize, autoCorrect, keyboardType, allowImageResizing, handleEditorUpdate, handleEditorError, handleExternalTextCompositionEnd, handleSelectionChange, handleFocusChange, handleContentHeightChange, handleAtomLayout, handleToolbarAction, handleAddonEvent, toolbarFrameOwnerId, commandToggleMark, commandToggleList, commandToggleHeading, commandToggleBlockquote, commandInsertNode, commandIndentListItem, commandOutdentListItem, openLinkRequest, openImageRequest, onToolbarAction, } = context;
21
21
  const themeJson = (0, react_1.useMemo)(() => (0, EditorTheme_1.serializeEditorTheme)(theme, mentionSuggestionTheme), [mentionSuggestionTheme, theme]);
22
22
  const addonsJson = (0, RichTextEditorSerialization_1.useSerializedValue)(addons, value => (0, addons_1.serializeNormalizedEditorAddons)(value));
23
23
  const imageLoadingPolicyJson = (0, RichTextEditorSerialization_1.useSerializedValue)(imageLoadingPolicy, value => (0, ImageLoadingPolicy_1.serializeEditorImageLoadingPolicy)(value));
@@ -161,7 +161,7 @@ function useRichTextEditorPresentation(context) {
161
161
  const currentPushedUpdate = pushedUpdate?.editorId === editorId ? pushedUpdate : null;
162
162
  const focusPreservingFrames = [...registeredToolbarFrames, ...suppliedFocusPreservingFrames];
163
163
  const toolbarFrameJson = (0, RichTextEditorSerialization_1.serializeToolbarFrames)(editable && isFocused ? focusPreservingFrames : undefined);
164
- return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [RichTextEditorNativeView_1.styles.container, containerStyle], children: [(0, jsx_runtime_1.jsx)(RichTextEditorNativeView_1.NativeEditorView, { ref: nativeViewRef, style: nativeViewStyle, onLayout: refreshFocusPreservingFrames, accessibilityLabel: accessibilityLabel, accessibilityHint: accessibilityHint, editorId: editorId, placeholder: placeholder, editable: editable, autoFocus: autoFocus, autoCapitalize: autoCapitalize, autoCorrect: autoCorrect, keyboardType: keyboardType, ...(react_native_1.Platform.OS === 'android' ? { androidInputOptionsJson } : {}), showToolbar: showToolbar, toolbarPlacement: toolbarPlacement, heightBehavior: heightBehavior, allowImageResizing: allowImageResizing, imageLoadingPolicyJson: imageLoadingPolicyJson, themeJson: themeJson, addonsJson: addonsJson, atomsJson: atomsJson, toolbarItemsJson: toolbarItemsJson, toolbarFrameJson: toolbarFrameJson, remoteSelectionsJson: remoteSelectionsJson, editorUpdateJson: currentPushedUpdate?.json, editorUpdateResetJson: currentPushedUpdate?.resetJson, editorUpdateEditorId: currentPushedUpdate?.editorId, editorUpdateRevision: currentPushedUpdate?.revision ?? 0, onEditorUpdate: handleEditorUpdate, onEditorError: handleEditorError, onExternalTextCompositionEnd: handleExternalTextCompositionEnd, onSelectionChange: handleSelectionChange, onFocusChange: handleFocusChange, onContentHeightChange: handleContentHeightChange, onAtomLayout: handleAtomLayout, onToolbarAction: handleToolbarAction, onAddonEvent: handleAddonEvent, children: atomChildren }), shouldRenderJsToolbar ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { testID: 'native-editor-js-toolbar', style: [RichTextEditorNativeView_1.styles.inlineToolbar, { marginTop: inlineToolbarMarginTop }], children: (0, jsx_runtime_1.jsx)(EditorToolbar_1.EditorToolbarFrameOwnerProvider, { ownerId: toolbarFrameOwnerId, children: (0, jsx_runtime_1.jsx)(EditorToolbar_1.EditorToolbar, { activeState: activeState, historyState: document.historyState, toolbarItems: toolbarItems, theme: theme?.toolbar, showTopBorder: theme?.toolbar?.showTopBorder ?? false, preserveEditorFocus: false, onToggleMark: commandToggleMark, onToggleListType: (listType) => commandToggleList(listType), onToggleHeading: commandToggleHeading, onToggleBlockquote: commandToggleBlockquote, onInsertNodeType: commandInsertNode, onRunCommand: (command) => {
164
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [RichTextEditorNativeView_1.styles.container, containerStyle], children: [(0, jsx_runtime_1.jsx)(RichTextEditorNativeView_1.NativeEditorView, { ref: nativeViewRef, style: nativeViewStyle, onLayout: refreshFocusPreservingFrames, accessibilityLabel: accessibilityLabel, accessibilityHint: accessibilityHint, editorId: editorId, placeholder: placeholder, editable: editable, autoFocus: autoFocus, pasteMode: pasteMode, autoCapitalize: autoCapitalize, autoCorrect: autoCorrect, keyboardType: keyboardType, ...(react_native_1.Platform.OS === 'android' ? { androidInputOptionsJson } : {}), showToolbar: showToolbar, toolbarPlacement: toolbarPlacement, heightBehavior: heightBehavior, allowImageResizing: allowImageResizing, imageLoadingPolicyJson: imageLoadingPolicyJson, themeJson: themeJson, addonsJson: addonsJson, atomsJson: atomsJson, toolbarItemsJson: toolbarItemsJson, toolbarFrameJson: toolbarFrameJson, remoteSelectionsJson: remoteSelectionsJson, editorUpdateJson: currentPushedUpdate?.json, editorUpdateResetJson: currentPushedUpdate?.resetJson, editorUpdateEditorId: currentPushedUpdate?.editorId, editorUpdateRevision: currentPushedUpdate?.revision ?? 0, onEditorUpdate: handleEditorUpdate, onEditorError: handleEditorError, onExternalTextCompositionEnd: handleExternalTextCompositionEnd, onSelectionChange: handleSelectionChange, onFocusChange: handleFocusChange, onContentHeightChange: handleContentHeightChange, onAtomLayout: handleAtomLayout, onToolbarAction: handleToolbarAction, onAddonEvent: handleAddonEvent, children: atomChildren }), shouldRenderJsToolbar ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { testID: 'native-editor-js-toolbar', style: [RichTextEditorNativeView_1.styles.inlineToolbar, { marginTop: inlineToolbarMarginTop }], children: (0, jsx_runtime_1.jsx)(EditorToolbar_1.EditorToolbarFrameOwnerProvider, { ownerId: toolbarFrameOwnerId, children: (0, jsx_runtime_1.jsx)(EditorToolbar_1.EditorToolbar, { activeState: activeState, historyState: document.historyState, toolbarItems: toolbarItems, theme: theme?.toolbar, showTopBorder: theme?.toolbar?.showTopBorder ?? false, preserveEditorFocus: false, onToggleMark: commandToggleMark, onToggleListType: (listType) => commandToggleList(listType), onToggleHeading: commandToggleHeading, onToggleBlockquote: commandToggleBlockquote, onInsertNodeType: commandInsertNode, onRunCommand: (command) => {
165
165
  switch (command) {
166
166
  case 'indentList':
167
167
  commandIndentListItem();
@@ -1,3 +1,4 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
1
2
  import { type EditorToolbarItem } from './EditorToolbar';
2
3
  import type React from 'react';
3
4
  import { type ReadonlyActiveState, type Selection } from './NativeEditorBridge';
@@ -8,7 +9,7 @@ import { type AtomViewport } from './AtomHost';
8
9
  import { type RichTextEditorProps, type RichTextEditorRef } from './RichTextEditorTypes';
9
10
  import { type AtomRenderState } from './RichTextEditorSerialization';
10
11
  import { type NativeEditorViewHandle, type NativeEditorErrorBinding, type NativeAtomPosition } from './RichTextEditorNativeTypes';
11
- export declare function useRichTextEditorState({ documentHandle, documentRevision, value, valueJSON, valueJSONRevision, valueJSONUpdateMode, placeholder, editable, autoFocus, autoCapitalize, autoCorrect, keyboardType, androidInputOptions, heightBehavior, showToolbar, toolbarPlacement, toolbarItems, onToolbarAction, onRequestLink, onRequestImage, imageLoadingPolicy, accessibilityLabel, accessibilityHint, style, containerStyle, theme, addons: addonDescriptors, atoms, atomsInteractive, virtualizeAtoms, atomViewport, remoteSelections, allowImageResizing, onContentChange, onContentChangeJSON, onSelectionChange, onActiveStateChange, onHistoryStateChange, onFocus, onBlur, focusPreservingRefs, onLocalCommit, }: RichTextEditorProps, ref: React.ForwardedRef<RichTextEditorRef>): {
12
+ export declare function useRichTextEditorState({ documentHandle, documentRevision, value, valueJSON, valueJSONRevision, valueJSONUpdateMode, placeholder, editable, pasteMode, autoFocus, autoCapitalize, autoCorrect, keyboardType, androidInputOptions, heightBehavior, showToolbar, toolbarPlacement, toolbarItems, onToolbarAction, onRequestLink, onRequestImage, imageLoadingPolicy, accessibilityLabel, accessibilityHint, style, containerStyle, theme, addons: addonDescriptors, atoms, atomsInteractive, virtualizeAtoms, atomViewport, remoteSelections, allowImageResizing, onContentChange, onContentChangeJSON, onSelectionChange, onActiveStateChange, onHistoryStateChange, onFocus, onBlur, focusPreservingRefs, onLocalCommit, }: RichTextEditorProps, ref: React.ForwardedRef<RichTextEditorRef>): {
12
13
  atomStateRef: React.RefObject<AtomRenderState>;
13
14
  setSelectedKeys: React.Dispatch<React.SetStateAction<ReadonlySet<string>>>;
14
15
  bridge: import("./NativeEditorDocumentBridge").NativeEditorDocumentBridge;
@@ -156,8 +157,8 @@ export declare function useRichTextEditorState({ documentHandle, documentRevisio
156
157
  toolbarItems: readonly EditorToolbarItem[];
157
158
  toolbarPlacement: import("./RichTextEditorTypes").RichTextEditorToolbarPlacement;
158
159
  showToolbar: boolean;
159
- containerStyle: import("react-native").StyleProp<import("react-native").ViewStyle>;
160
- style: import("react-native").StyleProp<import("react-native").ViewStyle>;
160
+ containerStyle: StyleProp<ViewStyle>;
161
+ style: StyleProp<ViewStyle>;
161
162
  autoGrowHeight: number | null;
162
163
  pushedUpdate: {
163
164
  json: string;
@@ -172,6 +173,7 @@ export declare function useRichTextEditorState({ documentHandle, documentRevisio
172
173
  accessibilityHint: string | undefined;
173
174
  placeholder: string | undefined;
174
175
  autoFocus: boolean;
176
+ pasteMode: import("./RichTextEditorTypes").RichTextEditorPasteMode;
175
177
  autoCapitalize: import("./RichTextEditorTypes").RichTextEditorAutoCapitalize | undefined;
176
178
  autoCorrect: boolean | undefined;
177
179
  keyboardType: import("./RichTextEditorTypes").RichTextEditorKeyboardType | undefined;
@@ -10,7 +10,7 @@ const useNativeEditor_1 = require("./useNativeEditor");
10
10
  const addons_1 = require("./addons");
11
11
  const useFocusPreservingFrames_1 = require("./useFocusPreservingFrames");
12
12
  const RichTextEditorSerialization_1 = require("./RichTextEditorSerialization");
13
- function useRichTextEditorState({ documentHandle, documentRevision, value, valueJSON, valueJSONRevision, valueJSONUpdateMode = 'replace', placeholder, editable = true, autoFocus = false, autoCapitalize, autoCorrect, keyboardType, androidInputOptions, heightBehavior = 'autoGrow', showToolbar = true, toolbarPlacement = 'keyboard', toolbarItems = EditorToolbar_1.DEFAULT_EDITOR_TOOLBAR_ITEMS, onToolbarAction, onRequestLink, onRequestImage, imageLoadingPolicy, accessibilityLabel, accessibilityHint, style, containerStyle, theme, addons: addonDescriptors, atoms, atomsInteractive = true, virtualizeAtoms = false, atomViewport, remoteSelections, allowImageResizing = true, onContentChange, onContentChangeJSON, onSelectionChange, onActiveStateChange, onHistoryStateChange, onFocus, onBlur, focusPreservingRefs, onLocalCommit, }, ref) {
13
+ function useRichTextEditorState({ documentHandle, documentRevision, value, valueJSON, valueJSONRevision, valueJSONUpdateMode = 'replace', placeholder, editable = true, pasteMode = 'rich', autoFocus = false, autoCapitalize, autoCorrect, keyboardType, androidInputOptions, heightBehavior = 'autoGrow', showToolbar = true, toolbarPlacement = 'keyboard', toolbarItems = EditorToolbar_1.DEFAULT_EDITOR_TOOLBAR_ITEMS, onToolbarAction, onRequestLink, onRequestImage, imageLoadingPolicy, accessibilityLabel, accessibilityHint, style, containerStyle, theme, addons: addonDescriptors, atoms, atomsInteractive = true, virtualizeAtoms = false, atomViewport, remoteSelections, allowImageResizing = true, onContentChange, onContentChangeJSON, onSelectionChange, onActiveStateChange, onHistoryStateChange, onFocus, onBlur, focusPreservingRefs, onLocalCommit, }, ref) {
14
14
  const addons = (0, react_1.useMemo)(() => (0, addons_1.normalizeEditorAddons)(addonDescriptors), [addonDescriptors]);
15
15
  (0, NativeEditorBridge_1._assertNativeEditorDocumentHandle)(documentHandle);
16
16
  const documentDescriptor = (0, NativeEditorBridge_1._getNativeEditorDocumentHandleDescriptor)(documentHandle);
@@ -390,8 +390,8 @@ function useRichTextEditorState({ documentHandle, documentRevision, value, value
390
390
  toolbarItems,
391
391
  toolbarPlacement,
392
392
  showToolbar,
393
- containerStyle,
394
- style,
393
+ containerStyle: containerStyle,
394
+ style: style,
395
395
  autoGrowHeight,
396
396
  pushedUpdate,
397
397
  registeredToolbarFrames,
@@ -401,6 +401,7 @@ function useRichTextEditorState({ documentHandle, documentRevision, value, value
401
401
  accessibilityHint,
402
402
  placeholder,
403
403
  autoFocus,
404
+ pasteMode,
404
405
  autoCapitalize,
405
406
  autoCorrect,
406
407
  keyboardType,