noteloom 0.3.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +173 -808
  2. package/bin/noteloom.mjs +139 -0
  3. package/dist/canvas.cjs +2 -0
  4. package/dist/canvas.cjs.map +1 -0
  5. package/dist/canvas.d.ts +2 -0
  6. package/dist/canvas.js +5 -0
  7. package/dist/canvas.js.map +1 -0
  8. package/dist/collab.cjs +2 -0
  9. package/dist/collab.cjs.map +1 -0
  10. package/dist/collab.d.ts +19 -0
  11. package/dist/collab.js +379 -0
  12. package/dist/collab.js.map +1 -0
  13. package/dist/comments.cjs +2 -0
  14. package/dist/comments.cjs.map +1 -0
  15. package/dist/comments.d.ts +17 -0
  16. package/dist/comments.js +19 -0
  17. package/dist/comments.js.map +1 -0
  18. package/dist/index.cjs +2 -0
  19. package/dist/index.cjs.map +1 -0
  20. package/dist/index.d.ts +374 -34
  21. package/dist/index.js +3983 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/persistence.cjs +2 -0
  24. package/dist/persistence.cjs.map +1 -0
  25. package/dist/persistence.d.ts +11 -0
  26. package/dist/persistence.js +12 -0
  27. package/dist/persistence.js.map +1 -0
  28. package/dist/shared/CommentAvatar-TKqsM8vG.js +53 -0
  29. package/dist/shared/CommentAvatar-TKqsM8vG.js.map +1 -0
  30. package/dist/shared/CommentAvatar-V457IgoQ.cjs +2 -0
  31. package/dist/shared/CommentAvatar-V457IgoQ.cjs.map +1 -0
  32. package/dist/shared/CommentThreadCard-CwKd6fp3.js +213 -0
  33. package/dist/shared/CommentThreadCard-CwKd6fp3.js.map +1 -0
  34. package/dist/shared/CommentThreadCard-YziIa8My.cjs +2 -0
  35. package/dist/shared/CommentThreadCard-YziIa8My.cjs.map +1 -0
  36. package/dist/shared/CommentsPanel-DezejDdE.cjs +2 -0
  37. package/dist/shared/CommentsPanel-DezejDdE.cjs.map +1 -0
  38. package/dist/shared/CommentsPanel-dx7IaoqS.js +76 -0
  39. package/dist/shared/CommentsPanel-dx7IaoqS.js.map +1 -0
  40. package/dist/shared/VersionHistory-DhYb8C2e.js +1120 -0
  41. package/dist/shared/VersionHistory-DhYb8C2e.js.map +1 -0
  42. package/dist/shared/VersionHistory-DuSxis_7.cjs +12 -0
  43. package/dist/shared/VersionHistory-DuSxis_7.cjs.map +1 -0
  44. package/dist/shared/VoiceListeningIndicator-BXByLZwO.cjs +2 -0
  45. package/dist/shared/VoiceListeningIndicator-BXByLZwO.cjs.map +1 -0
  46. package/dist/shared/VoiceListeningIndicator-bv285FSY.js +338 -0
  47. package/dist/shared/VoiceListeningIndicator-bv285FSY.js.map +1 -0
  48. package/dist/shared/fieldRegistry-BoYyW3GH.cjs +2 -0
  49. package/dist/shared/fieldRegistry-BoYyW3GH.cjs.map +1 -0
  50. package/dist/shared/fieldRegistry-PjJWXFoB.js +223 -0
  51. package/dist/shared/fieldRegistry-PjJWXFoB.js.map +1 -0
  52. package/dist/shared/icons-BCseh2pt.cjs +3531 -0
  53. package/dist/shared/icons-BCseh2pt.cjs.map +1 -0
  54. package/dist/shared/icons-D5Ctow8R.js +4279 -0
  55. package/dist/shared/icons-D5Ctow8R.js.map +1 -0
  56. package/dist/shared/index-CbIBsFmI.cjs +2 -0
  57. package/dist/shared/index-CbIBsFmI.cjs.map +1 -0
  58. package/dist/shared/index-D_8hJpI7.js +2145 -0
  59. package/dist/shared/index-D_8hJpI7.js.map +1 -0
  60. package/dist/shared/indexedDbPersistence-BKlGPFTP.js +112 -0
  61. package/dist/shared/indexedDbPersistence-BKlGPFTP.js.map +1 -0
  62. package/dist/shared/indexedDbPersistence-BWJ1h5Vp.cjs +2 -0
  63. package/dist/shared/indexedDbPersistence-BWJ1h5Vp.cjs.map +1 -0
  64. package/dist/shared/leafBlockFactory-CaLWUcfa.cjs +2 -0
  65. package/dist/shared/leafBlockFactory-CaLWUcfa.cjs.map +1 -0
  66. package/dist/shared/leafBlockFactory-DSa1XCox.js +335 -0
  67. package/dist/shared/leafBlockFactory-DSa1XCox.js.map +1 -0
  68. package/dist/shared/serialize-BqKU9EZy.js +86 -0
  69. package/dist/shared/serialize-BqKU9EZy.js.map +1 -0
  70. package/dist/shared/serialize-CqwX55uK.cjs +3 -0
  71. package/dist/shared/serialize-CqwX55uK.cjs.map +1 -0
  72. package/dist/shared/starter-kit-DyX1U84W.cjs +27 -0
  73. package/dist/shared/starter-kit-DyX1U84W.cjs.map +1 -0
  74. package/dist/shared/starter-kit-mfeNxqFn.js +4980 -0
  75. package/dist/shared/starter-kit-mfeNxqFn.js.map +1 -0
  76. package/dist/shared/usePopoverEdgeClamp-CPRWQtZV.cjs +2 -0
  77. package/dist/shared/usePopoverEdgeClamp-CPRWQtZV.cjs.map +1 -0
  78. package/dist/shared/usePopoverEdgeClamp-D_hB5t60.js +109 -0
  79. package/dist/shared/usePopoverEdgeClamp-D_hB5t60.js.map +1 -0
  80. package/dist/shared/useServiceWorkerUpdate-BduabXv6.js +94 -0
  81. package/dist/shared/useServiceWorkerUpdate-BduabXv6.js.map +1 -0
  82. package/dist/shared/useServiceWorkerUpdate-DQboGesi.cjs +2 -0
  83. package/dist/shared/useServiceWorkerUpdate-DQboGesi.cjs.map +1 -0
  84. package/dist/starter-kit.cjs +2 -0
  85. package/dist/starter-kit.cjs.map +1 -0
  86. package/dist/starter-kit.d.ts +9 -0
  87. package/dist/starter-kit.js +10 -0
  88. package/dist/starter-kit.js.map +1 -0
  89. package/dist/style.css +3529 -3283
  90. package/dist/versions.cjs +2 -0
  91. package/dist/versions.cjs.map +1 -0
  92. package/dist/versions.d.ts +11 -0
  93. package/dist/versions.js +13 -0
  94. package/dist/versions.js.map +1 -0
  95. package/dist/voice.cjs +2 -0
  96. package/dist/voice.cjs.map +1 -0
  97. package/dist/voice.d.ts +7 -0
  98. package/dist/voice.js +8 -0
  99. package/dist/voice.js.map +1 -0
  100. package/package.json +159 -92
  101. package/dist/noteloom.cjs +0 -3292
  102. package/dist/noteloom.cjs.map +0 -1
  103. package/dist/noteloom.es.js +0 -15047
  104. package/dist/noteloom.es.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -6,7 +6,14 @@
