@octane-xplat/lexical 0.0.1 → 0.10.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.
- package/LICENSE +21 -0
- package/README.md +85 -3
- package/dist/macos/browser.d.ts +1 -0
- package/dist/macos/browser.js +2 -0
- package/dist/native/index.js +3 -0
- package/dist/native/index2.js +232 -0
- package/dist/native/index3.js +211 -0
- package/dist/native/octane-client-build.json +8 -0
- package/dist/web/index.js +12 -0
- package/dist/web/index2.js +346 -0
- package/dist/web/octane-client-build.json +8 -0
- package/package.json +89 -3
- package/src/Editor.macos.tsx +9 -0
- package/src/LexicalEditor.tsrx +111 -0
- package/src/LexicalEditor.web.tsrx +406 -0
- package/src/browser-entry.web.tsx +5 -0
- package/src/index.macos.ts +13 -0
- package/src/index.ts +3 -0
- package/src/index.web.ts +12 -0
- package/src/json-bridge.ts +335 -0
- package/src/types.ts +105 -0
- package/types/index.d.ts +8 -0
- package/types/index.macos.d.ts +7 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/** Lazy lexical document-model bridge for native runtimes. The DOM-free
|
|
2
|
+
* slices (lexical core + the Aztec-shaped node packages, @lexical/html,
|
|
3
|
+
* zeed-dom as the parser host) load on demand — on a runtime that can't
|
|
4
|
+
* host them the bridge settles to unavailable and callers get null/no-op.
|
|
5
|
+
*
|
|
6
|
+
* Conversions run on a single headless `createEditor` (no `setRootElement`,
|
|
7
|
+
* no @lexical/headless — that package pulls happy-dom). Each call swaps the
|
|
8
|
+
* editor state wholesale, so the shared instance is a pure converter.
|
|
9
|
+
*
|
|
10
|
+
* Import behavior was proven by the demos probe (see packages/demos
|
|
11
|
+
* LexicalProbe): all slices load on both NS engines and the round-trip
|
|
12
|
+
* preserves links/alignment on 14/14 steps; the failure mode left is a
|
|
13
|
+
* future version or bundler regression, which the catch below degrades
|
|
14
|
+
* instead of crashing. */
|
|
15
|
+
|
|
16
|
+
import type { LexicalJSON } from './types'
|
|
17
|
+
|
|
18
|
+
interface Bridge {
|
|
19
|
+
editor: any
|
|
20
|
+
lexical: any
|
|
21
|
+
html: any
|
|
22
|
+
zeed: any
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let bridge: Bridge | null | undefined
|
|
26
|
+
|
|
27
|
+
const kebab = (k: string) => k.replace(/[A-Z]/g, (c) => '-' + c.toLowerCase())
|
|
28
|
+
|
|
29
|
+
function chainDesc(proto: object, key: string): PropertyDescriptor | undefined {
|
|
30
|
+
let o: object | null = proto
|
|
31
|
+
while (o && o !== Object.prototype) {
|
|
32
|
+
const d = Object.getOwnPropertyDescriptor(o, key)
|
|
33
|
+
if (d) {
|
|
34
|
+
return d
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
o = Object.getPrototypeOf(o)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function cssText(el: any): string {
|
|
44
|
+
return el.getAttribute('style') ?? ''
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function writeStyleProp(el: any, key: string, value: string): void {
|
|
48
|
+
const rules = cssText(el)
|
|
49
|
+
.split(';')
|
|
50
|
+
.map((s: string) => s.trim())
|
|
51
|
+
.filter(Boolean)
|
|
52
|
+
.filter((r: string) => !r.startsWith(kebab(key) + ':'))
|
|
53
|
+
|
|
54
|
+
if (value !== '' && value != null) {
|
|
55
|
+
rules.push(`${kebab(key)}: ${value}`)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
el.setAttribute('style', rules.join('; '))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** zeed-dom is a vdom, not a DOM — lexical's walkers and exportDOM need four
|
|
62
|
+
* categories of patches beyond the classList/DOMParser install the tiptap
|
|
63
|
+
* bridge carries:
|
|
64
|
+
*
|
|
65
|
+
* 1. `parentElement` (absent pre-0.18 zeed-dom; guarded either way).
|
|
66
|
+
* 2. `firstChild`/`lastChild`/sibling accessors return `undefined` where the
|
|
67
|
+
* DOM spec says `null`, and the getters live on an ancestor proto —
|
|
68
|
+
* chainDesc finds them so the coercion wraps the real getter.
|
|
69
|
+
* 3. `style`: DOM reads of unset props return `''`, and lexical's exportDOM
|
|
70
|
+
* writes via property assignment and `setProperty` — neither serializes
|
|
71
|
+
* in zeed. The proxy defaults missing props to `''` and writes through
|
|
72
|
+
* to the element's `style` attribute.
|
|
73
|
+
* 4. Attribute-valued property assignments (`element.href = …`) must land
|
|
74
|
+
* as attributes — LinkNode.exportDOM sets `anchor.href`, dropping the
|
|
75
|
+
* link target entirely without this.
|
|
76
|
+
*
|
|
77
|
+
* Plus the `Node` constants global (lexical's helpers read
|
|
78
|
+
* `Node.TEXT_NODE`). */
|
|
79
|
+
function installLexicalDomShim(zeed: any): void {
|
|
80
|
+
const bootDoc = zeed.createHTMLDocument()
|
|
81
|
+
bootDoc.body.innerHTML = '<p>x</p>'
|
|
82
|
+
const elProto = Object.getPrototypeOf(bootDoc.body.childNodes[0])
|
|
83
|
+
const textProto = Object.getPrototypeOf(bootDoc.body.childNodes[0].childNodes[0])
|
|
84
|
+
|
|
85
|
+
for (const p of [elProto, textProto]) {
|
|
86
|
+
if (!chainDesc(p, 'parentElement')) {
|
|
87
|
+
Object.defineProperty(p, 'parentElement', {
|
|
88
|
+
configurable: true,
|
|
89
|
+
get(this: any) {
|
|
90
|
+
const par = this.parentNode
|
|
91
|
+
return par && par.nodeType === 1 ? par : null
|
|
92
|
+
},
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for (const k of ['firstChild', 'lastChild', 'nextSibling', 'previousSibling']) {
|
|
97
|
+
const d = chainDesc(p, k)
|
|
98
|
+
Object.defineProperty(p, k, {
|
|
99
|
+
configurable: true,
|
|
100
|
+
get(this: any) {
|
|
101
|
+
const v = d?.get ? d.get.call(this) : undefined
|
|
102
|
+
return v ?? null
|
|
103
|
+
},
|
|
104
|
+
set: d?.set,
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const styleCache = new WeakMap()
|
|
110
|
+
Object.defineProperty(elProto, 'style', {
|
|
111
|
+
configurable: true,
|
|
112
|
+
get(this: any) {
|
|
113
|
+
let proxy = styleCache.get(this)
|
|
114
|
+
if (!proxy) {
|
|
115
|
+
const el = this
|
|
116
|
+
proxy = new Proxy(
|
|
117
|
+
{},
|
|
118
|
+
{
|
|
119
|
+
get: (_t, k) => {
|
|
120
|
+
if (k === 'setProperty') {
|
|
121
|
+
return (prop: string, value: string) => writeStyleProp(el, prop, value)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (k === 'removeProperty') {
|
|
125
|
+
return (prop: string) => {
|
|
126
|
+
writeStyleProp(el, prop, '')
|
|
127
|
+
return ''
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (k === 'cssText') {
|
|
132
|
+
return cssText(el)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (k === 'getPropertyValue') {
|
|
136
|
+
return (prop: string) => {
|
|
137
|
+
const raw = cssText(el)
|
|
138
|
+
.split(';')
|
|
139
|
+
.map((s: string) => s.trim())
|
|
140
|
+
.find((r: string) => r.startsWith(prop + ':'))
|
|
141
|
+
|
|
142
|
+
return raw ? raw.slice(raw.indexOf(':') + 1).trim() : ''
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (typeof k === 'string') {
|
|
147
|
+
const raw = cssText(el)
|
|
148
|
+
.split(';')
|
|
149
|
+
.map((s: string) => s.trim())
|
|
150
|
+
.find((r: string) => r.startsWith(kebab(k) + ':'))
|
|
151
|
+
|
|
152
|
+
return raw ? raw.slice(raw.indexOf(':') + 1).trim() : ''
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return undefined
|
|
156
|
+
},
|
|
157
|
+
set: (_t, k, v) => {
|
|
158
|
+
if (typeof k === 'string') {
|
|
159
|
+
writeStyleProp(el, k, v)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return true
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
styleCache.set(this, proxy)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return proxy
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
for (const attr of ['href', 'target', 'rel', 'title']) {
|
|
175
|
+
const d = chainDesc(elProto, attr)
|
|
176
|
+
if (!d?.get && !d?.set) {
|
|
177
|
+
Object.defineProperty(elProto, attr, {
|
|
178
|
+
configurable: true,
|
|
179
|
+
get(this: any) {
|
|
180
|
+
return this.getAttribute(attr) ?? ''
|
|
181
|
+
},
|
|
182
|
+
set(this: any, v: string) {
|
|
183
|
+
this.setAttribute(attr, v)
|
|
184
|
+
},
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const clDesc = chainDesc(elProto, 'classList')
|
|
190
|
+
if (clDesc?.get) {
|
|
191
|
+
Object.defineProperty(elProto, 'classList', {
|
|
192
|
+
configurable: true,
|
|
193
|
+
get(this: any) {
|
|
194
|
+
const cl = clDesc.get!.call(this)
|
|
195
|
+
if (cl && typeof cl[Symbol.iterator] !== 'function') {
|
|
196
|
+
const tokens = String(this.getAttribute('class') ?? '')
|
|
197
|
+
.split(/\s+/)
|
|
198
|
+
.filter(Boolean)
|
|
199
|
+
|
|
200
|
+
return Object.assign(tokens, cl)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return cl
|
|
204
|
+
},
|
|
205
|
+
set: clDesc.set,
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const g = globalThis as any
|
|
210
|
+
if (!g.window?.DOMParser) {
|
|
211
|
+
class ZeedDOMParser {
|
|
212
|
+
parseFromString(html: string) {
|
|
213
|
+
const doc = zeed.createHTMLDocument()
|
|
214
|
+
doc.body.innerHTML = html
|
|
215
|
+
return doc
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
g.window = { DOMParser: ZeedDOMParser }
|
|
220
|
+
g.document = zeed.createHTMLDocument()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
g.Node = g.Node ?? {
|
|
224
|
+
ELEMENT_NODE: 1,
|
|
225
|
+
ATTRIBUTE_NODE: 2,
|
|
226
|
+
TEXT_NODE: 3,
|
|
227
|
+
CDATA_SECTION_NODE: 4,
|
|
228
|
+
PROCESSING_INSTRUCTION_NODE: 7,
|
|
229
|
+
COMMENT_NODE: 8,
|
|
230
|
+
DOCUMENT_NODE: 9,
|
|
231
|
+
DOCUMENT_TYPE_NODE: 10,
|
|
232
|
+
DOCUMENT_FRAGMENT_NODE: 11,
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export async function ensureJSONBridge(): Promise<boolean> {
|
|
237
|
+
if (bridge !== undefined) {
|
|
238
|
+
return bridge !== null
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
const [lexical, html, rt, list, link, code, ext, zeed] = await Promise.all([
|
|
243
|
+
import('lexical'),
|
|
244
|
+
import('@lexical/html'),
|
|
245
|
+
import('@lexical/rich-text'),
|
|
246
|
+
import('@lexical/list'),
|
|
247
|
+
import('@lexical/link'),
|
|
248
|
+
import('@lexical/code'),
|
|
249
|
+
import('@lexical/extension'),
|
|
250
|
+
import('zeed-dom'),
|
|
251
|
+
])
|
|
252
|
+
|
|
253
|
+
installLexicalDomShim(zeed)
|
|
254
|
+
|
|
255
|
+
// The leaf's native node set — Aztec's capability surface in lexical
|
|
256
|
+
// form. taskList/highlight/sub/sup formats have no lexical node here
|
|
257
|
+
// and stay no-ops on the facade.
|
|
258
|
+
const editor = lexical.createEditor({
|
|
259
|
+
namespace: 'octane-xplat/lexical',
|
|
260
|
+
nodes: [
|
|
261
|
+
rt.HeadingNode,
|
|
262
|
+
rt.QuoteNode,
|
|
263
|
+
list.ListNode,
|
|
264
|
+
list.ListItemNode,
|
|
265
|
+
link.LinkNode,
|
|
266
|
+
code.CodeNode,
|
|
267
|
+
ext.HorizontalRuleNode,
|
|
268
|
+
],
|
|
269
|
+
onError: () => undefined,
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
bridge = { editor, lexical, html, zeed }
|
|
273
|
+
|
|
274
|
+
return true
|
|
275
|
+
} catch {
|
|
276
|
+
bridge = null
|
|
277
|
+
return false
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function jsonBridgeReady(): boolean {
|
|
282
|
+
return bridge != null
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function parseHTML(htmlText: string): any {
|
|
286
|
+
const doc = bridge!.zeed.createHTMLDocument()
|
|
287
|
+
doc.body.innerHTML = htmlText
|
|
288
|
+
return doc
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/** HTML → serialized editor state through lexical's own DOM import rules.
|
|
292
|
+
* Null when the bridge hasn't loaded (call ensureJSONBridge first / check
|
|
293
|
+
* `jsonBridgeReady`). */
|
|
294
|
+
export function htmlToJSON(htmlText: string): LexicalJSON | null {
|
|
295
|
+
if (!bridge) {
|
|
296
|
+
return null
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
try {
|
|
300
|
+
bridge.editor.update(
|
|
301
|
+
() => {
|
|
302
|
+
const nodes = bridge!.html.$generateNodesFromDOM(bridge!.editor, parseHTML(htmlText))
|
|
303
|
+
bridge!.lexical
|
|
304
|
+
.$getRoot()
|
|
305
|
+
.clear()
|
|
306
|
+
.append(...nodes)
|
|
307
|
+
},
|
|
308
|
+
{ discrete: true },
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
return bridge.editor.getEditorState().toJSON() as LexicalJSON
|
|
312
|
+
} catch {
|
|
313
|
+
return null
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/** Serialized editor state → HTML via lexical's own exportDOM rules (no
|
|
318
|
+
* browser DOM — the zeed-dom shim stands in). */
|
|
319
|
+
export function jsonToHTML(doc: LexicalJSON): string | null {
|
|
320
|
+
if (!bridge) {
|
|
321
|
+
return null
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
bridge.editor.setEditorState(bridge.editor.parseEditorState(JSON.stringify(doc)))
|
|
326
|
+
let out = ''
|
|
327
|
+
bridge.editor.read(() => {
|
|
328
|
+
out = bridge!.html.$generateHtmlFromNodes(bridge!.editor)
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
return out
|
|
332
|
+
} catch {
|
|
333
|
+
return null
|
|
334
|
+
}
|
|
335
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { Octane } from 'octane/jsx-runtime'
|
|
2
|
+
|
|
3
|
+
/** Format vocabulary shared by the web (lexical core + registered nodes)
|
|
4
|
+
* and native (Aztec) backends. On web, `taskList`/`highlight`/`subscript`/
|
|
5
|
+
* `superscript` are only active when their nodes are registered — the
|
|
6
|
+
* default node set doesn't include them, so they no-op there and map to
|
|
7
|
+
* Aztec formats on Android. */
|
|
8
|
+
export type LexicalFormat =
|
|
9
|
+
| 'bold'
|
|
10
|
+
| 'italic'
|
|
11
|
+
| 'underline'
|
|
12
|
+
| 'strikethrough'
|
|
13
|
+
| 'code'
|
|
14
|
+
| 'blockquote'
|
|
15
|
+
| 'bulletList'
|
|
16
|
+
| 'orderedList'
|
|
17
|
+
| 'taskList'
|
|
18
|
+
| 'codeBlock'
|
|
19
|
+
| 'horizontalRule'
|
|
20
|
+
| 'highlight'
|
|
21
|
+
| 'subscript'
|
|
22
|
+
| 'superscript'
|
|
23
|
+
| 'paragraph'
|
|
24
|
+
| 'heading1'
|
|
25
|
+
| 'heading2'
|
|
26
|
+
| 'heading3'
|
|
27
|
+
| 'heading4'
|
|
28
|
+
| 'heading5'
|
|
29
|
+
| 'heading6'
|
|
30
|
+
| 'alignLeft'
|
|
31
|
+
| 'alignCenter'
|
|
32
|
+
| 'alignRight'
|
|
33
|
+
| 'link'
|
|
34
|
+
|
|
35
|
+
/** Lexical serialized editor state (`{ root: { children: [...] } }` — the
|
|
36
|
+
* `EditorState.toJSON()` shape). Opaque here — callers round-trip through
|
|
37
|
+
* lexical's own schema on both platforms. */
|
|
38
|
+
export type LexicalJSON = { root: Record<string, unknown> } & Record<string, unknown>
|
|
39
|
+
|
|
40
|
+
export interface LexicalEditorHandle {
|
|
41
|
+
/** AppKit: returns the latest WebKit snapshot; commands are asynchronous. */
|
|
42
|
+
getHTML(): string
|
|
43
|
+
/** Web: `setEditorState` inside an update (undo-aware). Native: Aztec
|
|
44
|
+
* `fromHtml` — resets undo history. */
|
|
45
|
+
setHTML(html: string): void
|
|
46
|
+
/** Serialized editor state, or null while the native doc-model modules
|
|
47
|
+
* are still loading / on a runtime that can't host them (`onJSONReady`
|
|
48
|
+
* reports the outcome). Web is always ready. */
|
|
49
|
+
/** AppKit: latest live engine JSON snapshot; null before onReady. */
|
|
50
|
+
getJSON(): LexicalJSON | null
|
|
51
|
+
setJSON(doc: LexicalJSON): void
|
|
52
|
+
apply(format: LexicalFormat): void
|
|
53
|
+
linkTo(url: string, anchor?: string): void
|
|
54
|
+
removeLink(): void
|
|
55
|
+
isActive(format: LexicalFormat): boolean
|
|
56
|
+
undo(): void
|
|
57
|
+
redo(): void
|
|
58
|
+
focus(): void
|
|
59
|
+
blur(): void
|
|
60
|
+
isFocused(): boolean
|
|
61
|
+
/** The platform surface — the lexical `LexicalEditor` on web,
|
|
62
|
+
* `AztecText` on Android. */
|
|
63
|
+
/** AppKit: the XplatEditorHost transport, not the browser engine instance. */
|
|
64
|
+
native: any
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface LexicalEditorProps {
|
|
68
|
+
id?: string
|
|
69
|
+
className?: string
|
|
70
|
+
style?: any
|
|
71
|
+
/** Document HTML. Seed at mount; external changes re-push. */
|
|
72
|
+
value?: string
|
|
73
|
+
/** Serialized editor state. Takes precedence over `value` when both
|
|
74
|
+
* arrive. On native it waits for the doc-model modules (see
|
|
75
|
+
* `onJSONReady`). */
|
|
76
|
+
json?: LexicalJSON
|
|
77
|
+
placeholder?: string
|
|
78
|
+
editable?: boolean
|
|
79
|
+
autofocus?: boolean
|
|
80
|
+
onReady?: () => void
|
|
81
|
+
/** Fires once when the native lexical bridge settles — `true` if the
|
|
82
|
+
* DOM-free lexical modules loaded, `false` on runtimes that can't host
|
|
83
|
+
* them (JSON calls then no-op / return null). Never fires on web. */
|
|
84
|
+
/** AppKit: fires true with mounted engine readiness; no headless conversion bridge. */
|
|
85
|
+
onJSONReady?: (ready: boolean) => void
|
|
86
|
+
onChange?: (html: string) => void
|
|
87
|
+
onJSONChange?: (doc: LexicalJSON) => void
|
|
88
|
+
onSelectionChange?: (event: { start: number; end: number; active: LexicalFormat[] }) => void
|
|
89
|
+
onFocus?: () => void
|
|
90
|
+
onBlur?: () => void
|
|
91
|
+
ref?: Octane.Ref<LexicalEditorHandle>
|
|
92
|
+
android?: Record<string, any>
|
|
93
|
+
ios?: Record<string, any>
|
|
94
|
+
row?: number | string
|
|
95
|
+
col?: number | string
|
|
96
|
+
rowSpan?: number
|
|
97
|
+
colSpan?: number
|
|
98
|
+
dock?: 'left' | 'top' | 'right' | 'bottom'
|
|
99
|
+
left?: number
|
|
100
|
+
top?: number
|
|
101
|
+
flexGrow?: number
|
|
102
|
+
flexShrink?: number
|
|
103
|
+
alignSelf?: 'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'
|
|
104
|
+
order?: number
|
|
105
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { UniversalComponent } from 'octane/universal'
|
|
2
|
+
import type { LexicalEditorProps, LexicalJSON } from '../src/types'
|
|
3
|
+
|
|
4
|
+
export declare const LexicalEditor: UniversalComponent<LexicalEditorProps>
|
|
5
|
+
export declare const supported: boolean
|
|
6
|
+
export declare function ensureJSONBridge(): Promise<boolean>
|
|
7
|
+
export declare function jsonBridgeReady(): boolean
|
|
8
|
+
export type * from '../src/types'
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UniversalComponent } from 'octane/universal'
|
|
2
|
+
import type { LexicalEditorProps } from '../src/types'
|
|
3
|
+
export declare const LexicalEditor: UniversalComponent<LexicalEditorProps>
|
|
4
|
+
export declare const supported: boolean
|
|
5
|
+
export type * from '../src/types'
|
|
6
|
+
export declare function ensureJSONBridge(): Promise<boolean>
|
|
7
|
+
export declare function jsonBridgeReady(): boolean
|