Tiptap.res
1// src/ffi/Tiptap.res
2// FFI bindings for TipTap Editor (@tiptap/core)
3
4// Import the extensions array from JavaScript
5// Extensions are opaque - configured once in TiptapExtensions.js
6@module("./extensions.js") external extensions: (Y.Doc.t, string) => array<unknown> = "extensions"
7
8// Opaque type for the Editor instance
9type t
10
11// Range type for insertContentAt with range
12// Uses object syntax for JavaScript interop
13type range = {"from": int, "to": int}
14
15// Callback types for lifecycle events
16type editorCallback = t => unit
17// Transaction callback receives an object with editor and transaction properties
18// Transaction type is opaque - use unknown if you need to access it
19type editorTransactionCallback = {"editor": t, "transaction": unknown} => unit
20
21// Axis values for scrollThreshold and scrollMargin
22// Single number or per-axis object
23type scrollAxes = {
24 top?: int,
25 bottom?: int,
26 left?: int,
27 right?: int,
28}
29
30// Editor options type
31// Note: autofocus uses boolean only (simplified from string/boolean/number/null)
32// Content uses JSON.t directly from stdlib for interoperability
33type editorOptions = {
34 editorProps?: {
35 attributes: {class: string},
36 scrollThreshold?: scrollAxes,
37 scrollMargin?: scrollAxes,
38 },
39 element?: nullable<Dom.element>,
40 extensions: array<unknown>,
41 content?: JSON.t,
42 editable?: bool,
43 autofocus?: bool,
44 enableInputRules?: bool,
45 enablePasteRules?: bool,
46 injectCSS?: bool,
47 // Callbacks
48 onCreate?: editorCallback,
49 onUpdate?: editorCallback,
50 onSelectionUpdate?: editorCallback,
51 onTransaction?: editorTransactionCallback,
52 onFocus?: editorCallback,
53 onBlur?: editorCallback,
54 onDestroy?: editorCallback,
55}
56
57// Editor constructor
58@module("@tiptap/core") @new
59external make: editorOptions => t = "Editor"
60
61// Mount the editor to a DOM element
62@send
63external mount: (t, Dom.element) => unit = "mount"
64
65// Unmount the editor from its current element
66@send
67external unmount: t => unit = "unmount"
68
69// Destroy the editor and clean up all resources
70@send
71external destroy: t => unit = "destroy"
72
73// Get the editor content as JSON
74// Returns JSON.t directly for use with stdlib functions
75@send
76external getJSON: t => JSON.t = "getJSON"
77
78// Check if editor is editable
79@get
80external isEditable: t => bool = "isEditable"
81
82// Check if editor is empty
83@get
84external isEmpty: t => bool = "isEmpty"
85
86// Check if editor is focused
87@get
88external isFocused: t => bool = "isFocused"
89
90// Check if editor is destroyed
91@get
92external isDestroyed: t => bool = "isDestroyed"
93
94// Access editor state and current selection
95// Used by formatting actions that need to read the live selection range
96type selection = {
97 from: int,
98 to: int,
99 empty: bool,
100}
101
102type editorState = {selection: selection}
103
104@get
105external state: t => editorState = "state"
106
107// Focus and blur commands are in the Commands module
108
109// Set the editable state
110@send
111external setEditable: (t, bool) => unit = "setEditable"
112
113// Commands module - all editor commands are accessed through editor.commands
114module Commands = {
115 // Set the editor content (replaces existing content)
116 @scope("commands") @send
117 external setContent: (t, JSON.t) => unit = "setContent"
118
119 // Insert content at the current cursor position
120 @scope("commands") @send
121 external insertContent: (t, JSON.t) => unit = "insertContent"
122
123 // Insert content at a specific position
124 @scope("commands") @send
125 external insertContentAt: (t, int, JSON.t) => unit = "insertContentAt"
126
127 // Insert content replacing a range (from..to)
128 @scope("commands") @send
129 external insertContentAtRange: (t, range, JSON.t) => unit = "insertContentAt"
130
131 // Focus the editor
132 @scope("commands") @send
133 external focus: t => unit = "focus"
134
135 // Blur the editor (remove focus)
136 @scope("commands") @send
137 external blur: t => unit = "blur"
138
139 // Set metadata on the editor instance
140 @scope("commands") @send
141 external setMeta: (t, string, string) => unit = "setMeta"
142
143 @scope("commands") @send
144 external setMark: (t, string) => unit = "setMark"
145
146 @scope("commands") @send
147 external toggleMark: (t, string) => unit = "toggleMark"
148
149 @scope("commands") @send
150 external unsetAllMarks: t => unit = "unsetAllMarks"
151
152 @scope("commands") @send
153 external setTextSelectionToPosition: (t, int) => unit = "setTextSelection"
154
155 @scope("commands") @send
156 external toggleHeading: (t, {"level": int}) => unit = "toggleHeading"
157}