6
6
  // every export still gets *something* useful rather than `any`. No `.js`/
7
7
  // `.jsx` source was changed to produce this file.
8
8
 
9
- import type { ComponentType, ReactNode, ReactElement, CSSProperties, RefObject, ClipboardEvent } from 'react';
9
+ import type {
10
+ ComponentType,
11
+ ReactNode,
12
+ ReactElement,
13
+ CSSProperties,
14
+ RefObject,
15
+ ClipboardEvent,
16
+ } from 'react';
10
17
 
11
18
  // ---------------------------------------------------------------------------
12
19
  // Document shape
@@ -93,11 +100,20 @@ export const OP: {
93
100
  };
94
101
 
95
102
  export namespace operations {
96
- export function insertBlock(block: Block, parentId: string, index: number, subtree?: { blocks: Block[]; runs: Run[] }): Operation;
103
+ export function insertBlock(
104
+ block: Block,
105
+ parentId: string,
106
+ index: number,
107
+ subtree?: { blocks: Block[]; runs: Run[] },
108
+ ): Operation;
97
109
  export function removeBlock(id: string): Operation;
98
110
  export function moveBlock(id: string, toParentId: string, toIndex: number): Operation;
99
111
  export function updateBlockProps(id: string, patch: Record<string, unknown>): Operation;
100
- export function changeBlockType(id: string, blockType: string, props: Record<string, unknown>): Operation;
112
+ export function changeBlockType(
113
+ id: string,
114
+ blockType: string,
115
+ props: Record<string, unknown>,
116
+ ): Operation;
101
117
  export function updateRun(id: string, patch: Record<string, unknown>): Operation;
102
118
  export function setBlockContentIds(blockId: string, contentIds: string[]): Operation;
103
119
  export function replaceRunSpan(blockId: string, oldRunIds: string[], newRuns: Run[]): Operation;
@@ -285,13 +301,21 @@ export function encodeMessage(message: unknown): string;
285
301
  export function decodeMessage(raw: string): unknown;
286
302
 
287
303
  export class PeerConnection {
288
- constructor(options: { peerConnection: RTCPeerConnection; dataChannel?: RTCDataChannel; onMessage?: (message: unknown) => void });
304
+ constructor(options: {
305
+ peerConnection: RTCPeerConnection;
306
+ dataChannel?: RTCDataChannel;
307
+ onMessage?: (message: unknown) => void;
308
+ });
289
309
  send(message: unknown): void;
290
310
  close(): void;
291
311
  }
292
312
 
293
313
  export class CollabSession {
294
- constructor(options: { history: History | EditorStore; signaling: SignalingChannel; presenceThrottleMs?: number });
314
+ constructor(options: {
315
+ history: History | EditorStore;
316
+ signaling: SignalingChannel;
317
+ presenceThrottleMs?: number;
318
+ });
295
319
  connect(remotePeerId: string, options: { initiator: boolean }): void;
296
320
  disconnect(remotePeerId: string): void;
297
321
  destroy(): void;
@@ -346,7 +370,10 @@ export function loadTemplate(id: string): Promise<StoredTemplate | null>;
346
370
  export function deleteTemplate(id: string): Promise<void>;
347
371
  export function listTemplates(): Promise<StoredTemplate[]>;
348
372
 
349
- export function captureBlockTemplate(store: EditorStore | History, blockIds: string[]): BlockTemplate;
373
+ export function captureBlockTemplate(
374
+ store: EditorStore | History,
375
+ blockIds: string[],
376
+ ): BlockTemplate;
350
377
  export function insertBlockTemplate(
351
378
  store: EditorStore | History,
352
379
  template: BlockTemplate,
@@ -364,7 +391,10 @@ export interface BlockTemplateDefinition {
364
391
  }
365
392
 
366
393
  /** Registers block templates as slash commands, discoverable/insertable via "/" alongside every built-in block — no SlashMenu/BlockRegistry changes needed. */
367
- export function registerBlockTemplates(registry: BlockRegistry, templates: BlockTemplateDefinition[]): void;
394
+ export function registerBlockTemplates(
395
+ registry: BlockRegistry,
396
+ templates: BlockTemplateDefinition[],
397
+ ): void;
368
398
 
369
399
  export function useTemplates(options?: { scope?: 'document' | 'block' }): {
370
400
  templates: StoredTemplate[];
@@ -434,7 +464,10 @@ export function useDocumentVersions(docId: string | null | undefined): {
434
464
  * `.be-version-diff-removed` spans. Used internally by `<VersionHistory>`'s
435
465
  * "Changes" tab; exported for building a custom version-history UI.
436
466
  */
437
- export function diffDocumentsHTML(prevDoc: DocumentJSON | null | undefined, nextDoc: DocumentJSON): string;
467
+ export function diffDocumentsHTML(
468
+ prevDoc: DocumentJSON | null | undefined,
469
+ nextDoc: DocumentJSON,
470
+ ): string;
438
471
 
439
472
  export interface VersionHistoryProps {
440
473
  docId: string;
@@ -458,18 +491,37 @@ export interface CommentRange {
458
491
  }
459
492
 
460
493
  /** Creates a comment thread anchored to `range`, highlighting it and creating the thread as one atomic undo step. Returns the new comment's id. */
461
- export function addComment(store: EditorStore | History, range: CommentRange, message: { authorId: string; text: string }): string;
494
+ export function addComment(
495
+ store: EditorStore | History,
496
+ range: CommentRange,
497
+ message: { authorId: string; text: string },
498
+ ): string;
462
499
  /** Appends a reply to an existing thread. Returns the new message's id. */
463
- export function replyToComment(store: EditorStore | History, commentId: string, message: { authorId: string; text: string }): string;
500
+ export function replyToComment(
501
+ store: EditorStore | History,
502
+ commentId: string,
503
+ message: { authorId: string; text: string },
504
+ ): string;
464
505
  /** Flips a thread's resolved flag (defaults to true). */
465
- export function resolveComment(store: EditorStore | History, commentId: string, resolved?: boolean): void;
506
+ export function resolveComment(
507
+ store: EditorStore | History,
508
+ commentId: string,
509
+ resolved?: boolean,
510
+ ): void;
466
511
  /** Removes a thread and strips its highlight from every run that still carries it, as one atomic undo step. */
467
512
  export function deleteComment(store: EditorStore | History, commentId: string): void;
468
513
 
469
514
  /** Computes (does not apply) the op that highlights `range` with `commentId` -- for advanced use; addComment already calls this. Returns null for a collapsed/unresolvable range. */
470
- export function addCommentMarkOverRange(store: EditorStore | History, range: CommentRange, commentId: string): Operation | null;
515
+ export function addCommentMarkOverRange(
516
+ store: EditorStore | History,
517
+ range: CommentRange,
518
+ commentId: string,
519
+ ): Operation | null;
471
520
  /** Computes (does not apply) the ops that strip `commentId` from every run in the document that carries it. */
472
- export function removeCommentMarkEverywhere(store: EditorStore | History, commentId: string): Operation[];
521
+ export function removeCommentMarkEverywhere(
522
+ store: EditorStore | History,
523
+ commentId: string,
524
+ ): Operation[];
473
525
 
474
526
  export function useComments(): CommentThread[];
475
527
 
@@ -555,7 +607,10 @@ export type BlockTypeDefinition = BlockTypeEntry;
555
607
  export type InlineTypeDefinition = InlineTypeEntry;
556
608
 
557
609
  export function registerBuiltInBlocks(registry: BlockRegistry): void;
558
- export function registerBlocks(registry: BlockRegistry, types: Record<string, BlockTypeDefinition>): void;
610
+ export function registerBlocks(
611
+ registry: BlockRegistry,
612
+ types: Record<string, BlockTypeDefinition>,
613
+ ): void;
559
614
  export const TABLE_BLOCKS: Record<string, BlockTypeDefinition>;
560
615
  export const LAYOUT_BLOCKS: Record<string, BlockTypeDefinition>;
561
616
 
@@ -577,7 +632,10 @@ export const embedBlockType: BlockTypeDefinition;
577
632
  export const canvasBlockType: BlockTypeDefinition;
578
633
 
579
634
  export function registerBuiltInInlineTypes(inlineRegistry: InlineRegistry): void;
580
- export function registerInlineTypes(inlineRegistry: InlineRegistry, types: Record<string, InlineTypeDefinition>): void;
635
+ export function registerInlineTypes(
636
+ inlineRegistry: InlineRegistry,
637
+ types: Record<string, InlineTypeDefinition>,
638
+ ): void;
581
639
  export const TABLE_SELECT_INLINE_TYPES: Record<string, InlineTypeDefinition>;
582
640
 
583
641
  export const selectInlineType: InlineTypeDefinition;
@@ -586,6 +644,120 @@ export const checkboxInlineType: InlineTypeDefinition;
586
644
  export const tableSelectInlineType: InlineTypeDefinition;
587
645
  export const emojiInlineType: InlineTypeDefinition;
588
646
 
647
+ // ---------------------------------------------------------------------------
648
+ // registry/define.js, starter-kit.js — the defineBlock/defineInline factories
649
+ // ---------------------------------------------------------------------------
650
+
651
+ export interface DefineBlockConfig {
652
+ /** Unique — used as the block `type`. */
653
+ name: string;
654
+ /** React component, receives `{ id }`. */
655
+ component: ComponentType<{ id: string }>;
656
+ /** 'blocks' (default, holds child blocks) | 'runs' | 'void' (both leaves). */
657
+ contentModel?: 'blocks' | 'runs' | 'void';
658
+ /** Escape hatch — set `isLeaf` directly instead of `contentModel`. */
659
+ isLeaf?: boolean;
660
+ defaultProps?: Record<string, unknown>;
661
+ toHTML?: (block: Block, ctx: unknown) => string;
662
+ fromHTML?: (node: unknown, ctx: unknown) => unknown;
663
+ toPlainText?: (block: Block, ctx: unknown) => string;
664
+ toMarkdown?: (block: Block, ctx: unknown) => string;
665
+ slashCommand?: unknown;
666
+ slashCommands?: unknown[];
667
+ [key: string]: unknown;
668
+ }
669
+
670
+ export interface DefineInlineConfig {
671
+ name: string;
672
+ component: ComponentType<{ id: string }>;
673
+ /** Only `true` (the default) is supported today. */
674
+ atomic?: boolean;
675
+ isAtomic?: boolean;
676
+ toHTML?: (run: Run, ctx: unknown) => string;
677
+ fromHTML?: (node: unknown, ctx: unknown) => unknown;
678
+ toPlainText?: (run: Run, ctx: unknown) => string;
679
+ slashCommand?: unknown;
680
+ slashCommands?: unknown[];
681
+ atCommand?: unknown;
682
+ atCommands?: unknown[];
683
+ [key: string]: unknown;
684
+ }
685
+
686
+ /** A `defineBlock()` result — a `BlockRegistry` entry tagged `kind: 'block'`. */
687
+ export type BlockDefinition = BlockTypeDefinition & { name: string; kind: 'block' };
688
+ /** A `defineInline()` result — an `InlineRegistry` entry tagged `kind: 'inline'`. */
689
+ export type InlineDefinition = InlineTypeDefinition & { name: string; kind: 'inline' };
690
+ /** A `defineExtension()` result — a named bundle of block/inline definitions and/or behavior. */
691
+ export interface ExtensionBundle {
692
+ name: string;
693
+ kind: 'extension';
694
+ blocks: BlockDefinition[];
695
+ inlineTypes: InlineDefinition[];
696
+ keymap?: Record<string, KeymapHandler>;
697
+ onBeforeInput?: ExtensionEventHandler;
698
+ onPaste?: ExtensionEventHandler;
699
+ setup?: (ctx: ExtensionCtx) => void | (() => void);
700
+ [key: string]: unknown;
701
+ }
702
+ export type Extension = BlockDefinition | InlineDefinition | ExtensionBundle;
703
+
704
+ /** The stable facade passed to every `defineExtension()` behavior handler. */
705
+ export interface ExtensionCtx {
706
+ store: EditorStore | History;
707
+ registry: BlockRegistry;
708
+ inlineRegistry: InlineRegistry;
709
+ /** The editor's root element (null before mount). */
710
+ readonly container: HTMLElement | null;
711
+ getBlock(id: string): Block | undefined;
712
+ getRun(id: string): Run | undefined;
713
+ getRootId(): string | null;
714
+ /** Apply an operation, flushing React synchronously so the DOM is current before `setCaret`. */
715
+ applyOperation(op: Operation): void;
716
+ applyOperations(ops: Operation[]): void;
717
+ getSelection(): { blockId: string; runId: string; startOffset: number; endOffset: number } | null;
718
+ getCaret(): { blockId: string; runId: string; offset: number } | null;
719
+ setCaret(runId: string, offset: number): void;
720
+ subscribe(listener: () => void): () => void;
721
+ }
722
+
723
+ /** A keymap handler — return truthy to mark the key handled. */
724
+ export type KeymapHandler = (ctx: ExtensionCtx, event: KeyboardEvent) => boolean | void;
725
+ /** A beforeinput/paste handler — return truthy to mark the event handled. */
726
+ export type ExtensionEventHandler = (ctx: ExtensionCtx, event: Event) => boolean | void;
727
+
728
+ export interface DefineExtensionConfig {
729
+ /** Label for the bundle / diagnostics. */
730
+ name: string;
731
+ blocks?: BlockDefinition[];
732
+ inlineTypes?: InlineDefinition[];
733
+ /** `{ 'Mod-Shift-x': (ctx, event) => boolean }` — `Mod` is Ctrl/Cmd. */
734
+ keymap?: Record<string, KeymapHandler>;
735
+ onBeforeInput?: ExtensionEventHandler;
736
+ onPaste?: ExtensionEventHandler;
737
+ /** Runs once on mount; may return a cleanup function. */
738
+ setup?: (ctx: ExtensionCtx) => void | (() => void);
739
+ [key: string]: unknown;
740
+ }
741
+
742
+ export function defineBlock(config: DefineBlockConfig): BlockDefinition;
743
+ export function defineInline(config: DefineInlineConfig): InlineDefinition;
744
+ /** Groups block/inline definitions and/or behavior (keymap/onBeforeInput/onPaste/setup) under one name. */
745
+ export function defineExtension(config: DefineExtensionConfig): ExtensionBundle;
746
+
747
+ /** Opt-in typing behavior: straight quotes -> curly. */
748
+ export function smartQuotes(): ExtensionBundle;
749
+ /** Opt-in typing behavior: auto-close `(` `[` `{`. */
750
+ export function autoPairBrackets(): ExtensionBundle;
751
+
752
+ /** Registers a flat/nested array of `defineBlock()` / `defineInline()` results (and `defineExtension()` bundles) onto the given registries. */
753
+ export function registerExtensions(
754
+ extensions: ReadonlyArray<Extension | ReadonlyArray<Extension>>,
755
+ registries: { registry?: BlockRegistry; inlineRegistry?: InlineRegistry },
756
+ ): void;
757
+
758
+ /** Every built-in block + inline type as an `extensions` array. `exclude` drops types by name. */
759
+ export function starterKit(options?: { exclude?: string[] }): Extension[];
760
+
589
761
  // ---------------------------------------------------------------------------
590
762
  // react/ — provider, core hooks
591
763
  // ---------------------------------------------------------------------------
@@ -604,7 +776,10 @@ export interface EditorProviderProps {
604
776
  /** Whether CodeBlock renders its line-number gutter -- see useShowLineNumbers. */
605
777
  showLineNumbers?: boolean;
606
778
  /** Sends a picked/dropped EmbedBlock file somewhere real (local disk, S3, any other cloud storage) instead of inlining it as a data: URL -- see useFileUpload's own doc comment for the full contract. */
607
- uploadFile?: (file: File, ctx: { kind: 'image' | 'video' | 'audio' | 'file' }) => Promise<{ src: string; name?: string; mimeType?: string }>;
779
+ uploadFile?: (
780
+ file: File,
781
+ ctx: { kind: 'image' | 'video' | 'audio' | 'file' },
782
+ ) => Promise<{ src: string; name?: string; mimeType?: string }>;
608
783
  /** Byte cap for the in-document data: URL fallback ONLY (no effect once uploadFile is configured) -- an oversized file is rejected with a clear error instead of bloating the document. */
609
784
  maxFileSize?: number;
610
785
  children?: ReactNode;
@@ -624,7 +799,10 @@ export function useCommentAuthorId(): string | undefined;
624
799
  export function useShowLineNumbers(): boolean;
625
800
  /** `{ uploadFile, maxFileSize }` from EditorProvider -- see EditorProviderProps and useFileUpload's own doc comment for the full contract. */
626
801
  export function useFileUpload(): {
627
- uploadFile?: (file: File, ctx: { kind: 'image' | 'video' | 'audio' | 'file' }) => Promise<{ src: string; name?: string; mimeType?: string }>;
802
+ uploadFile?: (
803
+ file: File,
804
+ ctx: { kind: 'image' | 'video' | 'audio' | 'file' },
805
+ ) => Promise<{ src: string; name?: string; mimeType?: string }>;
628
806
  maxFileSize?: number;
629
807
  };
630
808
  export function useFieldTypeEditor(): {
@@ -632,9 +810,13 @@ export function useFieldTypeEditor(): {
632
810
  openFieldTypeEditor: (id: string | null) => void;
633
811
  closeFieldTypeEditor: () => void;
634
812
  };
635
- export function useBlockClassName(baseClassName: string | undefined, block: Block): string | undefined;
813
+ export function useBlockClassName(
814
+ baseClassName: string | undefined,
815
+ block: Block,
816
+ ): string | undefined;
636
817
 
637
- export function injectDefaultStyles(): void;
818
+ /** Inject the default theme `<style>` tag once. The explicit alternative to letting `<EditorProvider>` auto-inject (which a future major will stop doing) — or `import 'noteloom/theme'`. */
819
+ export function injectDefaultStyles(options?: { auto?: boolean }): void;
638
820
 
639
821
  export function useBlock(id: string): Block | undefined;
640
822
  export function useRun(id: string): Run | undefined;
@@ -661,7 +843,9 @@ export function usePersistedDocument(options: {
661
843
  onSave?: () => void;
662
844
  }): { isLoaded: boolean; save: () => Promise<void> };
663
845
 
664
- export function usePresence(session: CollabSession | null | undefined): Map<string, Record<string, unknown>>;
846
+ export function usePresence(
847
+ session: CollabSession | null | undefined,
848
+ ): Map<string, Record<string, unknown>>;
665
849
 
666
850
  export function useServiceWorkerUpdate(): { updateAvailable: boolean; applyUpdate: () => void };
667
851
 
@@ -694,7 +878,12 @@ export const MobileActionBar: ComponentType<{ containerRef: RefObject<HTMLElemen
694
878
  export const MobileBlockPickerSheet: ComponentType<Record<string, unknown>>;
695
879
  export const MobileBlockOptionsSheet: ComponentType<Record<string, unknown>>;
696
880
  export const EditableBlockContent: ComponentType<Record<string, unknown>>;
697
- export const Modal: ComponentType<{ isOpen?: boolean; onClose?: () => void; children?: ReactNode; [key: string]: unknown }>;
881
+ export const Modal: ComponentType<{
882
+ isOpen?: boolean;
883
+ onClose?: () => void;
884
+ children?: ReactNode;
885
+ [key: string]: unknown;
886
+ }>;
698
887
  export const Select: ComponentType<Record<string, unknown>>;
699
888
  export const EditorTrailingSpace: ComponentType<Record<string, unknown>>;
700
889
 
@@ -729,11 +918,47 @@ export function deserializeClipboard(...args: unknown[]): unknown;
729
918
  export function walkDomToBlocks(...args: unknown[]): unknown;
730
919
  export function textToParagraphs(...args: unknown[]): unknown;
731
920
  /** Returns a JSON *string* (pretty-printed by default) — parse it (`JSON.parse`) to get back a plain `{ version, rootId, blocks, runs }` object usable as `useEditor({ doc })`. */
732
- export function exportDocumentJSON(store: EditorStore | History, options?: { pretty?: boolean }): string;
921
+ export function exportDocumentJSON(
922
+ store: EditorStore | History,
923
+ options?: { pretty?: boolean },
924
+ ): string;
733
925
  export function exportDocumentHTML(store: EditorStore | History, registry: BlockRegistry): string;
734
926
  export function exportDocumentText(store: EditorStore | History, registry: BlockRegistry): string;
735
- export function exportDocumentSimpleJSON(store: EditorStore | History, registry: BlockRegistry, inlineRegistry: InlineRegistry): unknown;
736
- export function importDocumentSimpleJSON(json: unknown, registry: BlockRegistry, inlineRegistry: InlineRegistry): DocumentJSON;
927
+ export function exportDocumentMarkdown(
928
+ store: EditorStore | History,
929
+ registry: BlockRegistry,
930
+ inlineRegistry?: InlineRegistry,
931
+ ): string;
932
+ export function exportDocumentWordHTML(
933
+ store: EditorStore | History,
934
+ registry: BlockRegistry,
935
+ inlineRegistry?: InlineRegistry,
936
+ ): string;
937
+ /** A `{ id, type, data, children? }` block in the simple document format. */
938
+ export interface SimpleBlock {
939
+ id: string;
940
+ type: string;
941
+ data: Record<string, unknown>;
942
+ children?: SimpleBlock[];
943
+ }
944
+ /** The canonical interchange format — see docs/document.schema.json. */
945
+ export interface SimpleDocument {
946
+ version: 1;
947
+ blocks: SimpleBlock[];
948
+ }
949
+ export function exportDocumentSimpleJSON(
950
+ store: EditorStore | History,
951
+ registry: BlockRegistry,
952
+ inlineRegistry: InlineRegistry,
953
+ options?: { pretty?: boolean },
954
+ ): string;
955
+ export function importDocumentSimpleJSON(
956
+ json: string | SimpleDocument,
957
+ registry: BlockRegistry,
958
+ inlineRegistry: InlineRegistry,
959
+ ): DocumentJSON;
960
+ /** True when `doc` is a `SimpleDocument` rather than the internal `DocumentJSON` shape. */
961
+ export function isSimpleDocument(doc: unknown): doc is SimpleDocument;
737
962
  export const DocumentExportButton: ComponentType<Record<string, unknown>>;
738
963
 
739
964
  // ---------------------------------------------------------------------------
@@ -761,9 +986,15 @@ export interface SlashMenuProps {
761
986
  }
762
987
 
763
988
  export const SlashMenu: ComponentType<SlashMenuProps>;
764
- export function useSlashMenuTrigger(containerRef: RefObject<HTMLElement | null>): CommandMenuTriggerState;
765
- export function useEmojiMenuTrigger(containerRef: RefObject<HTMLElement | null>): CommandMenuTriggerState;
766
- export function useAtMenuTrigger(containerRef: RefObject<HTMLElement | null>): CommandMenuTriggerState;
989
+ export function useSlashMenuTrigger(
990
+ containerRef: RefObject<HTMLElement | null>,
991
+ ): CommandMenuTriggerState;
992
+ export function useEmojiMenuTrigger(
993
+ containerRef: RefObject<HTMLElement | null>,
994
+ ): CommandMenuTriggerState;
995
+ export function useAtMenuTrigger(
996
+ containerRef: RefObject<HTMLElement | null>,
997
+ ): CommandMenuTriggerState;
767
998
 
768
999
  export interface FloatingToolbarProps {
769
1000
  isOpen: boolean;
@@ -802,6 +1033,12 @@ export function renameColumn(...args: unknown[]): unknown;
802
1033
  export function setColumnType(...args: unknown[]): unknown;
803
1034
  export function setColumnOptions(...args: unknown[]): unknown;
804
1035
  export function setColumnWidth(...args: unknown[]): unknown;
1036
+ export function sortTableByColumn(...args: unknown[]): unknown;
1037
+ export function setColumnAggregate(...args: unknown[]): unknown;
1038
+ export function computeColumnAggregate(...args: unknown[]): unknown;
1039
+ export function formatAggregateValue(value: number | null): string;
1040
+ export const AGGREGATE_TYPES: string[];
1041
+ export const AGGREGATE_LABELS: Record<string, string>;
805
1042
  export function resolveColumns(...args: unknown[]): unknown;
806
1043
  export function createDefaultColumns(...args: unknown[]): unknown;
807
1044
  export function createCellForColumn(...args: unknown[]): unknown;
@@ -853,8 +1090,14 @@ export function copyBlockRangeToClipboard(...args: unknown[]): unknown;
853
1090
  // ---------------------------------------------------------------------------
854
1091
 
855
1092
  export function createSelectFieldType(options: Record<string, unknown>): InlineTypeDefinition;
856
- export function registerStoredFieldTypes(inlineRegistry: InlineRegistry, fieldTypes: FieldType[]): void;
857
- export function useRegisterFieldTypes(inlineRegistry: InlineRegistry, fieldTypes: FieldType[]): void;
1093
+ export function registerStoredFieldTypes(
1094
+ inlineRegistry: InlineRegistry,
1095
+ fieldTypes: FieldType[],
1096
+ ): void;
1097
+ export function useRegisterFieldTypes(
1098
+ inlineRegistry: InlineRegistry,
1099
+ fieldTypes: FieldType[],
1100
+ ): void;
858
1101
  export const FieldTypeEditorModal: ComponentType<Record<string, unknown>>;
859
1102
 
860
1103
  // ---------------------------------------------------------------------------
@@ -862,15 +1105,17 @@ export const FieldTypeEditorModal: ComponentType<Record<string, unknown>>;
862
1105
  // ---------------------------------------------------------------------------
863
1106
 
864
1107
  export interface UseEditorOptions {
865
- /** Starting document; defaults to one empty paragraph. */
866
- doc?: DocumentJSON;
1108
+ /** Starting document; defaults to one empty paragraph. Accepts either the simple format (`SimpleDocument`, what `editor.toJSON()` returns) or the internal engine shape (`DocumentJSON`) — auto-detected. */
1109
+ doc?: DocumentJSON | SimpleDocument;
867
1110
  /** true (default): store is undo/redo-aware (a History instance). false: a plain EditorStore. */
868
1111
  history?: boolean;
869
1112
  /** Stamped as every edit's actorId (History's defaultActorId) -- used by createAutoVersionHistory/VersionHistory for "who changed this", with no separate identity plumbing needed. Ignored when history: false. */
870
1113
  currentUserId?: string | null;
871
- /** Replaces registerBuiltInBlocks for an opt-in subset of block types. */
1114
+ /** Recommended: an array of `defineBlock()` / `defineInline()` results (nesting allowed), e.g. `[...starterKit(), myBlock]`. Passing it turns off automatic built-in registration; `registerBlocks`/`registerInlineTypes`, if also given, still run afterward. */
1115
+ extensions?: ReadonlyArray<Extension | ReadonlyArray<Extension>>;
1116
+ /** Callback form: replaces registerBuiltInBlocks for an opt-in subset of block types. Runs after `extensions` if both are given. */
872
1117
  registerBlocks?: (registry: BlockRegistry) => void;
873
- /** Replaces registerBuiltInInlineTypes for an opt-in subset of inline types. */
1118
+ /** Callback form: replaces registerBuiltInInlineTypes for an opt-in subset of inline types. Runs after `extensions` if both are given. */
874
1119
  registerInlineTypes?: (inlineRegistry: InlineRegistry) => void;
875
1120
  }
876
1121
 
@@ -878,6 +1123,10 @@ export interface UseEditorResult {
878
1123
  store: History | EditorStore;
879
1124
  registry: BlockRegistry;
880
1125
  inlineRegistry: InlineRegistry;
1126
+ /** The flattened `extensions` list, forwarded to `<NoteloomEditor>` for the behavior half. */
1127
+ extensions: Extension[];
1128
+ /** Read the live document out. `'simple'` (default) → `SimpleDocument`; `'internal'` → `DocumentJSON`. */
1129
+ toJSON(options?: { format?: 'simple' | 'internal' }): SimpleDocument | DocumentJSON;
881
1130
  }
882
1131
 
883
1132
  /** The one-call path to a working editor — see the README's Quick start. */
@@ -896,7 +1145,10 @@ export interface NoteloomEditorProps {
896
1145
  /** Renders CommentsPanel (right-side, Notion/Google Docs-style thread list) automatically. */
897
1146
  showCommentsPanel?: boolean;
898
1147
  /** Sends a picked/dropped EmbedBlock file somewhere real (local disk, S3, any other cloud storage) instead of inlining it as a data: URL -- see useFileUpload's own doc comment for the full contract. */
899
- uploadFile?: (file: File, ctx: { kind: 'image' | 'video' | 'audio' | 'file' }) => Promise<{ src: string; name?: string; mimeType?: string }>;
1148
+ uploadFile?: (
1149
+ file: File,
1150
+ ctx: { kind: 'image' | 'video' | 'audio' | 'file' },
1151
+ ) => Promise<{ src: string; name?: string; mimeType?: string }>;
900
1152
  /** Byte cap for the in-document data: URL fallback ONLY (no effect once uploadFile is configured). */
901
1153
  maxFileSize?: number;
902
1154
  children?: ReactNode;
@@ -904,3 +1156,91 @@ export interface NoteloomEditorProps {
904
1156
 
905
1157
  /** Renders the object useEditor() returned, with every built-in interaction wired up. */
906
1158
  export function NoteloomEditor(props: NoteloomEditorProps): ReactElement;
1159
+
1160
+ export interface FindMatch {
1161
+ blockId: string;
1162
+ runId: string;
1163
+ offset: number;
1164
+ length: number;
1165
+ }
1166
+
1167
+ /** Finds every occurrence of `query` in the document, in reading order — single-run matches only (see the implementation's own doc comment for scope). */
1168
+ export function findMatches(
1169
+ store: EditorStore | History,
1170
+ query: string,
1171
+ options?: { caseSensitive?: boolean; wholeWord?: boolean },
1172
+ ): FindMatch[];
1173
+ /** Replaces one match's own slice of its run's text, one atomic write. */
1174
+ export function replaceMatch(
1175
+ store: EditorStore | History,
1176
+ match: FindMatch,
1177
+ replacement: string,
1178
+ ): void;
1179
+ /** Replaces every given match, one write per affected run, one atomic undo step. */
1180
+ export function replaceAllMatches(
1181
+ store: EditorStore | History,
1182
+ matches: FindMatch[],
1183
+ replacement: string,
1184
+ ): void;
1185
+
1186
+ export interface UseFindInDocumentResult {
1187
+ isOpen: boolean;
1188
+ open: () => void;
1189
+ close: () => void;
1190
+ query: string;
1191
+ setQuery: (value: string) => void;
1192
+ caseSensitive: boolean;
1193
+ setCaseSensitive: (value: boolean) => void;
1194
+ wholeWord: boolean;
1195
+ setWholeWord: (value: boolean) => void;
1196
+ isReplaceOpen: boolean;
1197
+ setIsReplaceOpen: (value: boolean) => void;
1198
+ replacement: string;
1199
+ setReplacement: (value: string) => void;
1200
+ matches: FindMatch[];
1201
+ currentIndex: number;
1202
+ next: () => void;
1203
+ prev: () => void;
1204
+ replaceCurrent: () => void;
1205
+ replaceAll: () => void;
1206
+ queryInputRef: RefObject<HTMLInputElement | null>;
1207
+ }
1208
+
1209
+ /** Ctrl/Cmd+F (while `containerRef` has focus) find/replace — see NoteloomEditor's own doc comment for scope. Pair with `<FindBar>`, or build custom chrome off this hook's returned state/actions directly. */
1210
+ export function useFindInDocument(
1211
+ containerRef: RefObject<HTMLElement | null>,
1212
+ ): UseFindInDocumentResult;
1213
+ export function FindBar(props: UseFindInDocumentResult): ReactElement | null;
1214
+
1215
+ // ---------------------------------------------------------------------------
1216
+ // people/people.js, react/usePeople.js — a document's own people list
1217
+ // ---------------------------------------------------------------------------
1218
+
1219
+ export interface Person {
1220
+ id: string;
1221
+ name: string;
1222
+ color?: string;
1223
+ [key: string]: unknown;
1224
+ }
1225
+
1226
+ export function addPerson(
1227
+ store: EditorStore | History,
1228
+ person: { name: string; color?: string },
1229
+ ): string;
1230
+ export function updatePerson(
1231
+ store: EditorStore | History,
1232
+ id: string,
1233
+ patch: Partial<Person>,
1234
+ ): void;
1235
+ export function removePerson(store: EditorStore | History, id: string): void;
1236
+ /** Reactive view of the document's `people` collection. */
1237
+ export function usePeople(): Person[];
1238
+
1239
+ // ---------------------------------------------------------------------------
1240
+ // react/useSmartQuotes.js, react/useAutoPairBrackets.js — optional typing behaviors
1241
+ // ---------------------------------------------------------------------------
1242
+
1243
+ /** Straight `"`/`'` typed while composing becomes the contextually correct curly quote (one char in, one out). */
1244
+ export function useSmartQuotes(): void;
1245
+ /** Typing `(`/`[`/`{` inserts the matching closer and puts the caret between them; excludes quotes (that's `useSmartQuotes`). Off inside `code` blocks. */
1246
+ export function useAutoPairBrackets(): void;