@lyfie/luthor-headless 2.3.1 → 2.3.2

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 (2) hide show
  1. package/package.json +2 -2
  2. package/dist/index.d.cts +0 -2531
package/dist/index.d.cts DELETED
@@ -1,2531 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { TextFormatType, LexicalEditor, KlassConstructor, LexicalNode, LexicalNodeReplacement, EditorThemeClasses, ParagraphNode, SerializedLexicalNode, EditorConfig as EditorConfig$1, DOMConversionMap, DOMExportOutput, ElementNode, DecoratorNode, RangeSelection } from 'lexical';
3
- export { LexicalEditor } from 'lexical';
4
- import * as React$1 from 'react';
5
- import React__default, { ReactNode, ComponentType, CSSProperties } from 'react';
6
- import { ListNode, ListItemNode } from '@lexical/list';
7
- import { CodeNode, CodeHighlightNode } from '@lexical/code';
8
- import { HeadingTagType, HeadingNode, QuoteNode } from '@lexical/rich-text';
9
-
10
- type LexicalNodeRegistration = KlassConstructor<typeof LexicalNode> | LexicalNodeReplacement;
11
- /** Extension category buckets */
12
- declare enum ExtensionCategory {
13
- Toolbar = "toolbar",
14
- Sidebar = "sidebar",
15
- ContextMenu = "contextmenu",
16
- Floating = "floating"
17
- }
18
- /** Shared base config for extensions */
19
- interface BaseExtensionConfig {
20
- showInToolbar?: boolean;
21
- category?: ExtensionCategory[];
22
- position?: "before" | "after";
23
- /** Initialization priority; higher registers first (default: 0) */
24
- initPriority?: number;
25
- [key: string]: unknown;
26
- }
27
- /** Toolbar item configuration */
28
- interface ToolbarItem {
29
- label: string;
30
- onClick: () => void;
31
- isActive?: () => boolean;
32
- component?: React.ComponentType<Record<string, unknown>>;
33
- }
34
- /**
35
- * Core extension contract implemented by all extensions.
36
- * Defines the required API surface for Luthor extensions.
37
- *
38
- * @template Name - Exact literal type of the extension name
39
- * @template Config - Extension configuration type
40
- * @template Commands - Command map exposed by the extension
41
- * @template StateQueries - State query function map
42
- * @template Plugins - React plugins exposed by the extension
43
- */
44
- interface Extension<Name extends string = string, Config extends BaseExtensionConfig = BaseExtensionConfig, Commands extends Record<string, unknown> = Record<string, never>, StateQueries extends Record<string, () => Promise<boolean>> = Record<string, never>, Plugins extends ReactNode[] = ReactNode[]> {
45
- /** Unique identifier for this extension */
46
- name: Name;
47
- /** Category groups for this extension */
48
- category: ExtensionCategory[];
49
- /** Extension configuration */
50
- config: Config;
51
- /** Supported text formats */
52
- supportedFormats?: readonly TextFormatType[];
53
- /** Update extension settings */
54
- configure?: (config: Partial<Config>) => Extension<Name, Config, Commands, StateQueries, Plugins>;
55
- /** Register the extension with Lexical */
56
- register: (editor: LexicalEditor) => () => void;
57
- /** Override the extension UI component */
58
- overrideUI?: (CustomUI: ComponentType<{
59
- selected?: boolean;
60
- className?: string;
61
- style?: CSSProperties;
62
- [key: string]: unknown;
63
- }>) => Extension<Name, Config, Commands, StateQueries, Plugins>;
64
- /** Override node rendering logic */
65
- overrideNodeRender?: (overrides: {
66
- createDOM?: (config: unknown) => HTMLElement;
67
- updateDOM?: (prev: unknown, next: unknown, dom: HTMLElement) => boolean;
68
- }) => Extension<Name, Config, Commands, StateQueries, Plugins>;
69
- /** Return custom Lexical nodes */
70
- getNodes?: () => LexicalNodeRegistration[];
71
- /** Return React plugins */
72
- getPlugins: () => Plugins;
73
- /** Provide commands exposed by the extension */
74
- getCommands: (editor: LexicalEditor) => Commands;
75
- /** Return state query functions */
76
- getStateQueries?: (editor: LexicalEditor) => StateQueries;
77
- }
78
- type MergeCommands<T> = {
79
- [K in UnionKeys<T>]: T extends {
80
- [P in K]: infer V;
81
- } ? V : never;
82
- };
83
- type MergeStateQueries<T> = {
84
- [K in UnionKeys<T>]: boolean;
85
- };
86
- type ExtractNames<Exts extends readonly Extension[]> = Exts[number]["name"];
87
- type ExtractCommands<Exts extends readonly Extension[]> = MergeCommands<ReturnType<Exts[number]["getCommands"]>>;
88
- type ExtractPlugins<Exts extends readonly Extension[]> = ReturnType<Exts[number]["getPlugins"]>[number];
89
- type UnionKeys<T> = T extends unknown ? keyof T : never;
90
- type ExtractStateQueries<Exts extends readonly Extension[]> = MergeStateQueries<ReturnType<NonNullable<Exts[number]["getStateQueries"]>>>;
91
- interface BaseCommands {
92
- formatText: (format: TextFormatType, value?: boolean | string) => void;
93
- }
94
- /**
95
- * Editor system context type, parameterized by the extensions array.
96
- * Exposes typed commands, state, and utilities.
97
- *
98
- * @template Exts - Extensions array that defines available functionality
99
- */
100
- interface EditorContextType<Exts extends readonly Extension[]> {
101
- /** Underlying Lexical editor instance */
102
- editor: LexicalEditor | null;
103
- /** Editor settings */
104
- config?: EditorConfig;
105
- /** Loaded extensions list */
106
- extensions: Exts;
107
- /** Commands available from all extensions */
108
- commands: BaseCommands & ExtractCommands<Exts>;
109
- /** Current state for all extensions */
110
- activeStates: ExtractStateQueries<Exts>;
111
- /** State query functions from extensions */
112
- stateQueries: Record<string, () => Promise<unknown>>;
113
- /** Event listener registration */
114
- listeners: {
115
- registerUpdate: (listener: (state: unknown) => void) => (() => void) | undefined;
116
- registerPaste: (listener: (event: ClipboardEvent) => boolean) => (() => void) | undefined;
117
- };
118
- /** Export helpers for formats */
119
- export: {
120
- toJSON: () => unknown;
121
- };
122
- /** Import helpers for formats */
123
- import: {
124
- fromJSON: (json: unknown) => void;
125
- };
126
- /** Alias of the raw Lexical editor */
127
- lexical: LexicalEditor | null;
128
- /** Dynamic extensions API */
129
- extensionsAPI: {
130
- add: (ext: Extension) => void;
131
- remove: (name: string) => void;
132
- reorder: (names: string[]) => void;
133
- };
134
- /** React plugins collected from extensions */
135
- plugins: ExtractPlugins<Exts>[];
136
- /** Check whether a specific extension is loaded */
137
- hasExtension: (name: ExtractNames<Exts>) => boolean;
138
- }
139
- interface EditorConfig {
140
- theme?: EditorThemeClasses;
141
- [key: string]: unknown;
142
- }
143
-
144
- interface ProviderProps<Exts extends readonly Extension[]> {
145
- children: ReactNode;
146
- config?: EditorConfig;
147
- extensions: Exts;
148
- }
149
- /**
150
- * Creates a typed editor system based on the provided extensions array.
151
- * This factory function generates a Provider component and useEditor hook
152
- * that are strongly typed based on the extensions passed to it.
153
- *
154
- * @template Exts - Array of extensions that define the editor's capabilities
155
- * @returns Object containing Provider component and useEditor hook
156
- *
157
- * @example
158
- * ```tsx
159
- * const extensions = [boldExtension, italicExtension] as const;
160
- * const { Provider, useEditor } = createEditorSystem<typeof extensions>();
161
- * ```
162
- */
163
- declare function createEditorSystem<Exts extends readonly Extension[]>(): {
164
- Provider: (props: ProviderProps<Exts>) => react_jsx_runtime.JSX.Element;
165
- useEditor: () => EditorContextType<Exts>;
166
- };
167
- declare const BaseProvider: (props: ProviderProps<readonly Extension<string, BaseExtensionConfig, Record<string, never>, Record<string, never>, React__default.ReactNode[]>[]>) => react_jsx_runtime.JSX.Element;
168
- declare const useBaseEditor: () => EditorContextType<readonly Extension<string, BaseExtensionConfig, Record<string, never>, Record<string, never>, React__default.ReactNode[]>[]>;
169
-
170
- /**
171
- * Abstract base class for all Luthor extensions.
172
- * Provides default implementations and shared extension behavior.
173
- *
174
- * @template Name - Literal extension name
175
- * @template Config - Configuration object type
176
- * @template Commands - Commands exposed by this extension
177
- * @template StateQueries - State query functions exposed by this extension
178
- * @template Plugins - React plugins/components exposed by this extension
179
- */
180
- declare abstract class BaseExtension<Name extends string = string, Config extends BaseExtensionConfig = BaseExtensionConfig, Commands extends Record<string, unknown> = Record<string, never>, StateQueries extends Record<string, () => Promise<boolean>> = Record<string, never>, Plugins extends ReactNode[] = ReactNode[]> implements Extension<Name, Config, Commands, StateQueries, Plugins> {
181
- /** Unique name identifier for this extension */
182
- name: Name;
183
- /** Categories this extension belongs to (toolbar, sidebar, etc.) */
184
- category: ExtensionCategory[];
185
- /** Configuration for this extension */
186
- config: Config;
187
- /** Text formats supported by this extension */
188
- supportedFormats: readonly TextFormatType[];
189
- /** Node rendering overrides */
190
- nodeOverrides: {
191
- createDOM?: (config: unknown) => HTMLElement;
192
- updateDOM?: (prev: unknown, next: unknown, dom: HTMLElement) => boolean;
193
- };
194
- /**
195
- * Creates a new extension instance.
196
- *
197
- * @param name - Unique name for this extension
198
- * @param category - Categories this extension belongs to
199
- */
200
- constructor(name: Name, category?: ExtensionCategory[]);
201
- /**
202
- * Configures the extension with new settings.
203
- * Returns the instance with updated configuration.
204
- *
205
- * @param config - Partial configuration to merge into existing config
206
- * @returns Extension instance with updated config
207
- */
208
- configure(config: Partial<Config>): Extension<Name, Config, Commands, StateQueries, Plugins>;
209
- /**
210
- * Registers the extension with the Lexical editor.
211
- * Override to set up event listeners, commands, etc.
212
- *
213
- * @param editor - Lexical editor instance
214
- * @returns Cleanup function to unregister the extension
215
- */
216
- abstract register(editor: LexicalEditor): () => void;
217
- /**
218
- * Returns custom Lexical nodes exposed by this extension.
219
- *
220
- * @returns Array of Lexical node classes
221
- */
222
- getNodes(): LexicalNodeRegistration[];
223
- /**
224
- * Allows overriding the UI component used for this extension.
225
- *
226
- * @param CustomUI - Custom React component to render
227
- * @returns Extension instance for chaining
228
- */
229
- overrideUI(CustomUI: ComponentType<{
230
- selected?: boolean;
231
- className?: string;
232
- style?: CSSProperties;
233
- [key: string]: unknown;
234
- }>): Extension<Name, Config, Commands, StateQueries, Plugins>;
235
- /**
236
- * Overrides node rendering behavior.
237
- *
238
- * @param overrides - DOM creation and update handlers
239
- * @returns Extension instance for chaining
240
- */
241
- overrideNodeRender(overrides: {
242
- createDOM?: (config: unknown) => HTMLElement;
243
- updateDOM?: (prev: unknown, next: unknown, dom: HTMLElement) => boolean;
244
- }): Extension<Name, Config, Commands, StateQueries, Plugins>;
245
- /**
246
- * Returns React plugins/components exposed by this extension.
247
- *
248
- * @returns Array of React nodes to render
249
- */
250
- getPlugins(): Plugins;
251
- /**
252
- * Returns commands exposed by this extension.
253
- *
254
- * @param editor - Lexical editor instance
255
- * @returns Object containing command functions
256
- */
257
- getCommands(editor: LexicalEditor): Commands;
258
- /**
259
- * Returns state query functions exposed by this extension.
260
- *
261
- * @param editor - Lexical editor instance
262
- * @returns Object containing state query functions
263
- */
264
- getStateQueries(editor: LexicalEditor): StateQueries;
265
- /**
266
- * Returns toolbar items contributed by this extension.
267
- *
268
- * @param commands - Available commands from all extensions
269
- * @returns Array of toolbar item configurations
270
- */
271
- getToolbarItems(commands: Record<string, unknown>): ToolbarItem[];
272
- }
273
-
274
- /**
275
- * Configuration options for creating a custom extension
276
- */
277
- interface CreateExtensionConfig<Name extends string, Config extends BaseExtensionConfig = BaseExtensionConfig, Commands extends Record<string, unknown> = Record<string, never>, StateQueries extends Record<string, () => Promise<boolean>> = Record<string, never>, Plugins extends ReactNode[] = ReactNode[]> {
278
- /** Unique name for the extension */
279
- name: Name;
280
- /** Categories this extension belongs to */
281
- category?: ExtensionCategory[];
282
- /** Default configuration */
283
- config?: Partial<Config>;
284
- /** Commands provided by this extension */
285
- commands?: (editor: LexicalEditor) => Commands;
286
- /** State query functions */
287
- stateQueries?: (editor: LexicalEditor) => StateQueries;
288
- /** React plugins/components */
289
- plugins?: Plugins;
290
- /** Initialization function called when extension is registered */
291
- initialize?: (editor: LexicalEditor) => (() => void) | void;
292
- /** Custom Lexical nodes */
293
- nodes?: LexicalNodeRegistration[];
294
- /** Text formats supported by this extension */
295
- supportedFormats?: readonly TextFormatType[];
296
- }
297
- /**
298
- * Factory function to create a type-safe extension that extends BaseExtension.
299
- * Provides a simpler API for creating extensions while maintaining full type safety.
300
- *
301
- * @template Name - Literal type for the extension name
302
- * @template Config - Configuration object type
303
- * @template Commands - Commands provided by the extension
304
- * @template StateQueries - State query functions
305
- * @template Plugins - React plugins provided by the extension
306
- *
307
- * @param config - Configuration object for the extension
308
- * @returns A fully typed extension instance
309
- *
310
- * @example
311
- * ```tsx
312
- * const myExtension = createExtension({
313
- * name: 'my-extension',
314
- * commands: (editor) => ({
315
- * myCommand: () => console.log('Hello!')
316
- * }),
317
- * stateQueries: (editor) => ({
318
- * isActive: async () => true
319
- * }),
320
- * initialize: (editor) => {
321
- * // Custom initialization
322
- * return () => {
323
- * // Cleanup function
324
- * };
325
- * }
326
- * });
327
- * ```
328
- */
329
- declare function createExtension<Name extends string, Config extends BaseExtensionConfig = BaseExtensionConfig, Commands extends Record<string, unknown> = Record<string, never>, StateQueries extends Record<string, () => Promise<boolean>> = Record<string, never>, Plugins extends ReactNode[] = ReactNode[]>(config: CreateExtensionConfig<Name, Config, Commands, StateQueries, Plugins>): BaseExtension<Name, Config, Commands, StateQueries, Plugins>;
330
-
331
- declare const LUTHOR_EDITOR_THEME_TOKENS: readonly ["--luthor-bg", "--luthor-fg", "--luthor-border", "--luthor-border-hover", "--luthor-border-active", "--luthor-accent", "--luthor-accent-hover", "--luthor-shadow", "--luthor-muted", "--luthor-muted-fg", "--luthor-theme-transition", "--luthor-drag-gutter-width", "--luthor-line-height-ratio", "--luthor-toolbar-bg", "--luthor-toolbar-section-border", "--luthor-toolbar-button-fg", "--luthor-toolbar-button-hover-bg", "--luthor-toolbar-button-hover-border", "--luthor-toolbar-button-hover-shadow", "--luthor-toolbar-button-press-shadow", "--luthor-toolbar-button-active-bg", "--luthor-toolbar-button-active-border", "--luthor-toolbar-button-active-fg", "--luthor-toolbar-button-active-shadow", "--luthor-toolbar-button-overlay", "--luthor-toolbar-button-active-overlay", "--luthor-toolbar-color-indicator-border", "--luthor-toolbar-highlight-bg", "--luthor-quote-bg", "--luthor-quote-fg", "--luthor-quote-border", "--luthor-text-bold-color", "--luthor-link-color", "--luthor-list-marker-color", "--luthor-list-checkbox-color", "--luthor-table-border-color", "--luthor-table-header-bg", "--luthor-hr-color", "--luthor-placeholder-color", "--luthor-codeblock-bg", "--luthor-syntax-comment", "--luthor-syntax-keyword", "--luthor-syntax-string", "--luthor-syntax-number", "--luthor-syntax-function", "--luthor-syntax-variable", "--luthor-floating-bg", "--luthor-floating-fg", "--luthor-floating-border", "--luthor-floating-shadow", "--luthor-floating-muted", "--luthor-floating-border-hover", "--luthor-floating-border-active", "--luthor-floating-accent", "--luthor-floating-accent-fg", "--luthor-preset-bg", "--luthor-preset-fg", "--luthor-preset-border", "--luthor-preset-muted", "--luthor-preset-muted-fg", "--luthor-preset-accent", "--luthor-preset-radius", "--luthor-preset-shadow", "--luthor-preset-content-padding", "--luthor-preset-content-min-height"];
332
- type LuthorEditorThemeToken = (typeof LUTHOR_EDITOR_THEME_TOKENS)[number];
333
- type LuthorEditorThemeOverrides = Partial<Record<LuthorEditorThemeToken, string>>;
334
- declare function createEditorThemeStyleVars(overrides?: LuthorEditorThemeOverrides): React__default.CSSProperties | undefined;
335
- /**
336
- * Enhanced theme type that extends Lexical's EditorThemeClasses
337
- * with better TypeScript support and additional properties
338
- */
339
- interface LuthorTheme extends EditorThemeClasses {
340
- toolbar?: {
341
- button?: string;
342
- buttonActive?: string;
343
- buttonDisabled?: string;
344
- group?: string;
345
- };
346
- container?: string;
347
- wrapper?: string;
348
- contextMenu?: {
349
- container?: string;
350
- item?: string;
351
- itemDisabled?: string;
352
- };
353
- draggable?: {
354
- handle?: string;
355
- handleActive?: string;
356
- handleHover?: string;
357
- handleDragging?: string;
358
- blockDragging?: string;
359
- dropIndicator?: string;
360
- upButton?: string;
361
- downButton?: string;
362
- blockIsDragging?: string;
363
- buttonStack?: string;
364
- styles?: {
365
- handle?: React__default.CSSProperties;
366
- handleActive?: React__default.CSSProperties;
367
- handleHover?: React__default.CSSProperties;
368
- handleDragging?: React__default.CSSProperties;
369
- blockDragging?: React__default.CSSProperties;
370
- dropIndicator?: React__default.CSSProperties;
371
- upButton?: React__default.CSSProperties;
372
- downButton?: React__default.CSSProperties;
373
- blockIsDragging?: React__default.CSSProperties;
374
- buttonStack?: React__default.CSSProperties;
375
- };
376
- };
377
- floatingToolbar?: {
378
- container?: string;
379
- button?: string;
380
- buttonActive?: string;
381
- styles?: {
382
- container?: React__default.CSSProperties;
383
- button?: React__default.CSSProperties;
384
- buttonActive?: React__default.CSSProperties;
385
- };
386
- };
387
- styles?: {
388
- toolbar?: {
389
- button?: React__default.CSSProperties;
390
- buttonActive?: React__default.CSSProperties;
391
- buttonDisabled?: React__default.CSSProperties;
392
- group?: React__default.CSSProperties;
393
- };
394
- container?: React__default.CSSProperties;
395
- wrapper?: React__default.CSSProperties;
396
- draggable?: {
397
- handle?: React__default.CSSProperties;
398
- handleHover?: React__default.CSSProperties;
399
- handleDragging?: React__default.CSSProperties;
400
- blockDragging?: React__default.CSSProperties;
401
- dropIndicator?: React__default.CSSProperties;
402
- upButton?: React__default.CSSProperties;
403
- downButton?: React__default.CSSProperties;
404
- blockIsDragging?: React__default.CSSProperties;
405
- buttonStack?: React__default.CSSProperties;
406
- };
407
- floatingToolbar?: {
408
- container?: React__default.CSSProperties;
409
- button?: React__default.CSSProperties;
410
- buttonActive?: React__default.CSSProperties;
411
- };
412
- };
413
- }
414
- /**
415
- * Default Luthor theme with sensible defaults
416
- */
417
- declare const defaultLuthorTheme: LuthorTheme;
418
- /**
419
- * Helper function to merge themes
420
- */
421
- declare function mergeThemes(baseTheme: LuthorTheme, overrideTheme: Partial<LuthorTheme>): LuthorTheme;
422
- /**
423
- * Type guard to check if a theme is a LuthorTheme
424
- */
425
- declare function isLuthorTheme(theme: any): theme is LuthorTheme;
426
-
427
- declare function clearLexicalSelection(editor: LexicalEditor): void;
428
- declare function resolveLinkNodeKeyFromAnchor(editor: LexicalEditor, anchorEl: HTMLAnchorElement): string | null;
429
-
430
- type JsonTextNode = {
431
- type: "text";
432
- version: 1;
433
- text: string;
434
- detail: 0;
435
- format: 0;
436
- mode: "normal";
437
- style: "";
438
- };
439
- type JsonParagraphNode = {
440
- type: "paragraph";
441
- version: 1;
442
- format: "";
443
- indent: 0;
444
- direction: null;
445
- children: JsonTextNode[];
446
- };
447
- type JsonRootNode = {
448
- type: "root";
449
- version: 1;
450
- format: "";
451
- indent: 0;
452
- direction: null;
453
- children: JsonParagraphNode[];
454
- };
455
- type JsonbDocument = {
456
- root: JsonRootNode;
457
- };
458
- declare function markdownToJSONB(markdown: string): JsonbDocument;
459
- declare function jsonbToMarkdown(input: unknown): string;
460
-
461
- /**
462
- * Commands exposed by text format extensions.
463
- * Generates toggle commands for text formatting (e.g., toggleBold, toggleItalic).
464
- */
465
- type TextFormatCommands<Name extends TextFormatType> = {
466
- [Key in `toggle${Capitalize<Name>}`]: () => void;
467
- };
468
- /**
469
- * Base extension for text formatting (bold, italic, underline, etc.).
470
- * Provides shared functionality for text format extensions.
471
- *
472
- * @template Name - Text format name (e.g., 'bold', 'italic')
473
- */
474
- declare abstract class TextFormatExtension<Name extends TextFormatType> extends BaseExtension<Name, any, TextFormatCommands<Name>, Record<Name, () => Promise<boolean>>, ReactNode[]> {
475
- /**
476
- * Creates a new text format extension instance.
477
- *
478
- * @param name - Text format name
479
- */
480
- constructor(name: Name);
481
- /**
482
- * Registers the extension with the editor.
483
- * Text format extensions register listeners for INSERT_PARAGRAPH_COMMAND and INSERT_LINE_BREAK_COMMAND
484
- * to handle formatting behavior when Enter/Shift+Enter is pressed.
485
- *
486
- * @param editor - Lexical editor instance
487
- * @returns Cleanup function
488
- */
489
- register(editor: LexicalEditor): () => void;
490
- /**
491
- * Returns the toggle command for this text format.
492
- *
493
- * @param editor - Lexical editor instance
494
- * @returns Object with toggle command function
495
- */
496
- getCommands(editor: LexicalEditor): TextFormatCommands<Name>;
497
- /**
498
- * Returns a state query to check if the selection has this format applied.
499
- *
500
- * @param editor - Lexical editor instance
501
- * @returns Object with format state query function
502
- */
503
- getStateQueries(editor: LexicalEditor): Record<Name, () => Promise<boolean>>;
504
- }
505
-
506
- /**
507
- * Bold text formatting extension.
508
- * Provides bold text formatting functionality with toggle command and state tracking.
509
- *
510
- * @example
511
- * ```tsx
512
- * const extensions = [boldExtension] as const;
513
- * const { Provider, useEditor } = createEditorSystem<typeof extensions>();
514
- *
515
- * function MyEditor() {
516
- * const { commands, activeStates } = useEditor();
517
- * return (
518
- * <button
519
- * onClick={() => commands.toggleBold()}
520
- * className={activeStates.bold ? 'active' : ''}
521
- * >
522
- * Bold
523
- * </button>
524
- * );
525
- * }
526
- * ```
527
- */
528
- declare class BoldExtension extends TextFormatExtension<"bold"> {
529
- /**
530
- * Creates a new bold extension instance.
531
- */
532
- constructor();
533
- }
534
- /**
535
- * Pre-configured bold extension instance.
536
- * Ready to use in extension arrays.
537
- */
538
- declare const boldExtension: BoldExtension;
539
-
540
- /**
541
- * Italic text formatting extension.
542
- * Provides italic formatting with toggle command and state tracking.
543
- */
544
- declare class ItalicExtension extends TextFormatExtension<"italic"> {
545
- /**
546
- * Creates a new italic extension.
547
- */
548
- constructor();
549
- }
550
- /**
551
- * Preconfigured italic extension instance.
552
- * Ready for use in extension arrays.
553
- */
554
- declare const italicExtension: ItalicExtension;
555
-
556
- /**
557
- * Custom underline transformer for Markdown
558
- * Uses ++underline++ syntax (common in extended Markdown)
559
- */
560
- declare const UNDERLINE_TRANSFORMER: {
561
- format: readonly ["underline"];
562
- tag: string;
563
- type: "text-format";
564
- };
565
- /**
566
- * UnderlineExtension - Adds underline text formatting
567
- *
568
- * Extends TextFormatExtension to add underline formatting for selected text in
569
- * the Lexical editor. Integrates with the toolbar system and exposes commands
570
- * and state queries for underline actions.
571
- *
572
- * Supports Markdown syntax: ++underline++
573
- *
574
- * @example
575
- * ```tsx
576
- * import { underlineExtension } from '@lyfie/luthor-headless/extensions/formatting/UnderlineExtension';
577
- *
578
- * const extensions = [underlineExtension];
579
- * const editor = createEditorSystem(extensions);
580
- * ```
581
- */
582
- declare class UnderlineExtension extends TextFormatExtension<"underline"> {
583
- constructor();
584
- /**
585
- * Returns Markdown transformers for underline formatting.
586
- *
587
- * @returns An array containing the underline transformer
588
- */
589
- getMarkdownTransformers(): readonly typeof UNDERLINE_TRANSFORMER[];
590
- }
591
- declare const underlineExtension: UnderlineExtension;
592
-
593
- /**
594
- * StrikethroughExtension - Adds strikethrough text formatting
595
- *
596
- * Extends TextFormatExtension to add strikethrough formatting for selected
597
- * text in the Lexical editor. Integrates with the toolbar system and exposes
598
- * commands and state queries for strikethrough actions.
599
- *
600
- * @example
601
- * ```tsx
602
- * import { strikethroughExtension } from '@lyfie/luthor-headless/extensions/formatting/StrikethroughExtension';
603
- *
604
- * const extensions = [strikethroughExtension];
605
- * const editor = createEditorSystem(extensions);
606
- * ```
607
- */
608
- declare class StrikethroughExtension extends TextFormatExtension<"strikethrough"> {
609
- constructor();
610
- }
611
- declare const strikethroughExtension: StrikethroughExtension;
612
-
613
- /**
614
- * Link extension configuration.
615
- */
616
- interface LinkConfig extends BaseExtensionConfig {
617
- /**
618
- * Automatically link URLs as you type in the editor.
619
- * Uses real-time pattern matching. Default: false
620
- */
621
- autoLinkText?: boolean;
622
- /**
623
- * Automatically link URLs when pasted into the editor.
624
- * When false, pasted URLs remain plain text. Default: true
625
- */
626
- autoLinkUrls?: boolean;
627
- /**
628
- * Link selected text when pasting URLs over it.
629
- * When true: selected text becomes a link with the pasted URL.
630
- * When false: selected text is replaced with the pasted URL and then linked. Default: true
631
- */
632
- linkSelectedTextOnPaste?: boolean;
633
- /** URL validation function (default: basic URL regex) */
634
- validateUrl?: (url: string) => boolean;
635
- /** Enable click navigation on links rendered inside the editor. Default: true */
636
- clickableLinks?: boolean;
637
- /** Open clicked links in a new tab when click navigation is enabled. Default: true */
638
- openLinksInNewTab?: boolean;
639
- }
640
- /**
641
- * Commands exposed by the link extension.
642
- */
643
- type LinkCommands = {
644
- insertLink: (url?: string, text?: string) => void;
645
- updateLink: (url: string, rel?: string, target?: string) => boolean;
646
- removeLink: () => void;
647
- getCurrentLink: () => Promise<{
648
- url: string;
649
- rel: string | null;
650
- target: string | null;
651
- } | null>;
652
- getLinkByKey: (linkNodeKey: string) => Promise<{
653
- url: string;
654
- rel: string | null;
655
- target: string | null;
656
- } | null>;
657
- updateLinkByKey: (linkNodeKey: string, url: string, rel?: string, target?: string) => boolean;
658
- removeLinkByKey: (linkNodeKey: string) => boolean;
659
- };
660
- /**
661
- * State queries exposed by the link extension.
662
- */
663
- type LinkStateQueries = {
664
- isLink: () => Promise<boolean>;
665
- isTextSelected: () => Promise<boolean>;
666
- };
667
- /**
668
- * Link extension for creating and managing hyperlinks.
669
- *
670
- * Features:
671
- * - Manual link creation via commands
672
- * - Built-in paste handling (creates links when pasting URLs)
673
- * - Optional auto-linking while typing
674
- * - Click to follow links, click again to edit
675
- *
676
- * Uses Lexical's built-in LinkPlugin which handles:
677
- * - Pasting URLs over selected text (converts selection to a link)
678
- * - Pasting URLs at the cursor (creates a new link)
679
- * - Link editing and validation
680
- *
681
- * @example
682
- * ```tsx
683
- * const extensions = [
684
- * linkExtension.configure({
685
- * autoLinkText: true, // Optional: auto-link while typing
686
- * autoLinkUrls: true, // Optional: auto-link pasted URLs
687
- * linkSelectedTextOnPaste: false // Optional: replace selected text rather than linking it
688
- * })
689
- * ] as const;
690
- *
691
- * function MyEditor() {
692
- * const { commands, activeStates } = useEditor();
693
- * return (
694
- * <button
695
- * onClick={() => commands.insertLink()}
696
- * className={activeStates.isLink ? 'active' : ''}
697
- * >
698
- * Link
699
- * </button>
700
- * );
701
- * }
702
- * ```
703
- */
704
- declare class LinkExtension extends BaseExtension<"link", LinkConfig, LinkCommands, LinkStateQueries, React__default.ReactElement[]> {
705
- private lastSelectedLinkNodeKey;
706
- /**
707
- * Creates a new link extension instance.
708
- */
709
- constructor();
710
- /**
711
- * Registers the extension with the editor.
712
- * Configures URL paste handling.
713
- */
714
- register(editor: LexicalEditor): () => void;
715
- /**
716
- * Returns Lexical nodes exposed by this extension.
717
- */
718
- getNodes(): any[];
719
- /**
720
- * Returns React plugins exposed by this extension.
721
- */
722
- getPlugins(): React__default.ReactElement[];
723
- /**
724
- * Returns command handlers exposed by this extension.
725
- */
726
- getCommands(editor: LexicalEditor): LinkCommands;
727
- private serializeLinkNode;
728
- private removeLinkNode;
729
- private getLinkNodeByKey;
730
- private getSelectedLinkNode;
731
- private getCachedLinkNode;
732
- /**
733
- * Returns state query functions exposed by this extension.
734
- */
735
- getStateQueries(editor: LexicalEditor): LinkStateQueries;
736
- }
737
- /**
738
- * Preconfigured link extension instance.
739
- * Ready for use in extension arrays.
740
- */
741
- declare const linkExtension: LinkExtension;
742
-
743
- /**
744
- * Commands exposed by the horizontal rule extension.
745
- */
746
- type HorizontalRuleCommands = {
747
- insertHorizontalRule: () => void;
748
- };
749
- /**
750
- * State queries exposed by the horizontal rule extension.
751
- */
752
- type HorizontalRuleStateQueries = {
753
- isHorizontalRuleSelected: () => Promise<boolean>;
754
- };
755
- /**
756
- * Horizontal rule extension for inserting dividers.
757
- * Provides commands to insert and manage horizontal rules in the editor.
758
- *
759
- * @example
760
- * ```tsx
761
- * const extensions = [horizontalRuleExtension] as const;
762
- * const { Provider, useEditor } = createEditorSystem<typeof extensions>();
763
- *
764
- * function MyEditor() {
765
- * const { commands } = useEditor();
766
- * return (
767
- * <button onClick={() => commands.insertHorizontalRule()}>
768
- * Insert HR
769
- * </button>
770
- * );
771
- * }
772
- * ```
773
- */
774
- declare class HorizontalRuleExtension extends BaseExtension<"horizontalRule", any, HorizontalRuleCommands, HorizontalRuleStateQueries, React__default.ReactElement[]> {
775
- /**
776
- * Creates a new horizontal rule extension.
777
- */
778
- constructor();
779
- /**
780
- * Registers the extension with the editor.
781
- * No special registration needed because Lexical handles HR commands.
782
- *
783
- * @param editor - Lexical editor instance
784
- * @returns Cleanup function
785
- */
786
- register(editor: LexicalEditor): () => void;
787
- /**
788
- * Returns Lexical nodes provided by this extension.
789
- *
790
- * @returns Array containing the HorizontalRuleNode
791
- */
792
- getNodes(): any[];
793
- /**
794
- * Returns React plugins provided by this extension.
795
- *
796
- * @returns Array containing the HorizontalRulePlugin
797
- */
798
- getPlugins(): React__default.ReactElement[];
799
- /**
800
- * Returns commands exposed by this extension.
801
- *
802
- * @param editor - Lexical editor instance
803
- * @returns Object with horizontal rule command functions
804
- */
805
- getCommands(editor: LexicalEditor): HorizontalRuleCommands;
806
- /**
807
- * Returns state query functions exposed by this extension.
808
- *
809
- * @param editor - Lexical editor instance
810
- * @returns Object with horizontal rule state query functions
811
- */
812
- getStateQueries(editor: LexicalEditor): HorizontalRuleStateQueries;
813
- }
814
- /**
815
- * Preconfigured horizontal rule extension instance.
816
- * Ready for use in extension arrays.
817
- */
818
- declare const horizontalRuleExtension: HorizontalRuleExtension;
819
-
820
- type FontFamilyOption = {
821
- value: string;
822
- label: string;
823
- fontFamily: string;
824
- cssImportUrl?: string;
825
- };
826
- type FontCssLoadStrategy = "none" | "preload-all" | "on-demand";
827
- interface FontFamilyConfig extends BaseExtensionConfig {
828
- options: readonly FontFamilyOption[];
829
- cssLoadStrategy: FontCssLoadStrategy;
830
- }
831
- type FontFamilyCommands = {
832
- setFontFamily: (fontValue: string) => void;
833
- clearFontFamily: () => void;
834
- getCurrentFontFamily: () => Promise<string | null>;
835
- getFontFamilyOptions: () => readonly FontFamilyOption[];
836
- };
837
- type FontFamilyStateQueries = {
838
- hasCustomFontFamily: () => Promise<boolean>;
839
- };
840
- /**
841
- * FontFamilyExtension provides controlled font-family styling for text selections.
842
- *
843
- * Fonts are only applied from a configured whitelist (`config.options`).
844
- * Optional CSS font loading can be configured via `cssLoadStrategy`:
845
- * - "none": do not load external CSS
846
- * - "preload-all": load all option `cssImportUrl` values on register
847
- * - "on-demand": load a font's `cssImportUrl` when it is first selected
848
- */
849
- declare class FontFamilyExtension extends BaseExtension<"fontFamily", FontFamilyConfig, FontFamilyCommands, FontFamilyStateQueries> {
850
- private readonly loadedFontUrls;
851
- constructor();
852
- register(): () => void;
853
- configure(config: Partial<FontFamilyConfig>): Extension<"fontFamily", FontFamilyConfig, FontFamilyCommands, FontFamilyStateQueries, React$1.ReactNode[]>;
854
- getCommands(editor: LexicalEditor): FontFamilyCommands;
855
- getStateQueries(editor: LexicalEditor): FontFamilyStateQueries;
856
- private applyFontFamily;
857
- private hasCustomFontFamily;
858
- private getCurrentFontFamilyValue;
859
- private findOption;
860
- private normalizeFontValue;
861
- private ensureFontCssLoaded;
862
- }
863
- declare const fontFamilyExtension: FontFamilyExtension;
864
-
865
- type FontSizeOption = {
866
- value: string;
867
- label: string;
868
- fontSize: string;
869
- };
870
- interface FontSizeConfig extends BaseExtensionConfig {
871
- options: readonly FontSizeOption[];
872
- }
873
- type FontSizeCommands = {
874
- setFontSize: (fontSizeValue: string) => void;
875
- clearFontSize: () => void;
876
- getCurrentFontSize: () => Promise<string | null>;
877
- getFontSizeOptions: () => readonly FontSizeOption[];
878
- };
879
- type FontSizeStateQueries = {
880
- hasCustomFontSize: () => Promise<boolean>;
881
- };
882
- declare class FontSizeExtension extends BaseExtension<"fontSize", FontSizeConfig, FontSizeCommands, FontSizeStateQueries> {
883
- constructor();
884
- register(): () => void;
885
- configure(config: Partial<FontSizeConfig>): Extension<"fontSize", FontSizeConfig, FontSizeCommands, FontSizeStateQueries, React$1.ReactNode[]>;
886
- getCommands(editor: LexicalEditor): FontSizeCommands;
887
- getStateQueries(editor: LexicalEditor): FontSizeStateQueries;
888
- private applyFontSize;
889
- private hasCustomFontSize;
890
- private getCurrentFontSizeValue;
891
- private findOption;
892
- private normalizeValue;
893
- }
894
- declare const fontSizeExtension: FontSizeExtension;
895
-
896
- type LineHeightOption = {
897
- value: string;
898
- label: string;
899
- lineHeight: string;
900
- };
901
- interface LineHeightConfig extends BaseExtensionConfig {
902
- options: readonly LineHeightOption[];
903
- defaultLineHeight: string;
904
- }
905
- type LineHeightCommands = {
906
- setLineHeight: (lineHeightValue: string) => void;
907
- clearLineHeight: () => void;
908
- getCurrentLineHeight: () => Promise<string | null>;
909
- getLineHeightOptions: () => readonly LineHeightOption[];
910
- };
911
- type LineHeightStateQueries = {
912
- hasCustomLineHeight: () => Promise<boolean>;
913
- };
914
- declare class LineHeightExtension extends BaseExtension<"lineHeight", LineHeightConfig, LineHeightCommands, LineHeightStateQueries> {
915
- constructor();
916
- register(): () => void;
917
- configure(config: Partial<LineHeightConfig>): Extension<"lineHeight", LineHeightConfig, LineHeightCommands, LineHeightStateQueries, React$1.ReactNode[]>;
918
- getCommands(editor: LexicalEditor): LineHeightCommands;
919
- getStateQueries(editor: LexicalEditor): LineHeightStateQueries;
920
- private applyLineHeight;
921
- private getSelectedTopLevelBlocks;
922
- private withStyleProperty;
923
- private hasCustomLineHeight;
924
- private getCurrentLineHeightValue;
925
- private getSelectedBlocksLineHeight;
926
- private findOption;
927
- private normalizeValue;
928
- private readStyleProperty;
929
- }
930
- declare const lineHeightExtension: LineHeightExtension;
931
-
932
- type TextColorOption = {
933
- value: string;
934
- label: string;
935
- color: string;
936
- };
937
- interface TextColorConfig extends BaseExtensionConfig {
938
- options: readonly TextColorOption[];
939
- }
940
- type TextColorCommands = {
941
- setTextColor: (colorValue: string) => void;
942
- clearTextColor: () => void;
943
- getCurrentTextColor: () => Promise<string | null>;
944
- getTextColorOptions: () => readonly TextColorOption[];
945
- };
946
- type TextColorStateQueries = {
947
- hasCustomTextColor: () => Promise<boolean>;
948
- };
949
- declare class TextColorExtension extends BaseExtension<"textColor", TextColorConfig, TextColorCommands, TextColorStateQueries> {
950
- constructor();
951
- register(): () => void;
952
- getCommands(editor: LexicalEditor): TextColorCommands;
953
- getStateQueries(editor: LexicalEditor): TextColorStateQueries;
954
- private applyColor;
955
- private hasCustomTextColor;
956
- private getCurrentTextColorValue;
957
- private findOption;
958
- private normalizeValue;
959
- private isValidCssColor;
960
- }
961
- declare const textColorExtension: TextColorExtension;
962
-
963
- type TextHighlightOption = {
964
- value: string;
965
- label: string;
966
- backgroundColor: string;
967
- };
968
- interface TextHighlightConfig extends BaseExtensionConfig {
969
- options: readonly TextHighlightOption[];
970
- }
971
- type TextHighlightCommands = {
972
- setTextHighlight: (highlightValue: string) => void;
973
- clearTextHighlight: () => void;
974
- getCurrentTextHighlight: () => Promise<string | null>;
975
- getTextHighlightOptions: () => readonly TextHighlightOption[];
976
- };
977
- type TextHighlightStateQueries = {
978
- hasTextHighlight: () => Promise<boolean>;
979
- };
980
- declare class TextHighlightExtension extends BaseExtension<"textHighlight", TextHighlightConfig, TextHighlightCommands, TextHighlightStateQueries> {
981
- constructor();
982
- register(): () => void;
983
- getCommands(editor: LexicalEditor): TextHighlightCommands;
984
- getStateQueries(editor: LexicalEditor): TextHighlightStateQueries;
985
- private applyHighlight;
986
- private hasTextHighlight;
987
- private getCurrentTextHighlightValue;
988
- private findOption;
989
- private normalizeValue;
990
- private isValidCssColor;
991
- }
992
- declare const textHighlightExtension: TextHighlightExtension;
993
-
994
- declare class SubscriptExtension extends TextFormatExtension<"subscript"> {
995
- constructor();
996
- }
997
- declare const subscriptExtension: SubscriptExtension;
998
-
999
- declare class SuperscriptExtension extends TextFormatExtension<"superscript"> {
1000
- constructor();
1001
- }
1002
- declare const superscriptExtension: SuperscriptExtension;
1003
-
1004
- /**
1005
- * Context menu item definition
1006
- */
1007
- type ContextMenuItem = {
1008
- label: string;
1009
- action: () => void;
1010
- icon?: React__default.ComponentType<{
1011
- size?: number;
1012
- className?: string;
1013
- }>;
1014
- disabled?: boolean;
1015
- separator?: boolean;
1016
- };
1017
- /**
1018
- * Context menu provider registered by extensions
1019
- */
1020
- type ContextMenuProvider = {
1021
- id: string;
1022
- priority?: number;
1023
- canHandle: (context: {
1024
- editor: LexicalEditor;
1025
- target: HTMLElement;
1026
- selection: any;
1027
- event: MouseEvent;
1028
- }) => boolean;
1029
- getItems: (context: {
1030
- editor: LexicalEditor;
1031
- target: HTMLElement;
1032
- selection: any;
1033
- event: MouseEvent;
1034
- }) => ContextMenuItem[];
1035
- renderer?: ContextMenuRenderer;
1036
- };
1037
- /**
1038
- * Context menu renderer function type
1039
- */
1040
- type ContextMenuRenderer = (props: {
1041
- items: ContextMenuItem[];
1042
- position: {
1043
- x: number;
1044
- y: number;
1045
- };
1046
- onClose: () => void;
1047
- className: string;
1048
- style?: React__default.CSSProperties;
1049
- itemClassName: string;
1050
- itemStyle?: React__default.CSSProperties;
1051
- disabledItemClassName: string;
1052
- disabledItemStyle?: React__default.CSSProperties;
1053
- }) => React__default.ReactElement;
1054
- /**
1055
- * Context menu configuration
1056
- */
1057
- interface ContextMenuConfig extends BaseExtensionConfig {
1058
- defaultRenderer?: ContextMenuRenderer;
1059
- preventDefault?: boolean;
1060
- theme?: {
1061
- container?: string;
1062
- item?: string;
1063
- itemDisabled?: string;
1064
- };
1065
- styles?: {
1066
- container?: React__default.CSSProperties;
1067
- item?: React__default.CSSProperties;
1068
- itemDisabled?: React__default.CSSProperties;
1069
- };
1070
- }
1071
- /**
1072
- * Commands exposed by the context menu extension
1073
- */
1074
- type ContextMenuCommands = {
1075
- registerProvider: (provider: ContextMenuProvider) => void;
1076
- unregisterProvider: (id: string) => void;
1077
- showContextMenu: (config: {
1078
- items: ContextMenuItem[];
1079
- position: {
1080
- x: number;
1081
- y: number;
1082
- };
1083
- renderer?: ContextMenuRenderer;
1084
- }) => void;
1085
- hideContextMenu: () => void;
1086
- };
1087
- /**
1088
- * State queries for context menus
1089
- */
1090
- type ContextMenuStateQueries = {
1091
- isContextMenuOpen: () => Promise<boolean>;
1092
- };
1093
- /**
1094
- * Context menu manager - handles provider registry and menu display
1095
- */
1096
- declare class ContextMenuManager {
1097
- private providers;
1098
- private currentMenu;
1099
- private listeners;
1100
- private editor;
1101
- private config;
1102
- constructor(editor: LexicalEditor, config?: ContextMenuConfig);
1103
- registerProvider(provider: ContextMenuProvider): void;
1104
- unregisterProvider(id: string): void;
1105
- handleContextMenu(event: MouseEvent): void;
1106
- showMenu(config: {
1107
- items: ContextMenuItem[];
1108
- position: {
1109
- x: number;
1110
- y: number;
1111
- };
1112
- renderer?: ContextMenuRenderer;
1113
- }): void;
1114
- hideMenu(): void;
1115
- getCurrentMenu(): {
1116
- items: ContextMenuItem[];
1117
- position: {
1118
- x: number;
1119
- y: number;
1120
- };
1121
- renderer?: ContextMenuRenderer;
1122
- } | null;
1123
- subscribe(listener: (menu: typeof this.currentMenu) => void): () => void;
1124
- private notifyListeners;
1125
- }
1126
- /**
1127
- * Context menu extension - provides a clean, registry-based context menu system
1128
- */
1129
- declare class ContextMenuExtension extends BaseExtension<"contextMenu", ContextMenuConfig, ContextMenuCommands, ContextMenuStateQueries, React__default.ReactElement[]> {
1130
- manager: ContextMenuManager | null;
1131
- private pendingListeners;
1132
- constructor(config?: ContextMenuConfig);
1133
- configure(config: Partial<ContextMenuConfig>): this;
1134
- register(editor: LexicalEditor): () => void;
1135
- getCommands(editor: LexicalEditor): ContextMenuCommands;
1136
- getStateQueries(editor: LexicalEditor): ContextMenuStateQueries;
1137
- getPlugins(): React__default.ReactElement[];
1138
- subscribe(listener: (menu: any) => void): () => void;
1139
- }
1140
- declare const contextMenuExtension: ContextMenuExtension;
1141
-
1142
- /**
1143
- * Table extension configuration options.
1144
- */
1145
- type TableConfig = BaseExtensionConfig & {
1146
- rows?: number;
1147
- columns?: number;
1148
- includeHeaders?: boolean;
1149
- /** Enable right-click context menu */
1150
- enableContextMenu?: boolean;
1151
- /** Custom context menu items - static list or a function that receives commands */
1152
- contextMenuItems?: ContextMenuItem[] | ((commands: TableCommands) => ContextMenuItem[]);
1153
- /** Custom context menu renderer for full headless control */
1154
- contextMenuRenderer?: ContextMenuRenderer;
1155
- /** Context menu extension used to register providers */
1156
- contextMenuExtension?: typeof contextMenuExtension;
1157
- /** Custom table bubble menu renderer */
1158
- tableBubbleRenderer?: (props: TableBubbleRenderProps) => ReactNode;
1159
- };
1160
- type TableBubbleRenderProps = {
1161
- headersEnabled: boolean;
1162
- setHeadersEnabled: (enabled: boolean) => void;
1163
- actions: {
1164
- insertRowAbove: () => void;
1165
- insertRowBelow: () => void;
1166
- insertColumnLeft: () => void;
1167
- insertColumnRight: () => void;
1168
- deleteSelectedColumn: () => void;
1169
- deleteSelectedRow: () => void;
1170
- deleteTable: () => void;
1171
- };
1172
- };
1173
- /**
1174
- * Commands exposed by the Table extension.
1175
- */
1176
- type TableCommands = {
1177
- insertTable: (config: {
1178
- rows?: number;
1179
- columns?: number;
1180
- includeHeaders?: boolean;
1181
- }) => void;
1182
- insertRowAbove: () => void;
1183
- insertRowBelow: () => void;
1184
- insertColumnLeft: () => void;
1185
- insertColumnRight: () => void;
1186
- toggleRowHeader: () => void;
1187
- toggleColumnHeader: () => void;
1188
- mergeSelectedCells: () => void;
1189
- unmergeSelectedCell: () => void;
1190
- deleteRow: () => void;
1191
- deleteColumn: () => void;
1192
- deleteTable: () => void;
1193
- showTableContextMenu: (position: {
1194
- x: number;
1195
- y: number;
1196
- }) => void;
1197
- };
1198
- /**
1199
- * State queries exposed by the Table extension.
1200
- */
1201
- type TableStateQueries = {
1202
- isTableSelected: () => Promise<boolean>;
1203
- isInTableCell: () => Promise<boolean>;
1204
- };
1205
- /**
1206
- * Table extension for table operations in the editor.
1207
- * Provides commands for inserting and manipulating tables.
1208
- */
1209
- declare class TableExtension extends BaseExtension<"table", TableConfig, TableCommands, TableStateQueries, ReactNode[]> {
1210
- getContextMenuItems(commands: TableCommands): ContextMenuItem[];
1211
- private defaultContextMenuItems;
1212
- constructor(config?: Partial<TableConfig>);
1213
- configure(config: Partial<TableConfig>): this;
1214
- register(editor: LexicalEditor): () => void;
1215
- getNodes(): any[];
1216
- getCommands(editor: LexicalEditor): TableCommands;
1217
- getStateQueries(editor: LexicalEditor): TableStateQueries;
1218
- getPlugins(): ReactNode[];
1219
- }
1220
- /**
1221
- * Preconfigured Table extension instance.
1222
- * Ready for use in extension arrays.
1223
- */
1224
- declare const tableExtension: TableExtension;
1225
-
1226
- /**
1227
- * Commands exposed by the list extension.
1228
- */
1229
- type ListCommands = {
1230
- /** Toggle a bullet list for the current selection */
1231
- toggleUnorderedList: () => void;
1232
- /** Toggle a numbered list for the current selection */
1233
- toggleOrderedList: () => void;
1234
- /** Toggle a checklist for the current selection */
1235
- toggleCheckList: () => void;
1236
- /** Indent the current list item (nest deeper) */
1237
- indentList: () => void;
1238
- /** Outdent the current list item (unnest) */
1239
- outdentList: () => void;
1240
- /** Create a nested bullet list at the current selection */
1241
- insertNestedUnorderedList: () => void;
1242
- /** Create a nested numbered list at the current selection */
1243
- insertNestedOrderedList: () => void;
1244
- };
1245
- /**
1246
- * List extension for managing ordered and unordered lists.
1247
- * Provides functionality to convert paragraphs to lists and vice versa.
1248
- *
1249
- * @example
1250
- * ```tsx
1251
- * const extensions = [listExtension] as const;
1252
- * const { Provider, useEditor } = createEditorSystem<typeof extensions>();
1253
- *
1254
- * function MyEditor() {
1255
- * const { commands, activeStates } = useEditor();
1256
- * return (
1257
- * <div>
1258
- * <button
1259
- * onClick={() => commands.toggleUnorderedList()}
1260
- * className={activeStates.unorderedList ? 'active' : ''}
1261
- * >
1262
- * Bullet List
1263
- * </button>
1264
- * <button
1265
- * onClick={() => commands.toggleOrderedList()}
1266
- * className={activeStates.orderedList ? 'active' : ''}
1267
- * >
1268
- * Numbered List
1269
- * </button>
1270
- * <button onClick={() => commands.indentList()}>Indent</button>
1271
- * <button onClick={() => commands.outdentList()}>Outdent</button>
1272
- * <button onClick={() => commands.insertNestedUnorderedList()}>Nested Bullet</button>
1273
- * <button onClick={() => commands.insertNestedOrderedList()}>Nested Numbered</button>
1274
- * </div>
1275
- * );
1276
- * }
1277
- * ```
1278
- */
1279
- declare class ListExtension extends BaseExtension<"list", any, ListCommands, {
1280
- unorderedList: () => Promise<boolean>;
1281
- orderedList: () => Promise<boolean>;
1282
- checkList: () => Promise<boolean>;
1283
- }, ReactNode[]> {
1284
- /**
1285
- * Creates a new list extension instance.
1286
- */
1287
- constructor();
1288
- /**
1289
- * Registers the extension with Lexical.
1290
- * No special registration needed because Lexical handles list commands.
1291
- *
1292
- * @param editor - Lexical editor instance
1293
- * @returns Cleanup function (no-op for lists)
1294
- */
1295
- register(editor: LexicalEditor): () => void;
1296
- /**
1297
- * Returns Lexical nodes needed for list functionality.
1298
- *
1299
- * @returns Array containing ListNode and ListItemNode
1300
- */
1301
- getNodes(): (typeof ListNode | typeof ListItemNode)[];
1302
- /**
1303
- * Returns React plugins needed for list functionality.
1304
- *
1305
- * @returns Array containing the ListPlugin component
1306
- */
1307
- getPlugins(): ReactNode[];
1308
- /**
1309
- * Returns command handlers exposed by this extension.
1310
- *
1311
- * @param editor - Lexical editor instance
1312
- * @returns Object containing list toggle commands
1313
- */
1314
- getCommands(editor: LexicalEditor): ListCommands;
1315
- /**
1316
- * Returns state query functions for list state.
1317
- *
1318
- * @param editor - Lexical editor instance
1319
- * @returns Object containing state query functions for list types
1320
- */
1321
- getStateQueries(editor: LexicalEditor): {
1322
- unorderedList: () => Promise<boolean>;
1323
- orderedList: () => Promise<boolean>;
1324
- checkList: () => Promise<boolean>;
1325
- };
1326
- }
1327
- /**
1328
- * Preconfigured list extension instance.
1329
- * Ready for use in extension arrays.
1330
- */
1331
- declare const listExtension: ListExtension;
1332
-
1333
- type CodeTokenizer = {
1334
- defaultLanguage: string;
1335
- tokenize: (code: string, language?: string) => unknown[];
1336
- };
1337
- type CodeHighlightResult = {
1338
- language?: string | null;
1339
- };
1340
- type CodeHighlightProvider = {
1341
- highlightAuto?: (code: string, languageSubset?: string[]) => CodeHighlightResult | Promise<CodeHighlightResult>;
1342
- tokenizer?: CodeTokenizer | null;
1343
- getTokenizer?: () => CodeTokenizer | null | Promise<CodeTokenizer | null>;
1344
- };
1345
- type CodeHighlightProviderConfig = {
1346
- provider?: CodeHighlightProvider | null;
1347
- loadProvider?: () => Promise<CodeHighlightProvider | null>;
1348
- };
1349
-
1350
- /**
1351
- * Commands exposed by the CodeExtension for toggling code blocks
1352
- */
1353
- type CodeCommands = {
1354
- /** Toggle code block vs paragraph for the current selection */
1355
- toggleCodeBlock: () => void;
1356
- };
1357
- /**
1358
- * State queries exposed by the CodeExtension for checking code block status
1359
- */
1360
- type CodeStateQueries = {
1361
- /** Check whether the current selection is within a code block */
1362
- isInCodeBlock: () => Promise<boolean>;
1363
- };
1364
- type CodeExtensionConfig = BaseExtensionConfig & CodeHighlightProviderConfig & {
1365
- syntaxHighlighting?: "auto" | "disabled";
1366
- tokenizer?: CodeTokenizer | null;
1367
- };
1368
- /**
1369
- * CodeExtension - Adds code block support for the Lexical editor
1370
- *
1371
- * Enables users to create and manage code blocks in the editor.
1372
- * Provides commands to toggle between code blocks and paragraphs,
1373
- * plus state queries to check whether the selection is in a code block.
1374
- *
1375
- * Integrates with Lexical's CodeNode and provides a clean API
1376
- * for toolbar integration and programmatic control.
1377
- *
1378
- * @example
1379
- * ```tsx
1380
- * import { codeExtension } from '@lyfie/luthor-headless/extensions/formatting/CodeExtension';
1381
- *
1382
- * const extensions = [codeExtension];
1383
- * const editor = createEditorSystem(extensions);
1384
- *
1385
- * // Use in a component
1386
- * const { commands } = useEditor();
1387
- * commands.toggleCodeBlock(); // Toggle code block on or off
1388
- * ```
1389
- */
1390
- declare class CodeExtension extends BaseExtension<"code", CodeExtensionConfig, CodeCommands, CodeStateQueries, ReactNode[]> {
1391
- private codeHighlightProviderPromise;
1392
- constructor();
1393
- /**
1394
- * Register the extension with Lexical
1395
- * @param editor - Lexical editor instance
1396
- * @returns Cleanup function
1397
- */
1398
- register(editor: LexicalEditor): () => void;
1399
- /**
1400
- * Get Lexical nodes required by this extension
1401
- * @returns Array of node classes
1402
- */
1403
- getNodes(): (typeof CodeNode | typeof CodeHighlightNode)[];
1404
- /**
1405
- * Get commands exposed by this extension
1406
- * @param editor - Lexical editor instance
1407
- * @returns Object containing available commands
1408
- */
1409
- getCommands(editor: LexicalEditor): CodeCommands;
1410
- /**
1411
- * Toggle between code block and paragraph for the selection
1412
- * @param editor - Lexical editor instance
1413
- */
1414
- private toggleCodeBlock;
1415
- private resolveConfiguredTokenizer;
1416
- private loadCodeHighlightProvider;
1417
- /**
1418
- * Get state queries exposed by this extension
1419
- * @param editor - Lexical editor instance
1420
- * @returns Object containing available state queries
1421
- */
1422
- getStateQueries(editor: LexicalEditor): CodeStateQueries;
1423
- /**
1424
- * Check whether the current selection matches the specified format
1425
- * @param format - Format to check for (currently only 'code')
1426
- * @param editor - Lexical editor instance
1427
- * @returns True if all selected nodes match the format
1428
- */
1429
- private isFormat;
1430
- /**
1431
- * Get the nearest block node from the given node
1432
- * @param node - Starting node
1433
- * @returns Nearest CodeNode or null
1434
- */
1435
- private getBlockNode;
1436
- /**
1437
- * Get the format type of a given node
1438
- * @param node - Node to check
1439
- * @returns Format type or null
1440
- */
1441
- private getNodeFormat;
1442
- /**
1443
- * Get the current format synchronously (for use inside editor.update())
1444
- * @returns Current format or null
1445
- */
1446
- private getCurrentFormatSync;
1447
- }
1448
- declare const codeExtension: CodeExtension;
1449
-
1450
- type CodeIntelligenceCommands = {
1451
- setCodeLanguage: (language: string) => void;
1452
- autoDetectCodeLanguage: () => Promise<string | null>;
1453
- getCurrentCodeLanguage: () => Promise<string | null>;
1454
- getCodeLanguageOptions: () => string[];
1455
- copySelectedCodeBlock: () => Promise<boolean>;
1456
- };
1457
- type CodeLanguageOptionsMode = "append" | "replace";
1458
- type CodeLanguageOptionsConfig = {
1459
- mode?: CodeLanguageOptionsMode;
1460
- values: readonly string[];
1461
- };
1462
- type CodeIntelligenceConfig = CodeHighlightProviderConfig & {
1463
- maxAutoDetectLength?: number;
1464
- isCopyAllowed?: boolean;
1465
- languageOptions?: readonly string[] | CodeLanguageOptionsConfig;
1466
- };
1467
- declare class CodeIntelligenceExtension extends BaseExtension<"codeIntelligence", CodeIntelligenceConfig, CodeIntelligenceCommands, Record<string, never>, ReactNode[]> {
1468
- private languageOptions;
1469
- constructor();
1470
- register(editor: LexicalEditor): () => void;
1471
- getPlugins(): ReactNode[];
1472
- getCommands(editor: LexicalEditor): CodeIntelligenceCommands;
1473
- isCopyAllowed(): boolean;
1474
- getLanguageOptionsSnapshot(): string[];
1475
- getCodeBlocksSnapshot(editor: LexicalEditor): CodeBlockSnapshot[];
1476
- setCodeBlockLanguage(editor: LexicalEditor, nodeKey: string, selectedLanguage: string): void;
1477
- getCodeBlockText(editor: LexicalEditor, nodeKey: string): string;
1478
- private getThemeForLanguage;
1479
- private ensureCodeBlockThemes;
1480
- private getSelectionCodeNodes;
1481
- private getNearestCodeNode;
1482
- private getLanguageOptions;
1483
- private getPrimaryCodeBlockText;
1484
- }
1485
- type CodeBlockSnapshot = {
1486
- key: string;
1487
- language: string;
1488
- text: string;
1489
- };
1490
- declare const codeIntelligenceExtension: CodeIntelligenceExtension;
1491
-
1492
- /**
1493
- * CodeFormatExtension - Provides inline code text formatting functionality
1494
- *
1495
- * This extension extends TextFormatExtension to provide inline code formatting
1496
- * for selected text in the Lexical editor. It integrates with the toolbar system
1497
- * and provides commands and state queries for inline code operations.
1498
- *
1499
- * @example
1500
- * ```tsx
1501
- * import { codeFormatExtension } from '@lyfie/luthor-headless/extensions/formatting/CodeFormatExtension';
1502
- *
1503
- * const extensions = [codeFormatExtension];
1504
- * const editor = createEditorSystem(extensions);
1505
- * ```
1506
- */
1507
- declare class CodeFormatExtension extends TextFormatExtension<"code"> {
1508
- constructor();
1509
- }
1510
- declare const codeFormatExtension: CodeFormatExtension;
1511
-
1512
- /**
1513
- * Supported block formats for BlockFormatExtension
1514
- */
1515
- type BlockFormat = "p" | HeadingTagType | "quote";
1516
- /**
1517
- * Commands exposed by BlockFormatExtension for block-level formatting
1518
- */
1519
- type BlockFormatCommands = {
1520
- /** Switch to a specific block format */
1521
- toggleBlockFormat: (format: BlockFormat) => void;
1522
- /** Switch to paragraph format */
1523
- toggleParagraph: () => void;
1524
- /** Switch to a heading format */
1525
- toggleHeading: (tag: HeadingTagType) => void;
1526
- /** Switch to quote format */
1527
- toggleQuote: () => void;
1528
- /** Set text alignment for selected blocks */
1529
- setTextAlignment: (alignment: "left" | "center" | "right" | "justify") => void;
1530
- /** Return the current block type as a string ('p', 'h1', 'h2', etc.) */
1531
- getCurrentBlockType: () => BlockFormat;
1532
- };
1533
- /**
1534
- * State queries exposed by BlockFormatExtension for checking block formats
1535
- */
1536
- type BlockFormatStateQueries = {
1537
- /** Check whether the selection is in a paragraph */
1538
- isParagraph: () => Promise<boolean>;
1539
- /** Check whether the selection is in an H1 heading */
1540
- isH1: () => Promise<boolean>;
1541
- /** Check whether the selection is in an H2 heading */
1542
- isH2: () => Promise<boolean>;
1543
- /** Check whether the selection is in an H3 heading */
1544
- isH3: () => Promise<boolean>;
1545
- /** Check whether the selection is in an H4 heading */
1546
- isH4: () => Promise<boolean>;
1547
- /** Check whether the selection is in an H5 heading */
1548
- isH5: () => Promise<boolean>;
1549
- /** Check whether the selection is in an H6 heading */
1550
- isH6: () => Promise<boolean>;
1551
- /** Check whether the selection is in a quote block */
1552
- isQuote: () => Promise<boolean>;
1553
- /** Check whether selected blocks are left-aligned */
1554
- isTextAlignedLeft: () => Promise<boolean>;
1555
- /** Check whether selected blocks are center-aligned */
1556
- isTextAlignedCenter: () => Promise<boolean>;
1557
- /** Check whether selected blocks are right-aligned */
1558
- isTextAlignedRight: () => Promise<boolean>;
1559
- /** Check whether selected blocks are justified */
1560
- isTextAlignedJustify: () => Promise<boolean>;
1561
- };
1562
- /**
1563
- * BlockFormatExtension - Provides block-level formatting
1564
- *
1565
- * Enables users to change block-level elements like paragraphs,
1566
- * headings (H1-H6), and quotes. Provides a comprehensive set of commands
1567
- * for switching between formats and state queries for checking
1568
- * the current block format.
1569
- *
1570
- * The extension supports true toggling - applying the same format
1571
- * again reverts to a paragraph.
1572
- *
1573
- * @example
1574
- * ```tsx
1575
- * import { blockFormatExtension } from '@lyfie/luthor-headless/extensions/formatting/BlockTypeExtension';
1576
- *
1577
- * const extensions = [blockFormatExtension];
1578
- * const editor = createEditorSystem(extensions);
1579
- *
1580
- * // Use in a component
1581
- * const { commands } = useEditor();
1582
- * commands.toggleHeading('h1'); // Switch selection to H1
1583
- * commands.toggleQuote(); // Convert selection to a quote block
1584
- * ```
1585
- */
1586
- declare class BlockFormatExtension extends BaseExtension<"blockFormat", Record<string, never>, BlockFormatCommands, BlockFormatStateQueries> {
1587
- constructor();
1588
- /**
1589
- * Register the extension with Lexical
1590
- * @param editor - Lexical editor instance
1591
- * @returns Cleanup function
1592
- */
1593
- register(editor: LexicalEditor): () => void;
1594
- /**
1595
- * Get Lexical nodes required by this extension
1596
- * @returns Array of node classes
1597
- */
1598
- getNodes(): (typeof ParagraphNode | typeof HeadingNode | typeof QuoteNode)[];
1599
- /**
1600
- * Get commands exposed by this extension
1601
- * @param editor - Lexical editor instance
1602
- * @returns Object containing available commands
1603
- */
1604
- getCommands(editor: LexicalEditor): BlockFormatCommands;
1605
- /**
1606
- * Set element alignment for selected blocks
1607
- * @param editor - Lexical editor instance
1608
- * @param alignment - Target text alignment
1609
- */
1610
- private setTextAlignment;
1611
- /**
1612
- * Toggle the block format for the current selection
1613
- * @param editor - Lexical editor instance
1614
- * @param format - Target block format
1615
- */
1616
- private toggleBlockFormat;
1617
- /**
1618
- * Get the state queries provided by this extension
1619
- * @param editor - Lexical editor instance
1620
- * @returns Object containing available state queries
1621
- */
1622
- getStateQueries(editor: LexicalEditor): BlockFormatStateQueries;
1623
- /**
1624
- * Check whether all selected blocks match the specified alignment
1625
- * @param alignment - Alignment to check
1626
- * @param editor - Lexical editor instance
1627
- * @returns True if all selected blocks match the alignment
1628
- */
1629
- private isAlignment;
1630
- private normalizeAlignment;
1631
- /**
1632
- * Get the nearest block node starting from the given node
1633
- * @param node - Starting node
1634
- * @returns Nearest block node or null
1635
- */
1636
- private getBlockNode;
1637
- /**
1638
- * Check whether all blocks in the current selection match the specified format
1639
- * @param format - Format to check for
1640
- * @param editor - Lexical editor instance
1641
- * @returns True if all selected blocks match the format
1642
- */
1643
- private isFormat;
1644
- /**
1645
- * Get the format type for a block node
1646
- * @param node - Block node to check
1647
- * @returns Format type or null
1648
- */
1649
- private getNodeFormat;
1650
- /**
1651
- * Get the current block format for the selection
1652
- * @param editor - Lexical editor instance
1653
- * @returns Current format or null
1654
- */
1655
- private getCurrentFormat;
1656
- /**
1657
- * Get the current block format synchronously (for use inside editor.update())
1658
- * @returns Current format or null
1659
- */
1660
- private getCurrentFormatSync;
1661
- }
1662
- declare const blockFormatExtension: BlockFormatExtension;
1663
-
1664
- /**
1665
- * Commands exposed by the history extension.
1666
- */
1667
- type HistoryCommands = {
1668
- /** Undo the most recent action */
1669
- undo: () => void;
1670
- /** Redo the most recently undone action */
1671
- redo: () => void;
1672
- /** Clear the full history stack */
1673
- clearHistory: () => void;
1674
- };
1675
- /**
1676
- * History extension that provides undo/redo functionality.
1677
- * Integrates with Lexical's built-in history system to offer
1678
- * undo and redo capabilities with state tracking.
1679
- *
1680
- * @example
1681
- * ```tsx
1682
- * const extensions = [historyExtension] as const;
1683
- * const { Provider, useEditor } = createEditorSystem<typeof extensions>();
1684
- *
1685
- * function MyEditor() {
1686
- * const { commands, activeStates } = useEditor();
1687
- * return (
1688
- * <div>
1689
- * <button
1690
- * onClick={() => commands.undo()}
1691
- * disabled={!activeStates.canUndo}
1692
- * >
1693
- * Undo
1694
- * </button>
1695
- * <button
1696
- * onClick={() => commands.redo()}
1697
- * disabled={!activeStates.canRedo}
1698
- * >
1699
- * Redo
1700
- * </button>
1701
- * </div>
1702
- * );
1703
- * }
1704
- * ```
1705
- */
1706
- declare class HistoryExtension extends BaseExtension<"history", any, HistoryCommands, {
1707
- canUndo: () => Promise<boolean>;
1708
- canRedo: () => Promise<boolean>;
1709
- }, ReactNode[]> {
1710
- private canUndoState;
1711
- private canRedoState;
1712
- /**
1713
- * Creates a new history extension.
1714
- */
1715
- constructor();
1716
- /**
1717
- * Registers the extension with the Lexical editor.
1718
- * Sets up listeners for undo/redo state changes.
1719
- *
1720
- * @param editor - Lexical editor instance
1721
- * @returns Cleanup function
1722
- */
1723
- register(editor: LexicalEditor): () => void;
1724
- /**
1725
- * Returns React plugins required for history support.
1726
- *
1727
- * @returns Array containing the HistoryPlugin component
1728
- */
1729
- getPlugins(): ReactNode[];
1730
- /**
1731
- * Returns commands exposed by this extension.
1732
- *
1733
- * @param editor - Lexical editor instance
1734
- * @returns Object containing history commands
1735
- */
1736
- getCommands(editor: LexicalEditor): HistoryCommands;
1737
- /**
1738
- * Returns state query functions for undo/redo availability.
1739
- *
1740
- * @param editor - Lexical editor instance
1741
- * @returns Object containing state query functions
1742
- */
1743
- getStateQueries(editor: LexicalEditor): {
1744
- canUndo: () => Promise<boolean>;
1745
- canRedo: () => Promise<boolean>;
1746
- };
1747
- }
1748
- /**
1749
- * Preconfigured history extension instance.
1750
- * Ready for use in extension arrays.
1751
- */
1752
- declare const historyExtension: HistoryExtension;
1753
-
1754
- /**
1755
- * DraggableBlockExtension configuration
1756
- */
1757
- interface DraggableConfig extends BaseExtensionConfig {
1758
- /** Portal anchor element (default: document.body) */
1759
- anchorElem?: HTMLElement;
1760
- /** Show the add button near the drag handle */
1761
- showAddButton?: boolean;
1762
- /** Button stack position relative to blocks */
1763
- buttonStackPosition?: "left" | "right";
1764
- /** Allow drag via text selection (default: true) */
1765
- enableTextSelectionDrag?: boolean;
1766
- /** Left offset */
1767
- offsetLeft?: number;
1768
- /** Right offset */
1769
- offsetRight?: number;
1770
- /** Theme class names */
1771
- theme?: {
1772
- handle?: string;
1773
- handleActive?: string;
1774
- blockDragging?: string;
1775
- dropIndicator?: string;
1776
- addButton?: string;
1777
- buttonStack?: string;
1778
- };
1779
- /** Custom styles for UI elements */
1780
- styles?: {
1781
- handle?: React__default.CSSProperties;
1782
- handleActive?: React__default.CSSProperties;
1783
- blockDragging?: React__default.CSSProperties;
1784
- dropIndicator?: React__default.CSSProperties;
1785
- addButton?: React__default.CSSProperties;
1786
- buttonStack?: React__default.CSSProperties;
1787
- };
1788
- /** Custom handle renderer for full headless control */
1789
- handleRenderer?: (props: {
1790
- rect: DOMRect;
1791
- isDragging: boolean;
1792
- onDragStart: (e: React__default.DragEvent) => void;
1793
- className: string;
1794
- }) => ReactNode;
1795
- /** Custom up/down button renderer */
1796
- buttonsRenderer?: (props: {
1797
- rect: DOMRect;
1798
- onMoveUp: () => void;
1799
- onMoveDown: () => void;
1800
- showUp: boolean;
1801
- showDown: boolean;
1802
- upClassName: string;
1803
- downClassName: string;
1804
- }) => ReactNode;
1805
- /** Custom drop indicator renderer */
1806
- dropIndicatorRenderer?: (props: {
1807
- top: number;
1808
- left: number;
1809
- width: number;
1810
- className: string;
1811
- }) => ReactNode;
1812
- }
1813
- /**
1814
- * Commands exposed by the draggable block extension
1815
- */
1816
- type DraggableCommands = {
1817
- moveBlock: (sourceKey: string, targetKey: string, insertAfter: boolean) => void;
1818
- moveCurrentBlockUp: () => void;
1819
- moveCurrentBlockDown: () => void;
1820
- };
1821
- /**
1822
- * State queries exposed by the draggable block extension
1823
- */
1824
- type DraggableStateQueries = {
1825
- isDragging: () => Promise<boolean>;
1826
- };
1827
- /**
1828
- * DraggableBlockExtension - Clean, headless drag-and-drop for blocks
1829
- */
1830
- declare class DraggableBlockExtension extends BaseExtension<"draggableBlock", DraggableConfig, DraggableCommands, DraggableStateQueries, ReactNode[]> {
1831
- private isDraggingState;
1832
- private stateChangeCallbacks;
1833
- constructor(config?: Partial<DraggableConfig>);
1834
- register(editor: LexicalEditor): () => void;
1835
- getPlugins(): ReactNode[];
1836
- getCommands(editor: LexicalEditor): DraggableCommands;
1837
- getStateQueries(editor: LexicalEditor): DraggableStateQueries;
1838
- setIsDragging(isDragging: boolean): void;
1839
- onStateChange(callback: () => void): () => void;
1840
- }
1841
- /**
1842
- * Preconfigured instance
1843
- */
1844
- declare const draggableBlockExtension: DraggableBlockExtension;
1845
-
1846
- /**
1847
- * Supported alignment options for media items
1848
- */
1849
- type Alignment = "left" | "right" | "center" | "none";
1850
- /**
1851
- * Payload interface for image insertion and updates
1852
- */
1853
- interface ImagePayload {
1854
- /** Source URL for the image */
1855
- src?: string;
1856
- /** Accessible alt text */
1857
- alt: string;
1858
- /** Optional caption */
1859
- caption?: string;
1860
- /** Alignment */
1861
- alignment?: Alignment;
1862
- /** CSS class name for styling */
1863
- className?: string;
1864
- /** Inline style overrides */
1865
- style?: CSSProperties;
1866
- /** File object for uploads */
1867
- file?: File;
1868
- /** Width in pixels */
1869
- width?: number;
1870
- /** Height in pixels */
1871
- height?: number;
1872
- }
1873
- /**
1874
- * Props for the Image component
1875
- */
1876
- interface ImageComponentProps extends ImagePayload {
1877
- /** Lexical node key */
1878
- nodeKey?: string;
1879
- /** Whether the image is resizable */
1880
- resizable?: boolean;
1881
- /** Whether resize keeps aspect ratio by default */
1882
- scaleByRatio?: boolean;
1883
- /** Whether the image is uploading */
1884
- uploading?: boolean;
1885
- }
1886
- /**
1887
- * Serialized ImageNode representation for persistence
1888
- */
1889
- interface SerializedImageNode {
1890
- /** Node type ID */
1891
- type: "image";
1892
- /** Version for migrations */
1893
- version: number;
1894
- /** Source URL for the image */
1895
- src: string;
1896
- /** Accessible alt text */
1897
- alt: string;
1898
- /** Optional caption */
1899
- caption?: string;
1900
- /** Alignment */
1901
- alignment: Alignment;
1902
- /** CSS class name */
1903
- className?: string;
1904
- /** Inline styles as a string record */
1905
- style?: Record<string, string>;
1906
- /** Width in pixels */
1907
- width?: number;
1908
- /** Height in pixels */
1909
- height?: number;
1910
- }
1911
- /**
1912
- * ImageExtension configuration options
1913
- */
1914
- interface ImageExtensionConfig extends BaseExtensionConfig {
1915
- /** Upload handler that returns the image URL */
1916
- uploadHandler?: (file: File) => Promise<string>;
1917
- /** Default alignment for new images */
1918
- defaultAlignment?: Alignment;
1919
- /** Class names for alignments and elements */
1920
- classNames?: Partial<Record<Alignment | "wrapper" | "caption", string>>;
1921
- /** Styles for alignments and elements */
1922
- styles?: Partial<Record<Alignment | "wrapper" | "caption", CSSProperties>>;
1923
- /** Custom renderer component for images */
1924
- customRenderer?: ComponentType<ImageComponentProps>;
1925
- /** Enable image resizing (default: true) */
1926
- resizable?: boolean;
1927
- /** Keep aspect ratio while resizing by default (Shift toggles) */
1928
- scaleByRatio?: boolean;
1929
- /** Paste behavior configuration */
1930
- pasteListener?: {
1931
- /** Insert a new image on paste when none is selected */
1932
- insert: boolean;
1933
- /** Replace selected image src on paste */
1934
- replace: boolean;
1935
- };
1936
- /** Enable debug logging */
1937
- debug?: boolean;
1938
- /** Force upload even for remote URLs (default: false) */
1939
- forceUpload?: boolean;
1940
- }
1941
- /**
1942
- * Commands exposed by the ImageExtension
1943
- */
1944
- type ImageCommands = {
1945
- /** Insert an image into the editor */
1946
- insertImage: (payload: ImagePayload) => void;
1947
- /** Set alignment for the selected image */
1948
- setImageAlignment: (alignment: Alignment) => void;
1949
- /** Set caption for the selected image */
1950
- setImageCaption: (caption: string) => void;
1951
- /** Read caption for the selected image */
1952
- getImageCaption: () => Promise<string>;
1953
- /** Set the CSS class name on the selected image */
1954
- setImageClassName: (className: string) => void;
1955
- /** Set inline styles on the selected image */
1956
- setImageStyle: (style: CSSProperties) => void;
1957
- };
1958
- /**
1959
- * State queries exposed by the ImageExtension
1960
- */
1961
- type ImageStateQueries = {
1962
- /** Check whether an image is selected */
1963
- imageSelected: () => Promise<boolean>;
1964
- /** Check whether the selected image is left-aligned */
1965
- isImageAlignedLeft: () => Promise<boolean>;
1966
- /** Check whether the selected image is center-aligned */
1967
- isImageAlignedCenter: () => Promise<boolean>;
1968
- /** Check whether the selected image is right-aligned */
1969
- isImageAlignedRight: () => Promise<boolean>;
1970
- /** Check whether the selected image has no special alignment */
1971
- isImageAlignedNone: () => Promise<boolean>;
1972
- };
1973
-
1974
- declare class ImageExtension extends BaseExtension<"image", ImageExtensionConfig, ImageCommands, ImageStateQueries, ReactNode[]> {
1975
- /** Track recent image sources to avoid duplicate inserts */
1976
- private recentImages;
1977
- /** Last selected image key for toolbar edits while focus moves to external inputs */
1978
- private lastSelectedImageNodeKey;
1979
- constructor();
1980
- configure(config: Partial<ImageExtensionConfig>): this;
1981
- register(editor: LexicalEditor): () => void;
1982
- getNodes(): any[];
1983
- getCommands(editor: LexicalEditor): ImageCommands;
1984
- getStateQueries(editor: LexicalEditor): ImageStateQueries;
1985
- }
1986
- declare const imageExtension: ImageExtension;
1987
-
1988
- type EmbedAlignment = "left" | "center" | "right";
1989
- interface IframeEmbedConfig extends BaseExtensionConfig {
1990
- defaultWidth?: number;
1991
- defaultHeight?: number;
1992
- defaultAlignment?: EmbedAlignment;
1993
- }
1994
- type IframeEmbedCommands = {
1995
- insertIframeEmbed: (inputUrl: string, width?: number, height?: number, title?: string) => void;
1996
- setIframeEmbedAlignment: (alignment: EmbedAlignment) => void;
1997
- resizeIframeEmbed: (width: number, height: number) => void;
1998
- setIframeEmbedCaption: (caption: string) => void;
1999
- getIframeEmbedCaption: () => Promise<string>;
2000
- updateIframeEmbedUrl: (inputUrl: string) => boolean;
2001
- getIframeEmbedUrl: () => Promise<string>;
2002
- };
2003
- type IframeEmbedQueries = {
2004
- isIframeEmbedSelected: () => Promise<boolean>;
2005
- isIframeEmbedAlignedLeft: () => Promise<boolean>;
2006
- isIframeEmbedAlignedCenter: () => Promise<boolean>;
2007
- isIframeEmbedAlignedRight: () => Promise<boolean>;
2008
- };
2009
- declare class IframeEmbedExtension extends BaseExtension<"iframeEmbed", IframeEmbedConfig, IframeEmbedCommands, IframeEmbedQueries, ReactNode[]> {
2010
- constructor(config?: Partial<IframeEmbedConfig>);
2011
- register(editor: LexicalEditor): () => void;
2012
- getNodes(): any[];
2013
- getPlugins(): ReactNode[];
2014
- getCommands(editor: LexicalEditor): IframeEmbedCommands;
2015
- getStateQueries(editor: LexicalEditor): IframeEmbedQueries;
2016
- }
2017
- declare const iframeEmbedExtension: IframeEmbedExtension;
2018
-
2019
- interface YouTubeEmbedConfig extends BaseExtensionConfig {
2020
- defaultWidth?: number;
2021
- defaultHeight?: number;
2022
- defaultAlignment?: EmbedAlignment;
2023
- allowFullscreen?: boolean;
2024
- autoplay?: boolean;
2025
- controls?: boolean;
2026
- nocookie?: boolean;
2027
- rel?: number;
2028
- }
2029
- type YouTubeEmbedCommands = {
2030
- insertYouTubeEmbed: (inputUrl: string, width?: number, height?: number, start?: number) => void;
2031
- setYouTubeEmbedAlignment: (alignment: EmbedAlignment) => void;
2032
- resizeYouTubeEmbed: (width: number, height: number) => void;
2033
- setYouTubeEmbedCaption: (caption: string) => void;
2034
- getYouTubeEmbedCaption: () => Promise<string>;
2035
- updateYouTubeEmbedUrl: (inputUrl: string) => boolean;
2036
- getYouTubeEmbedUrl: () => Promise<string>;
2037
- };
2038
- type YouTubeEmbedQueries = {
2039
- isYouTubeEmbedSelected: () => Promise<boolean>;
2040
- isYouTubeEmbedAlignedLeft: () => Promise<boolean>;
2041
- isYouTubeEmbedAlignedCenter: () => Promise<boolean>;
2042
- isYouTubeEmbedAlignedRight: () => Promise<boolean>;
2043
- };
2044
- declare class YouTubeEmbedExtension extends BaseExtension<"youtubeEmbed", YouTubeEmbedConfig, YouTubeEmbedCommands, YouTubeEmbedQueries, ReactNode[]> {
2045
- private lastSelectedYouTubeNodeKey;
2046
- constructor(config?: Partial<YouTubeEmbedConfig>);
2047
- register(editor: LexicalEditor): () => void;
2048
- getNodes(): any[];
2049
- getPlugins(): ReactNode[];
2050
- getCommands(editor: LexicalEditor): YouTubeEmbedCommands;
2051
- getStateQueries(editor: LexicalEditor): YouTubeEmbedQueries;
2052
- }
2053
- declare const youTubeEmbedExtension: YouTubeEmbedExtension;
2054
-
2055
- type CustomPayload = Record<string, any>;
2056
- interface CustomNodeConfig<CustomCommands, CustomStateQueries> {
2057
- nodeType: string;
2058
- isContainer?: boolean;
2059
- defaultPayload?: CustomPayload;
2060
- initialChildren?: () => SerializedLexicalNode[];
2061
- render?: (props: {
2062
- node: LexicalNode;
2063
- payload: CustomPayload;
2064
- children?: ReactNode;
2065
- nodeKey: string;
2066
- isSelected: boolean;
2067
- updatePayload: (newPayload: Partial<CustomPayload>) => void;
2068
- }) => ReactNode;
2069
- jsx?: (props: {
2070
- node: LexicalNode;
2071
- payload: CustomPayload;
2072
- nodeKey: string;
2073
- isSelected: boolean;
2074
- updatePayload: (newPayload: Partial<CustomPayload>) => void;
2075
- }) => React.ReactElement;
2076
- createDOM?: (config: EditorConfig$1, node: LexicalNode) => HTMLElement;
2077
- updateDOM?: (prevNode: LexicalNode, dom: HTMLElement, config: EditorConfig$1) => boolean;
2078
- importDOM?: () => DOMConversionMap;
2079
- exportDOM?: (editor: LexicalEditor, options: {
2080
- element: HTMLElement;
2081
- node: LexicalNode;
2082
- }) => DOMExportOutput;
2083
- commands?: (editor: LexicalEditor) => CustomCommands;
2084
- stateQueries?: (editor: LexicalEditor) => CustomStateQueries;
2085
- }
2086
- /**
2087
- * Creates a custom node extension for the Luthor editor system.
2088
- * This factory lets you define custom Lexical nodes with React rendering,
2089
- * commands, and state queries.
2090
- *
2091
- * @template Name - Literal name type for the extension
2092
- * @template Commands - Commands exposed by this custom extension
2093
- * @template StateQueries - State query functions exposed by this extension
2094
- * @param userConfig - Configuration object defining the custom node behavior
2095
- * @returns Object containing the extension and helper functions
2096
- *
2097
- * @example
2098
- * ```tsx
2099
- * const { extension, $createCustomNode } = createCustomNodeExtension({
2100
- * nodeType: 'myBlock',
2101
- * render: ({ payload, isSelected }) => (
2102
- * <div className={isSelected ? 'selected' : ''}>
2103
- * {payload.text}
2104
- * </div>
2105
- * ),
2106
- * commands: (editor) => ({
2107
- * insertMyBlock: (data) => {
2108
- * const node = $createCustomNode(data);
2109
- * editor.dispatchCommand(INSERT_CUSTOM_NODE, node);
2110
- * }
2111
- * })
2112
- * });
2113
- * ```
2114
- */
2115
- declare function createCustomNodeExtension<Name extends string, Commands extends Record<string, any> = Record<string, never>, StateQueries extends Record<string, () => Promise<boolean>> = Record<string, never>>(userConfig: CustomNodeConfig<Commands, StateQueries>): {
2116
- extension: BaseExtension<Name, BaseExtensionConfig, Commands, StateQueries>;
2117
- $createCustomNode: (payload?: CustomPayload) => ElementNode | DecoratorNode<ReactNode>;
2118
- jsxToDOM: (jsxElement: React.ReactElement) => HTMLElement;
2119
- };
2120
-
2121
- interface BaseRichTextProps {
2122
- contentEditable?: React__default.ReactElement;
2123
- placeholder?: React__default.ReactElement | string;
2124
- className?: string;
2125
- classNames?: {
2126
- container?: string;
2127
- contentEditable?: string;
2128
- placeholder?: string;
2129
- };
2130
- styles?: {
2131
- container?: React__default.CSSProperties;
2132
- contentEditable?: React__default.CSSProperties;
2133
- placeholder?: React__default.CSSProperties;
2134
- };
2135
- errorBoundary?: React__default.ComponentType<{
2136
- children: React__default.JSX.Element;
2137
- onError: (error: Error) => void;
2138
- }>;
2139
- }
2140
- interface RichTextConfig extends BaseExtensionConfig, BaseRichTextProps {
2141
- }
2142
- type SharedRichTextProps = BaseRichTextProps;
2143
- /**
2144
- * RichTextExtension - Provides core rich text editing functionality
2145
- * Extends BaseExtension to stay consistent with other extensions
2146
- */
2147
- declare class RichTextExtension extends BaseExtension<"richText", RichTextConfig, Record<string, never>, Record<string, never>, ReactNode[]> {
2148
- constructor(config?: RichTextConfig);
2149
- register(editor: LexicalEditor): () => void;
2150
- getPlugins(): ReactNode[];
2151
- }
2152
- declare const richTextExtension: RichTextExtension;
2153
- type RichTextComponentProps = SharedRichTextProps;
2154
- declare const RichText: React__default.FC<RichTextComponentProps>;
2155
-
2156
- /**
2157
- * TabIndentExtension - Adds universal Tab/Shift+Tab indentation support
2158
- *
2159
- * Enables Tab key to indent and Shift+Tab to outdent content throughout
2160
- * the editor, not just in code blocks. This provides a consistent
2161
- * indentation experience across all content types.
2162
- *
2163
- * @example
2164
- * ```tsx
2165
- * import { tabIndentExtension } from '@lyfie/luthor-headless';
2166
- *
2167
- * const extensions = [tabIndentExtension];
2168
- * ```
2169
- */
2170
- declare class TabIndentExtension extends BaseExtension<"tabIndent", Record<string, never>, Record<string, never>, Record<string, never>, ReactNode[]> {
2171
- constructor();
2172
- /**
2173
- * Register the extension with Lexical
2174
- * @param editor - Lexical editor instance
2175
- * @returns Cleanup function
2176
- */
2177
- register(editor: LexicalEditor): () => void;
2178
- /**
2179
- * Check if a node is within a code block
2180
- * @param node - Node to check
2181
- * @returns True if node is in a code block
2182
- */
2183
- private isInCodeBlock;
2184
- /**
2185
- * Check if a node is within a checklist list item.
2186
- */
2187
- private isInCheckList;
2188
- }
2189
- declare const tabIndentExtension: TabIndentExtension;
2190
-
2191
- type EmojiCatalogItem = {
2192
- emoji: string;
2193
- label: string;
2194
- shortcodes: string[];
2195
- keywords?: string[];
2196
- };
2197
- type EmojiCatalogAdapter = {
2198
- search: (query: string, options?: {
2199
- limit?: number;
2200
- }) => EmojiCatalogItem[];
2201
- resolveShortcode: (shortcode: string) => EmojiCatalogItem | null;
2202
- getAll: () => EmojiCatalogItem[];
2203
- };
2204
- type EmojiSuggestionState = {
2205
- isOpen: boolean;
2206
- query: string;
2207
- position: {
2208
- x: number;
2209
- y: number;
2210
- } | null;
2211
- suggestions: EmojiCatalogItem[];
2212
- };
2213
- interface EmojiConfig extends BaseExtensionConfig {
2214
- trigger?: string;
2215
- maxSuggestions?: number;
2216
- maxQueryLength?: number;
2217
- autoReplaceSymbols?: boolean;
2218
- symbolReplacements?: Record<string, string>;
2219
- catalog?: EmojiCatalogItem[];
2220
- catalogAdapter?: EmojiCatalogAdapter;
2221
- autoDetectExternalCatalog?: boolean;
2222
- offset?: {
2223
- x: number;
2224
- y: number;
2225
- };
2226
- }
2227
- type EmojiCommands = {
2228
- insertEmoji: (emoji: string) => void;
2229
- executeEmojiSuggestion: (emoji: string) => boolean;
2230
- closeEmojiSuggestions: () => void;
2231
- getEmojiSuggestions: (query?: string) => EmojiCatalogItem[];
2232
- getEmojiCatalog: () => EmojiCatalogItem[];
2233
- resolveEmojiShortcode: (shortcode: string) => EmojiCatalogItem | null;
2234
- setEmojiCatalog: (catalog: EmojiCatalogItem[]) => void;
2235
- setEmojiCatalogAdapter: (adapter: EmojiCatalogAdapter) => void;
2236
- getEmojiCatalogAdapter: () => EmojiCatalogAdapter;
2237
- };
2238
- type EmojiStateQueries = {
2239
- isEmojiSuggestionOpen: () => Promise<boolean>;
2240
- };
2241
- declare const LIGHTWEIGHT_EMOJI_CATALOG: EmojiCatalogItem[];
2242
- declare class EmojiExtension extends BaseExtension<"emoji", EmojiConfig, EmojiCommands, EmojiStateQueries, React__default.ReactElement[]> {
2243
- private listeners;
2244
- private isOpen;
2245
- private query;
2246
- private position;
2247
- private suggestions;
2248
- private activeMatch;
2249
- private applyingAutoReplace;
2250
- private catalogAdapter;
2251
- private hasExplicitCatalogConfig;
2252
- private hasExplicitAdapterConfig;
2253
- private externalCatalogDetectionStarted;
2254
- constructor(config?: EmojiConfig);
2255
- configure(config: Partial<EmojiConfig>): this;
2256
- register(editor: LexicalEditor): () => void;
2257
- getCommands(editor: LexicalEditor): EmojiCommands;
2258
- getStateQueries(editor: LexicalEditor): EmojiStateQueries;
2259
- subscribe(listener: (state: EmojiSuggestionState) => void): () => void;
2260
- private getCatalog;
2261
- private getSuggestions;
2262
- private resolveShortcode;
2263
- private resolveCatalogAdapter;
2264
- private tryEnableExternalCatalog;
2265
- private refreshSuggestionsIfOpen;
2266
- private updateFromSelection;
2267
- private isSelectionInsideCodeBlock;
2268
- private detectSymbolReplacement;
2269
- private replaceSymbolsInText;
2270
- private executeEmojiSuggestion;
2271
- private closeEmojiSuggestions;
2272
- private closeIfNeeded;
2273
- private getCaretPosition;
2274
- private getState;
2275
- private notifyListeners;
2276
- }
2277
- declare const emojiExtension: EmojiExtension;
2278
-
2279
- /**
2280
- * Selection rectangle with position data.
2281
- */
2282
- interface SelectionRect {
2283
- x: number;
2284
- y: number;
2285
- width: number;
2286
- height: number;
2287
- top: number;
2288
- left: number;
2289
- bottom: number;
2290
- right: number;
2291
- positionFromRight?: boolean;
2292
- }
2293
- /**
2294
- * Floating toolbar render props (typed, headless).
2295
- */
2296
- interface FloatingToolbarRenderProps<TCommands = any, TStates = any> {
2297
- /** Whether the toolbar is visible. */
2298
- isVisible: boolean;
2299
- /** Selection rectangle used for positioning. */
2300
- selectionRect: SelectionRect | null;
2301
- /** Current selection reference. */
2302
- selection: RangeSelection | null;
2303
- /** Lexical editor reference. */
2304
- editor: LexicalEditor;
2305
- /** Typed commands from the editor system. */
2306
- commands: TCommands;
2307
- /** Active state map from the editor system. */
2308
- activeStates: TStates;
2309
- /** Callback to dismiss the toolbar. */
2310
- hide: () => void;
2311
- /** Theme class names for styling. */
2312
- theme: {
2313
- container?: string;
2314
- button?: string;
2315
- buttonActive?: string;
2316
- };
2317
- }
2318
- /**
2319
- * FloatingToolbarExtension configuration.
2320
- */
2321
- interface FloatingConfig<TCommands = any, TStates = any> extends BaseExtensionConfig {
2322
- /**
2323
- * Headless render function for full UI control.
2324
- */
2325
- render: (props: FloatingToolbarRenderProps<TCommands, TStates>) => ReactNode | null;
2326
- /**
2327
- * Function to retrieve typed commands from the editor system.
2328
- */
2329
- getCommands?: () => TCommands;
2330
- /**
2331
- * Function to retrieve active states from the editor system.
2332
- */
2333
- getActiveStates?: () => TStates;
2334
- /**
2335
- * Portal anchor element (defaults to document.body).
2336
- */
2337
- anchorElem?: HTMLElement;
2338
- /**
2339
- * Debounce delay for selection changes (default: 100ms).
2340
- */
2341
- debounceMs?: number;
2342
- /**
2343
- * Offset from the selection (default: { x: 0, y: 8 }).
2344
- */
2345
- offset?: {
2346
- x: number;
2347
- y: number;
2348
- };
2349
- /**
2350
- * Position strategy (default: 'below').
2351
- */
2352
- positionStrategy?: "above" | "below" | "auto";
2353
- /**
2354
- * Theme class names for styling.
2355
- */
2356
- theme?: {
2357
- container?: string;
2358
- button?: string;
2359
- buttonActive?: string;
2360
- };
2361
- /**
2362
- * Toolbar dimensions for positioning calculations (default: { width: 300, height: 40 }).
2363
- */
2364
- toolbarDimensions?: {
2365
- width: number;
2366
- height: number;
2367
- };
2368
- }
2369
- /**
2370
- * Commands exposed by the floating toolbar extension (none by default).
2371
- */
2372
- type FloatingCommands = Record<string, never>;
2373
- /**
2374
- * State queries exposed by the floating toolbar extension.
2375
- */
2376
- type FloatingStateQueries = {
2377
- isFloatingVisible: () => Promise<boolean>;
2378
- };
2379
- /**
2380
- * FloatingToolbarExtension - Headless toolbar that appears on selection.
2381
- */
2382
- declare class FloatingToolbarExtension<TCommands = any, TStates = any> extends BaseExtension<"floatingToolbar", FloatingConfig<TCommands, TStates>, FloatingCommands, FloatingStateQueries, ReactNode[]> {
2383
- private isVisible;
2384
- private selectionRect;
2385
- constructor();
2386
- register(editor: LexicalEditor): () => void;
2387
- getPlugins(): ReactNode[];
2388
- getCommands(editor: LexicalEditor): FloatingCommands;
2389
- getStateQueries(editor: LexicalEditor): FloatingStateQueries;
2390
- updateContext(commands: TCommands, activeStates: TStates): void;
2391
- getSelectionRect(): SelectionRect | null;
2392
- getIsVisible(): boolean;
2393
- setVisible(visible: boolean): void;
2394
- setSelectionRect(rect: SelectionRect | null): void;
2395
- }
2396
- /**
2397
- * Preconfigured instance.
2398
- */
2399
- declare const floatingToolbarExtension: FloatingToolbarExtension<any, any>;
2400
-
2401
- /**
2402
- * Command palette item definition
2403
- */
2404
- type CommandPaletteItem = {
2405
- id: string;
2406
- label: string;
2407
- description?: string;
2408
- action: () => void;
2409
- keywords?: string[];
2410
- category?: string;
2411
- icon?: React__default.ReactNode;
2412
- shortcut?: string;
2413
- };
2414
- /**
2415
- * Commands exposed by the command palette extension
2416
- */
2417
- type CommandPaletteCommands = {
2418
- showCommandPalette: () => void;
2419
- hideCommandPalette: () => void;
2420
- registerCommand: (item: CommandPaletteItem) => void;
2421
- unregisterCommand: (id: string) => void;
2422
- };
2423
- /**
2424
- * State queries exposed by the command palette extension
2425
- */
2426
- type CommandPaletteStateQueries = {
2427
- isCommandPaletteOpen: () => Promise<boolean>;
2428
- };
2429
- /**
2430
- * Command palette extension for quick access to editor commands.
2431
- * Provides a searchable command palette similar to VS Code.
2432
- */
2433
- declare class CommandPaletteExtension extends BaseExtension<"commandPalette", any, CommandPaletteCommands, CommandPaletteStateQueries, React__default.ReactElement[]> {
2434
- private isOpen;
2435
- private commands;
2436
- private listeners;
2437
- constructor();
2438
- register(editor: LexicalEditor): () => void;
2439
- getCommands(editor: LexicalEditor): CommandPaletteCommands;
2440
- getStateQueries(editor: LexicalEditor): CommandPaletteStateQueries;
2441
- private showCommandPalette;
2442
- private hideCommandPalette;
2443
- private toggleCommandPalette;
2444
- private registerCommand;
2445
- private unregisterCommand;
2446
- private registerTableCommands;
2447
- private notifyListeners;
2448
- /**
2449
- * Subscribe to command palette updates
2450
- */
2451
- subscribe(listener: (isOpen: boolean, commands: CommandPaletteItem[]) => void): () => void;
2452
- getAllCommands(): CommandPaletteItem[];
2453
- }
2454
- declare const commandPaletteExtension: CommandPaletteExtension;
2455
-
2456
- type SlashCommandItem = {
2457
- id: string;
2458
- label: string;
2459
- description?: string;
2460
- action: () => void;
2461
- keywords?: string[];
2462
- category?: string;
2463
- icon?: React__default.ReactNode;
2464
- shortcut?: string;
2465
- };
2466
- type SlashCommandMenuState = {
2467
- isOpen: boolean;
2468
- query: string;
2469
- position: {
2470
- x: number;
2471
- y: number;
2472
- } | null;
2473
- commands: SlashCommandItem[];
2474
- };
2475
- interface SlashCommandConfig extends BaseExtensionConfig {
2476
- trigger?: string;
2477
- offset?: {
2478
- x: number;
2479
- y: number;
2480
- };
2481
- items?: readonly SlashCommandItem[];
2482
- }
2483
- type SlashCommandCommands = {
2484
- registerSlashCommand: (item: SlashCommandItem) => void;
2485
- unregisterSlashCommand: (id: string) => void;
2486
- setSlashCommands: (items: readonly SlashCommandItem[]) => void;
2487
- closeSlashMenu: () => void;
2488
- executeSlashCommand: (id: string) => boolean;
2489
- };
2490
- type SlashCommandStateQueries = {
2491
- isSlashMenuOpen: () => Promise<boolean>;
2492
- };
2493
- declare class SlashCommandExtension extends BaseExtension<"slashCommand", SlashCommandConfig, SlashCommandCommands, SlashCommandStateQueries, React__default.ReactElement[]> {
2494
- private commands;
2495
- private listeners;
2496
- private isOpen;
2497
- private query;
2498
- private position;
2499
- private activeMatch;
2500
- constructor(config?: SlashCommandConfig);
2501
- register(editor: LexicalEditor): () => void;
2502
- getCommands(editor: LexicalEditor): SlashCommandCommands;
2503
- getStateQueries(_editor: LexicalEditor): SlashCommandStateQueries;
2504
- subscribe(listener: (state: SlashCommandMenuState) => void): () => void;
2505
- getAllCommands(): SlashCommandItem[];
2506
- private registerSlashCommand;
2507
- private unregisterSlashCommand;
2508
- private setSlashCommands;
2509
- private closeSlashMenu;
2510
- private executeSlashCommand;
2511
- private updateMatchFromSelection;
2512
- private closeIfNeeded;
2513
- private getCaretPosition;
2514
- private getState;
2515
- private notifyListeners;
2516
- }
2517
- declare const slashCommandExtension: SlashCommandExtension;
2518
-
2519
- type EnterKeyBehaviorCommands = Record<string, never>;
2520
- type EnterKeyBehaviorStateQueries = Record<string, never>;
2521
- declare class EnterKeyBehaviorExtension extends BaseExtension<"enterKeyBehavior", BaseExtensionConfig, EnterKeyBehaviorCommands, EnterKeyBehaviorStateQueries> {
2522
- constructor();
2523
- register(editor: LexicalEditor): () => void;
2524
- private findQuoteNode;
2525
- private findCodeNode;
2526
- private findDirectQuoteChild;
2527
- private isEmptyQuoteLine;
2528
- }
2529
- declare const enterKeyBehaviorExtension: EnterKeyBehaviorExtension;
2530
-
2531
- export { type Alignment, type BaseCommands, BaseExtension, type BaseExtensionConfig, BaseProvider, BlockFormatExtension, BoldExtension, CodeExtension, type CodeExtensionConfig, CodeFormatExtension, type CodeHighlightProvider, type CodeHighlightProviderConfig, type CodeIntelligenceCommands, type CodeIntelligenceConfig, CodeIntelligenceExtension, type CodeLanguageOptionsConfig, type CodeLanguageOptionsMode, type CommandPaletteCommands, CommandPaletteExtension, type CommandPaletteItem, type CommandPaletteStateQueries, type ContextMenuCommands, type ContextMenuConfig, ContextMenuExtension, type ContextMenuItem, type ContextMenuStateQueries, DraggableBlockExtension, type DraggableCommands, type DraggableConfig, type DraggableStateQueries, type EditorConfig, type EditorContextType, type EmojiCatalogAdapter, type EmojiCatalogItem, type EmojiCommands, type EmojiConfig, EmojiExtension, type EmojiStateQueries, type EmojiSuggestionState, EnterKeyBehaviorExtension, type Extension, ExtensionCategory, type ExtractCommands, type ExtractNames, type ExtractPlugins, type ExtractStateQueries, type FloatingCommands, type FloatingConfig, type FloatingStateQueries, FloatingToolbarExtension, type FontCssLoadStrategy, type FontFamilyConfig, FontFamilyExtension, type FontFamilyOption, type FontSizeConfig, FontSizeExtension, type FontSizeOption, HistoryExtension, HorizontalRuleExtension, IframeEmbedExtension, type ImageCommands, type ImageComponentProps, ImageExtension, type ImageExtensionConfig, type ImagePayload, type ImageStateQueries, ItalicExtension, type JsonbDocument, LIGHTWEIGHT_EMOJI_CATALOG, LUTHOR_EDITOR_THEME_TOKENS, type LexicalNodeRegistration, type LineHeightConfig, LineHeightExtension, type LineHeightOption, LinkExtension, ListExtension, type LuthorEditorThemeOverrides, type LuthorEditorThemeToken, type LuthorTheme, RichText, type RichTextComponentProps, type RichTextConfig, type SerializedImageNode, type SlashCommandCommands, type SlashCommandConfig, SlashCommandExtension, type SlashCommandItem, type SlashCommandMenuState, type SlashCommandStateQueries, StrikethroughExtension, SubscriptExtension, SuperscriptExtension, TabIndentExtension, type TableConfig, TableExtension, type TextColorConfig, TextColorExtension, type TextColorOption, TextFormatExtension, type TextHighlightConfig, TextHighlightExtension, type TextHighlightOption, type ToolbarItem, UnderlineExtension, YouTubeEmbedExtension, blockFormatExtension, boldExtension, clearLexicalSelection, codeExtension, codeFormatExtension, codeIntelligenceExtension, commandPaletteExtension, contextMenuExtension, createCustomNodeExtension, createEditorSystem, createEditorThemeStyleVars, createExtension, defaultLuthorTheme, draggableBlockExtension, emojiExtension, enterKeyBehaviorExtension, floatingToolbarExtension, fontFamilyExtension, fontSizeExtension, historyExtension, horizontalRuleExtension, iframeEmbedExtension, imageExtension, isLuthorTheme, italicExtension, jsonbToMarkdown, lineHeightExtension, linkExtension, listExtension, markdownToJSONB, mergeThemes, resolveLinkNodeKeyFromAnchor, richTextExtension, slashCommandExtension, strikethroughExtension, subscriptExtension, superscriptExtension, tabIndentExtension, tableExtension, textColorExtension, textHighlightExtension, underlineExtension, useBaseEditor, youTubeEmbedExtension };