@apollohg/react-native-prose-editor 0.1.1 → 0.3.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.
Files changed (53) hide show
  1. package/README.md +12 -7
  2. package/android/build.gradle +7 -2
  3. package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +289 -2
  4. package/android/src/main/java/com/apollohg/editor/EditorTheme.kt +51 -1
  5. package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +199 -0
  6. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +16 -3
  7. package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +82 -1
  8. package/android/src/main/java/com/apollohg/editor/NativeToolbar.kt +403 -45
  9. package/android/src/main/java/com/apollohg/editor/RemoteSelectionOverlayView.kt +246 -0
  10. package/android/src/main/java/com/apollohg/editor/RenderBridge.kt +841 -155
  11. package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +125 -8
  12. package/{src/EditorTheme.ts → dist/EditorTheme.d.ts} +12 -52
  13. package/dist/EditorTheme.js +29 -0
  14. package/dist/EditorToolbar.d.ts +129 -0
  15. package/dist/EditorToolbar.js +394 -0
  16. package/dist/NativeEditorBridge.d.ts +242 -0
  17. package/dist/NativeEditorBridge.js +647 -0
  18. package/dist/NativeRichTextEditor.d.ts +142 -0
  19. package/dist/NativeRichTextEditor.js +649 -0
  20. package/dist/YjsCollaboration.d.ts +83 -0
  21. package/dist/YjsCollaboration.js +585 -0
  22. package/dist/addons.d.ts +70 -0
  23. package/dist/addons.js +77 -0
  24. package/dist/index.d.ts +8 -0
  25. package/dist/index.js +26 -0
  26. package/dist/schemas.d.ts +35 -0
  27. package/{src/schemas.ts → dist/schemas.js} +62 -27
  28. package/dist/useNativeEditor.d.ts +40 -0
  29. package/dist/useNativeEditor.js +117 -0
  30. package/ios/EditorAddons.swift +26 -3
  31. package/ios/EditorCore.xcframework/Info.plist +5 -5
  32. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  33. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  34. package/ios/EditorLayoutManager.swift +236 -0
  35. package/ios/EditorTheme.swift +51 -1
  36. package/ios/Generated_editor_core.swift +270 -2
  37. package/ios/NativeEditorExpoView.swift +612 -45
  38. package/ios/NativeEditorModule.swift +81 -0
  39. package/ios/PositionBridge.swift +22 -0
  40. package/ios/RenderBridge.swift +427 -39
  41. package/ios/RichTextEditorView.swift +1342 -18
  42. package/ios/editor_coreFFI/editor_coreFFI.h +209 -0
  43. package/package.json +80 -64
  44. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  45. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  46. package/rust/android/x86_64/libeditor_core.so +0 -0
  47. package/rust/bindings/kotlin/uniffi/editor_core/editor_core.kt +404 -4
  48. package/src/EditorToolbar.tsx +0 -620
  49. package/src/NativeEditorBridge.ts +0 -607
  50. package/src/NativeRichTextEditor.tsx +0 -951
  51. package/src/addons.ts +0 -158
  52. package/src/index.ts +0 -63
  53. package/src/useNativeEditor.ts +0 -173
@@ -2,6 +2,7 @@ package com.apollohg.editor
2
2
 
3
3
  import android.content.Context
4
4
  import android.graphics.Color
5
+ import android.graphics.RectF
5
6
  import android.graphics.drawable.GradientDrawable
6
7
  import android.util.AttributeSet
7
8
  import android.view.MotionEvent
@@ -17,6 +18,7 @@ class RichTextEditorView @JvmOverloads constructor(
17
18
  attrs: AttributeSet? = null,
18
19
  defStyleAttr: Int = 0
19
20
  ) : LinearLayout(context, attrs, defStyleAttr) {
21
+ val editorViewport: FrameLayout
20
22
 
21
23
  private class EditorScrollView(context: Context) : ScrollView(context) {
22
24
  private fun updateParentIntercept(action: Int) {
@@ -43,8 +45,11 @@ class RichTextEditorView @JvmOverloads constructor(
43
45
 
44
46
  val editorEditText: EditorEditText
45
47
  val editorScrollView: ScrollView
48
+ private val remoteSelectionOverlayView: RemoteSelectionOverlayView
49
+ private val imageResizeOverlayView: ImageResizeOverlayView
46
50
 
47
51
  private var heightBehavior: EditorHeightBehavior = EditorHeightBehavior.FIXED
52
+ private var imageResizingEnabled = true
48
53
  private var theme: EditorTheme? = null
49
54
  private var baseBackgroundColor: Int = Color.WHITE
50
55
  private var viewportBottomInsetPx: Int = 0
@@ -59,6 +64,7 @@ class RichTextEditorView @JvmOverloads constructor(
59
64
  } else {
60
65
  editorEditText.unbindEditor()
61
66
  }
67
+ refreshOverlays()
62
68
  }
63
69
 
64
70
  init {
@@ -69,9 +75,39 @@ class RichTextEditorView @JvmOverloads constructor(
69
75
  clipToPadding = false
70
76
  isFillViewport = false
71
77
  }
78
+ editorViewport = FrameLayout(context)
79
+ remoteSelectionOverlayView = RemoteSelectionOverlayView(context)
80
+ imageResizeOverlayView = ImageResizeOverlayView(context)
72
81
  editorScrollView.addView(editorEditText, createEditorLayoutParams())
82
+ editorViewport.addView(
83
+ editorScrollView,
84
+ FrameLayout.LayoutParams(
85
+ ViewGroup.LayoutParams.MATCH_PARENT,
86
+ ViewGroup.LayoutParams.MATCH_PARENT
87
+ )
88
+ )
89
+ editorViewport.addView(
90
+ remoteSelectionOverlayView,
91
+ FrameLayout.LayoutParams(
92
+ ViewGroup.LayoutParams.MATCH_PARENT,
93
+ ViewGroup.LayoutParams.MATCH_PARENT
94
+ )
95
+ )
96
+ editorViewport.addView(
97
+ imageResizeOverlayView,
98
+ FrameLayout.LayoutParams(
99
+ ViewGroup.LayoutParams.MATCH_PARENT,
100
+ ViewGroup.LayoutParams.MATCH_PARENT
101
+ )
102
+ )
103
+ remoteSelectionOverlayView.bind(this)
104
+ imageResizeOverlayView.bind(this)
105
+ editorScrollView.setOnScrollChangeListener { _, _, _, _, _ ->
106
+ refreshOverlays()
107
+ }
108
+ editorEditText.onSelectionOrContentMayChange = { refreshOverlays() }
73
109
 
74
- addView(editorScrollView, createContainerLayoutParams())
110
+ addView(editorViewport, createContainerLayoutParams())
75
111
  updateScrollContainerAppearance()
76
112
  updateScrollContainerInsets()
77
113
  }
@@ -84,6 +120,7 @@ class RichTextEditorView @JvmOverloads constructor(
84
120
  baseBackgroundColor = backgroundColor
85
121
  editorEditText.setBaseStyle(textSizePx, textColor, backgroundColor)
86
122
  updateScrollContainerAppearance()
123
+ refreshOverlays()
87
124
  }
88
125
 
89
126
  fun applyTheme(theme: EditorTheme?) {
@@ -100,8 +137,10 @@ class RichTextEditorView @JvmOverloads constructor(
100
137
  childHeight + editorScrollView.paddingTop + editorScrollView.paddingBottom - editorScrollView.height
101
138
  )
102
139
  editorScrollView.scrollTo(0, previousScrollY.coerceIn(0, maxScrollY))
140
+ refreshOverlays()
103
141
  }
104
142
  }
143
+ refreshOverlays()
105
144
  }
106
145
 
107
146
  fun setHeightBehavior(heightBehavior: EditorHeightBehavior) {
@@ -109,7 +148,7 @@ class RichTextEditorView @JvmOverloads constructor(
109
148
  this.heightBehavior = heightBehavior
110
149
  editorEditText.setHeightBehavior(heightBehavior)
111
150
  editorEditText.layoutParams = createEditorLayoutParams()
112
- editorScrollView.layoutParams = createContainerLayoutParams()
151
+ editorViewport.layoutParams = createContainerLayoutParams()
113
152
  editorScrollView.isVerticalScrollBarEnabled = heightBehavior == EditorHeightBehavior.FIXED
114
153
  editorScrollView.overScrollMode = if (heightBehavior == EditorHeightBehavior.FIXED) {
115
154
  OVER_SCROLL_IF_CONTENT_SCROLLS
@@ -117,18 +156,53 @@ class RichTextEditorView @JvmOverloads constructor(
117
156
  OVER_SCROLL_NEVER
118
157
  }
119
158
  updateScrollContainerInsets()
159
+ refreshOverlays()
120
160
  requestLayout()
121
161
  }
122
162
 
163
+ fun setImageResizingEnabled(enabled: Boolean) {
164
+ if (imageResizingEnabled == enabled) return
165
+ imageResizingEnabled = enabled
166
+ editorEditText.setImageResizingEnabled(enabled)
167
+ refreshOverlays()
168
+ }
169
+
123
170
  fun setViewportBottomInsetPx(bottomInsetPx: Int) {
124
171
  val clampedInset = bottomInsetPx.coerceAtLeast(0)
125
172
  if (viewportBottomInsetPx == clampedInset) return
126
173
  viewportBottomInsetPx = clampedInset
127
174
  updateScrollContainerInsets()
128
175
  editorEditText.setViewportBottomInsetPx(clampedInset)
176
+ refreshOverlays()
129
177
  requestLayout()
130
178
  }
131
179
 
180
+ fun setRemoteSelections(selections: List<RemoteSelectionDecoration>) {
181
+ remoteSelectionOverlayView.setRemoteSelections(selections)
182
+ }
183
+
184
+ fun refreshRemoteSelections() {
185
+ remoteSelectionOverlayView.invalidate()
186
+ }
187
+
188
+ fun imageResizeOverlayRectForTesting(): android.graphics.RectF? =
189
+ imageResizeOverlayView.visibleRectForTesting()
190
+
191
+ fun resizeSelectedImageForTesting(widthPx: Float, heightPx: Float) {
192
+ imageResizeOverlayView.simulateResizeForTesting(widthPx, heightPx)
193
+ }
194
+
195
+ fun remoteSelectionDebugSnapshotsForTesting(): List<RemoteSelectionDebugSnapshot> =
196
+ remoteSelectionOverlayView.debugSnapshotsForTesting()
197
+
198
+ fun setRemoteSelectionScalarResolverForTesting(resolver: (Long, Int) -> Int) {
199
+ remoteSelectionOverlayView.docToScalarResolver = resolver
200
+ }
201
+
202
+ fun setRemoteSelectionEditorIdForTesting(editorId: Long) {
203
+ remoteSelectionOverlayView.editorIdOverrideForTesting = editorId
204
+ }
205
+
132
206
  fun setContent(html: String) {
133
207
  if (editorId == 0L) return
134
208
  val renderJSON = editorSetHtml(editorId.toULong(), html)
@@ -157,16 +231,16 @@ class RichTextEditorView @JvmOverloads constructor(
157
231
  val childWidthSpec = getChildMeasureSpec(
158
232
  widthMeasureSpec,
159
233
  paddingLeft + paddingRight,
160
- editorScrollView.layoutParams.width
234
+ editorViewport.layoutParams.width
161
235
  )
162
236
  val childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
163
- editorScrollView.measure(childWidthSpec, childHeightSpec)
237
+ editorViewport.measure(childWidthSpec, childHeightSpec)
164
238
 
165
239
  val measuredWidth = resolveSize(
166
- editorScrollView.measuredWidth + paddingLeft + paddingRight,
240
+ editorViewport.measuredWidth + paddingLeft + paddingRight,
167
241
  widthMeasureSpec
168
242
  )
169
- val desiredHeight = editorScrollView.measuredHeight + paddingTop + paddingBottom
243
+ val desiredHeight = editorViewport.measuredHeight + paddingTop + paddingBottom
170
244
  val measuredHeight = when (MeasureSpec.getMode(heightMeasureSpec)) {
171
245
  MeasureSpec.AT_MOST -> desiredHeight.coerceAtMost(MeasureSpec.getSize(heightMeasureSpec))
172
246
  else -> desiredHeight
@@ -176,11 +250,12 @@ class RichTextEditorView @JvmOverloads constructor(
176
250
 
177
251
  private fun updateScrollContainerAppearance() {
178
252
  val cornerRadiusPx = (theme?.borderRadius ?: 0f) * resources.displayMetrics.density
179
- editorScrollView.background = GradientDrawable().apply {
253
+ editorViewport.background = GradientDrawable().apply {
180
254
  cornerRadius = cornerRadiusPx
181
255
  setColor(theme?.backgroundColor ?: baseBackgroundColor)
182
256
  }
183
- editorScrollView.clipToOutline = cornerRadiusPx > 0f
257
+ editorViewport.clipToOutline = cornerRadiusPx > 0f
258
+ editorScrollView.setBackgroundColor(Color.TRANSPARENT)
184
259
  appliedCornerRadiusPx = cornerRadiusPx
185
260
  }
186
261
 
@@ -208,4 +283,46 @@ class RichTextEditorView @JvmOverloads constructor(
208
283
  ViewGroup.LayoutParams.MATCH_PARENT,
209
284
  ViewGroup.LayoutParams.WRAP_CONTENT
210
285
  )
286
+
287
+ internal fun selectedImageGeometry(): EditorEditText.SelectedImageGeometry? {
288
+ val geometry = editorEditText.selectedImageGeometry() ?: return null
289
+ return EditorEditText.SelectedImageGeometry(
290
+ docPos = geometry.docPos,
291
+ rect = RectF(
292
+ editorViewport.left + editorScrollView.left + editorEditText.left + geometry.rect.left,
293
+ editorViewport.top + editorScrollView.top + editorEditText.top + geometry.rect.top - editorScrollView.scrollY,
294
+ editorViewport.left + editorScrollView.left + editorEditText.left + geometry.rect.right,
295
+ editorViewport.top + editorScrollView.top + editorEditText.top + geometry.rect.bottom - editorScrollView.scrollY
296
+ )
297
+ )
298
+ }
299
+
300
+ internal fun maximumImageWidthPx(): Float {
301
+ val availableWidth =
302
+ maxOf(editorEditText.width, editorEditText.measuredWidth) -
303
+ editorEditText.compoundPaddingLeft -
304
+ editorEditText.compoundPaddingRight
305
+ return availableWidth.coerceAtLeast(48).toFloat()
306
+ }
307
+
308
+ internal fun clampImageSize(
309
+ widthPx: Float,
310
+ heightPx: Float,
311
+ maximumWidthPx: Float = maximumImageWidthPx()
312
+ ): Pair<Float, Float> {
313
+ val aspectRatio = maxOf(widthPx / maxOf(heightPx, 1f), 0.1f)
314
+ val clampedWidth = minOf(maxOf(48f, maximumWidthPx), maxOf(48f, widthPx))
315
+ val clampedHeight = maxOf(48f, clampedWidth / aspectRatio)
316
+ return clampedWidth to clampedHeight
317
+ }
318
+
319
+ internal fun resizeImage(docPos: Int, widthPx: Float, heightPx: Float) {
320
+ val (clampedWidth, clampedHeight) = clampImageSize(widthPx, heightPx)
321
+ editorEditText.resizeImageAtDocPos(docPos, clampedWidth, clampedHeight)
322
+ }
323
+
324
+ private fun refreshOverlays() {
325
+ remoteSelectionOverlayView.invalidate()
326
+ imageResizeOverlayView.refresh()
327
+ }
211
328
  }
@@ -1,18 +1,5 @@
1
- export type EditorFontWeight =
2
- | 'normal'
3
- | 'bold'
4
- | '100'
5
- | '200'
6
- | '300'
7
- | '400'
8
- | '500'
9
- | '600'
10
- | '700'
11
- | '800'
12
- | '900';
13
-
1
+ export type EditorFontWeight = 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
14
2
  export type EditorFontStyle = 'normal' | 'italic';
15
-
16
3
  export interface EditorMentionTheme {
17
4
  textColor?: string;
18
5
  backgroundColor?: string;
@@ -30,7 +17,6 @@ export interface EditorMentionTheme {
30
17
  optionHighlightedBackgroundColor?: string;
31
18
  optionHighlightedTextColor?: string;
32
19
  }
33
-
34
20
  export interface EditorTextStyle {
35
21
  fontFamily?: string;
36
22
  fontSize?: number;
@@ -40,7 +26,6 @@ export interface EditorTextStyle {
40
26
  lineHeight?: number;
41
27
  spacingAfter?: number;
42
28
  }
43
-
44
29
  export interface EditorHeadingTheme {
45
30
  h1?: EditorTextStyle;
46
31
  h2?: EditorTextStyle;
@@ -49,21 +34,27 @@ export interface EditorHeadingTheme {
49
34
  h5?: EditorTextStyle;
50
35
  h6?: EditorTextStyle;
51
36
  }
52
-
53
37
  export interface EditorListTheme {
54
38
  indent?: number;
55
39
  itemSpacing?: number;
56
40
  markerColor?: string;
57
41
  markerScale?: number;
58
42
  }
59
-
60
43
  export interface EditorHorizontalRuleTheme {
61
44
  color?: string;
62
45
  thickness?: number;
63
46
  verticalMargin?: number;
64
47
  }
65
-
48
+ export interface EditorBlockquoteTheme {
49
+ text?: EditorTextStyle;
50
+ indent?: number;
51
+ borderColor?: string;
52
+ borderWidth?: number;
53
+ markerGap?: number;
54
+ }
55
+ export type EditorToolbarAppearance = 'custom' | 'native';
66
56
  export interface EditorToolbarTheme {
57
+ appearance?: EditorToolbarAppearance;
67
58
  backgroundColor?: string;
68
59
  borderColor?: string;
69
60
  borderWidth?: number;
@@ -77,17 +68,16 @@ export interface EditorToolbarTheme {
77
68
  buttonActiveBackgroundColor?: string;
78
69
  buttonBorderRadius?: number;
79
70
  }
80
-
81
71
  export interface EditorContentInsets {
82
72
  top?: number;
83
73
  right?: number;
84
74
  bottom?: number;
85
75
  left?: number;
86
76
  }
87
-
88
77
  export interface EditorTheme {
89
78
  text?: EditorTextStyle;
90
79
  paragraph?: EditorTextStyle;
80
+ blockquote?: EditorBlockquoteTheme;
91
81
  headings?: EditorHeadingTheme;
92
82
  list?: EditorListTheme;
93
83
  horizontalRule?: EditorHorizontalRuleTheme;
@@ -97,34 +87,4 @@ export interface EditorTheme {
97
87
  borderRadius?: number;
98
88
  contentInsets?: EditorContentInsets;
99
89
  }
100
-
101
- function stripUndefined(value: unknown): unknown {
102
- if (Array.isArray(value)) {
103
- return value
104
- .map((item) => stripUndefined(item))
105
- .filter((item) => item !== undefined);
106
- }
107
-
108
- if (value != null && typeof value === 'object') {
109
- const entries = Object.entries(value as Record<string, unknown>)
110
- .map(([key, entryValue]) => [key, stripUndefined(entryValue)] as const)
111
- .filter(([, entryValue]) => entryValue !== undefined);
112
- if (entries.length === 0) {
113
- return undefined;
114
- }
115
- return Object.fromEntries(entries);
116
- }
117
-
118
- if (typeof value === 'number' && !Number.isFinite(value)) {
119
- return undefined;
120
- }
121
-
122
- return value;
123
- }
124
-
125
- export function serializeEditorTheme(theme?: EditorTheme): string | undefined {
126
- if (!theme) return undefined;
127
- const cleaned = stripUndefined(theme);
128
- if (!cleaned || typeof cleaned !== 'object') return undefined;
129
- return JSON.stringify(cleaned);
130
- }
90
+ export declare function serializeEditorTheme(theme?: EditorTheme): string | undefined;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serializeEditorTheme = serializeEditorTheme;
4
+ function stripUndefined(value) {
5
+ if (Array.isArray(value)) {
6
+ return value.map((item) => stripUndefined(item)).filter((item) => item !== undefined);
7
+ }
8
+ if (value != null && typeof value === 'object') {
9
+ const entries = Object.entries(value)
10
+ .map(([key, entryValue]) => [key, stripUndefined(entryValue)])
11
+ .filter(([, entryValue]) => entryValue !== undefined);
12
+ if (entries.length === 0) {
13
+ return undefined;
14
+ }
15
+ return Object.fromEntries(entries);
16
+ }
17
+ if (typeof value === 'number' && !Number.isFinite(value)) {
18
+ return undefined;
19
+ }
20
+ return value;
21
+ }
22
+ function serializeEditorTheme(theme) {
23
+ if (!theme)
24
+ return undefined;
25
+ const cleaned = stripUndefined(theme);
26
+ if (!cleaned || typeof cleaned !== 'object')
27
+ return undefined;
28
+ return JSON.stringify(cleaned);
29
+ }
@@ -0,0 +1,129 @@
1
+ import type { ActiveState, HistoryState } from './NativeEditorBridge';
2
+ import type { EditorToolbarTheme } from './EditorTheme';
3
+ export type EditorToolbarListType = 'bulletList' | 'orderedList';
4
+ export type EditorToolbarCommand = 'indentList' | 'outdentList' | 'undo' | 'redo';
5
+ export type EditorToolbarDefaultIconId = 'bold' | 'italic' | 'underline' | 'strike' | 'link' | 'image' | 'blockquote' | 'bulletList' | 'orderedList' | 'indentList' | 'outdentList' | 'lineBreak' | 'horizontalRule' | 'undo' | 'redo';
6
+ export interface EditorToolbarSFSymbolIcon {
7
+ type: 'sfSymbol';
8
+ name: string;
9
+ }
10
+ export interface EditorToolbarMaterialIcon {
11
+ type: 'material';
12
+ name: string;
13
+ }
14
+ export type EditorToolbarIcon = {
15
+ type: 'default';
16
+ id: EditorToolbarDefaultIconId;
17
+ } | {
18
+ type: 'glyph';
19
+ text: string;
20
+ } | {
21
+ type: 'platform';
22
+ ios?: EditorToolbarSFSymbolIcon;
23
+ android?: EditorToolbarMaterialIcon;
24
+ fallbackText?: string;
25
+ };
26
+ export type EditorToolbarItem = {
27
+ type: 'mark';
28
+ mark: string;
29
+ label: string;
30
+ icon: EditorToolbarIcon;
31
+ key?: string;
32
+ } | {
33
+ type: 'link';
34
+ label: string;
35
+ icon: EditorToolbarIcon;
36
+ key?: string;
37
+ } | {
38
+ type: 'image';
39
+ label: string;
40
+ icon: EditorToolbarIcon;
41
+ key?: string;
42
+ } | {
43
+ type: 'blockquote';
44
+ label: string;
45
+ icon: EditorToolbarIcon;
46
+ key?: string;
47
+ } | {
48
+ type: 'list';
49
+ listType: EditorToolbarListType;
50
+ label: string;
51
+ icon: EditorToolbarIcon;
52
+ key?: string;
53
+ } | {
54
+ type: 'command';
55
+ command: EditorToolbarCommand;
56
+ label: string;
57
+ icon: EditorToolbarIcon;
58
+ key?: string;
59
+ } | {
60
+ type: 'node';
61
+ nodeType: string;
62
+ label: string;
63
+ icon: EditorToolbarIcon;
64
+ key?: string;
65
+ } | {
66
+ type: 'separator';
67
+ key?: string;
68
+ } | {
69
+ type: 'action';
70
+ key: string;
71
+ label: string;
72
+ icon: EditorToolbarIcon;
73
+ isActive?: boolean;
74
+ isDisabled?: boolean;
75
+ };
76
+ export declare const DEFAULT_EDITOR_TOOLBAR_ITEMS: readonly EditorToolbarItem[];
77
+ export interface EditorToolbarProps {
78
+ /** Currently active marks and nodes from the Rust engine. */
79
+ activeState: ActiveState;
80
+ /** Current undo/redo availability. */
81
+ historyState: HistoryState;
82
+ /** Toggle bold mark. */
83
+ onToggleBold: () => void;
84
+ /** Toggle italic mark. */
85
+ onToggleItalic: () => void;
86
+ /** Toggle underline mark. */
87
+ onToggleUnderline: () => void;
88
+ /** Toggle strikethrough mark. */
89
+ onToggleStrike: () => void;
90
+ /** Toggle bullet list. */
91
+ onToggleBulletList?: () => void;
92
+ /** Toggle blockquote wrapping. */
93
+ onToggleBlockquote?: () => void;
94
+ /** Toggle ordered list. */
95
+ onToggleOrderedList?: () => void;
96
+ /** Indent the current list item. */
97
+ onIndentList?: () => void;
98
+ /** Outdent the current list item. */
99
+ onOutdentList?: () => void;
100
+ /** Insert horizontal rule. */
101
+ onInsertHorizontalRule?: () => void;
102
+ /** Insert inline hard break. */
103
+ onInsertLineBreak?: () => void;
104
+ /** Undo the last operation. */
105
+ onUndo: () => void;
106
+ /** Redo the last undone operation. */
107
+ onRedo: () => void;
108
+ /** Generic mark toggle handler used by configurable mark buttons. */
109
+ onToggleMark?: (mark: string) => void;
110
+ /** Generic list toggle handler used by configurable list buttons. */
111
+ onToggleListType?: (listType: EditorToolbarListType) => void;
112
+ /** Generic node insertion handler used by configurable node buttons. */
113
+ onInsertNodeType?: (nodeType: string) => void;
114
+ /** Generic command handler used by configurable command buttons. */
115
+ onRunCommand?: (command: EditorToolbarCommand) => void;
116
+ /** Generic action handler for arbitrary JS-defined toolbar buttons. */
117
+ onToolbarAction?: (key: string) => void;
118
+ /** Link button handler used by first-class link toolbar items. */
119
+ onRequestLink?: () => void;
120
+ /** Image button handler used by first-class image toolbar items. */
121
+ onRequestImage?: () => void;
122
+ /** Displayed toolbar items, in order. Defaults to the built-in toolbar. */
123
+ toolbarItems?: readonly EditorToolbarItem[];
124
+ /** Optional theme overrides for toolbar chrome and button colors. */
125
+ theme?: EditorToolbarTheme;
126
+ /** Whether to render the built-in top separator line. */
127
+ showTopBorder?: boolean;
128
+ }
129
+ export declare function EditorToolbar({ activeState, historyState, onToggleBold, onToggleItalic, onToggleUnderline, onToggleStrike, onToggleBulletList, onToggleBlockquote, onToggleOrderedList, onIndentList, onOutdentList, onInsertHorizontalRule, onInsertLineBreak, onUndo, onRedo, onToggleMark, onToggleListType, onInsertNodeType, onRunCommand, onToolbarAction, onRequestLink, onRequestImage, toolbarItems, theme, showTopBorder, }: EditorToolbarProps): import("react/jsx-runtime").JSX.Element;