@sofereditor/react 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,32 @@
1
- import { RefObject, ReactNode, JSX } from 'react';
2
- import { EditorDocument, EditorHistory, SerializedDocument, Selection, MarkName, MarkAttrs, BlockType, BlockAttrs, ListKind, PageSettings, TableLocation, TableRect, ImageEmbed, SerializedBlock, DeltaOp } from '@sofereditor/core';
1
+ import { RefObject, JSX, ReactNode } from 'react';
2
+ import { EditorDocument, EditorHistory, SerializedDocument, Selection, MarkName, MarkAttrs, BlockType, BlockAttrs, AlignValue, ListKind, PageSettings, TableLocation, TableRect, ImageEmbed, EmbedLoc, SerializedBlock, DeltaOp, Position } from '@sofereditor/core';
3
+
4
+ /**
5
+ * Subconjunto mínimo da Awareness do y-protocols que o overlay usa. Tipar assim
6
+ * evita que `@sofereditor/react` dependa de `y-protocols` — o objeto vem de fora
7
+ * (de `useCollab().binding.awareness`) e é estruturalmente compatível.
8
+ */
9
+ interface AwarenessLike {
10
+ clientID: number;
11
+ getStates(): Map<number, Record<string, unknown>>;
12
+ on(event: "change", cb: () => void): void;
13
+ off(event: "change", cb: () => void): void;
14
+ setLocalStateField(field: string, value: unknown): void;
15
+ }
16
+ interface RemoteCursorsOverlayProps {
17
+ rootRef: RefObject<HTMLDivElement>;
18
+ doc: EditorDocument;
19
+ awareness: AwarenessLike;
20
+ /** Muda a cada edição/repaginação → re-medir os carets remotos. */
21
+ revision?: unknown;
22
+ }
23
+ /**
24
+ * Desenha o caret + seleção + nome de cada usuário remoto sobre o conteúdo
25
+ * paginado. Posições remotas chegam via awareness (campo `cursor`, codificado
26
+ * com Y.RelativePosition pelo core) e são resolvidas para coordenadas DOM com
27
+ * o mesmo bridge da seleção local — ciente de fragmentação por página.
28
+ */
29
+ declare function RemoteCursorsOverlay({ rootRef, doc, awareness, revision, }: RemoteCursorsOverlayProps): JSX.Element | null;
3
30
 
4
31
  /**
5
32
  * Sub-phase 3.2 — page layout with intra-paragraph fragmentation.
@@ -105,6 +132,8 @@ type PendingMarks = Partial<Record<MarkName, MarkAttrs[MarkName] | null>>;
105
132
  interface LinkRequest {
106
133
  initialHref: string;
107
134
  resolve: (href: string | null) => void;
135
+ /** Model selection captured when the link was requested (bug #6). */
136
+ selection: Selection;
108
137
  }
109
138
  interface PageConfigRequest {
110
139
  initial: PageSettings;
@@ -145,6 +174,8 @@ interface UseEditorResult {
145
174
  getBlockAttr: <K extends keyof BlockAttrs>(key: K) => BlockAttrs[K] | "mixed" | undefined;
146
175
  setBlockType: (type: BlockType, attrs?: BlockAttrs) => void;
147
176
  setBlockAttr: <K extends keyof BlockAttrs>(key: K, value: BlockAttrs[K] | null) => void;
177
+ setAlign: (value: AlignValue) => void;
178
+ getAlign: () => AlignValue | "mixed" | undefined;
148
179
  isListActive: (kind: ListKind) => boolean;
149
180
  toggleList: (kind: ListKind) => void;
150
181
  indentList: () => void;
@@ -202,6 +233,11 @@ interface UseEditorResult {
202
233
  mergeSelection: () => boolean;
203
234
  insertImage: (embed: ImageEmbed) => void;
204
235
  setImageAttrs: (blockIndex: number, offset: number, partial: Partial<ImageEmbed>, cellIndex?: number, newOffset?: number) => void;
236
+ /**
237
+ * Move a floating image embed from one anchor to another (re-anchor across
238
+ * blocks/pages) in a single transaction. No-op for inline embeds.
239
+ */
240
+ moveEmbedAnchor: (from: EmbedLoc, to: EmbedLoc, newOffsetX: number, newOffsetY: number) => void;
205
241
  /** Read a File (image) and insert it inline at the caret as a data-URL embed. */
206
242
  insertImageFromFile: (file: File) => Promise<void>;
207
243
  /**
@@ -244,8 +280,14 @@ interface EditorProps {
244
280
  * `"<n> / <total>"` centered. Pass `null` to omit.
245
281
  */
246
282
  renderPageFooter?: PageRenderProp | null;
283
+ /**
284
+ * Awareness do Yjs (de `useCollab().binding.awareness`). Quando presente,
285
+ * o editor publica a seleção local e desenha os cursores/seleções dos outros
286
+ * usuários (presença colaborativa). Omitir = sem cursores remotos.
287
+ */
288
+ awareness?: AwarenessLike;
247
289
  }
248
- declare function Editor({ editor: providedEditor, className, pageGeometry, renderPageHeader, renderPageFooter, }: EditorProps): JSX.Element;
290
+ declare function Editor({ editor: providedEditor, className, pageGeometry, renderPageHeader, renderPageFooter, awareness, }: EditorProps): JSX.Element;
249
291
 
250
292
  /**
251
293
  * Modal dialog for entering a link URL. Replaces the bare `window.prompt`
@@ -368,6 +410,11 @@ declare function getCellElement(root: HTMLElement, blockIndex: number, cellIndex
368
410
  */
369
411
  declare function textOffsetWithin(container: HTMLElement, node: Node, offsetInNode: number): number;
370
412
  declare function readDomSelection(root: HTMLElement): Selection | null;
413
+ interface DomPoint {
414
+ node: Node;
415
+ offset: number;
416
+ }
417
+ declare function locatePoint(root: HTMLElement, pos: Position): DomPoint | null;
371
418
  declare function selectionsEqual(a: Selection, b: Selection): boolean;
372
419
  /**
373
420
  * `true` when the selection is a rectangular table-cell range — both endpoints
@@ -379,4 +426,4 @@ declare function selectionsEqual(a: Selection, b: Selection): boolean;
379
426
  declare function isTableRectSelection(sel: Selection): boolean;
380
427
  declare function applyDomSelection(root: HTMLElement, modelSel: Selection): void;
381
428
 
382
- export { A4_PAGE, type BlockFragment, type CaptionAlign, Editor, type EditorProps, EditorProvider, type EditorProviderProps, ImageCaptionDialog, type ImageCaptionRequest, type ImageCaptionResult, LinkDialog, type LinkRequest, NodeView, type NodeViewFragment, PageConfigDialog, type PageConfigRequest, type PageEntry, type PageGeometry, type PageLayout, type PageLayoutResult, type PageRenderContext, type PageRenderProp, type PageSlot, type PaginationPhase, type PendingMarks, type TableRowFragment, Toolbar, type ToolbarProps, type UseEditorOptions, type UseEditorResult, applyDomSelection, contentHeight, contentWidth, defaultPageLayout, deltaLength, findBlockIndex, getBlockElement, getCellElement, getFragmentForOffset, isTableRectSelection, readDomSelection, renderInline, selectionsEqual, sliceDelta, textOffsetWithin, useEditor, useEditorContext, usePageLayout, usePageSettings };
429
+ export { A4_PAGE, type BlockFragment, type CaptionAlign, Editor, type EditorProps, EditorProvider, type EditorProviderProps, ImageCaptionDialog, type ImageCaptionRequest, type ImageCaptionResult, LinkDialog, type LinkRequest, NodeView, type NodeViewFragment, PageConfigDialog, type PageConfigRequest, type PageEntry, type PageGeometry, type PageLayout, type PageLayoutResult, type PageRenderContext, type PageRenderProp, type PageSlot, type PaginationPhase, type PendingMarks, RemoteCursorsOverlay, type TableRowFragment, Toolbar, type ToolbarProps, type UseEditorOptions, type UseEditorResult, applyDomSelection, contentHeight, contentWidth, defaultPageLayout, deltaLength, findBlockIndex, getBlockElement, getCellElement, getFragmentForOffset, isTableRectSelection, locatePoint, readDomSelection, renderInline, selectionsEqual, sliceDelta, textOffsetWithin, useEditor, useEditorContext, usePageLayout, usePageSettings };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,32 @@
1
- import { RefObject, ReactNode, JSX } from 'react';
2
- import { EditorDocument, EditorHistory, SerializedDocument, Selection, MarkName, MarkAttrs, BlockType, BlockAttrs, ListKind, PageSettings, TableLocation, TableRect, ImageEmbed, SerializedBlock, DeltaOp } from '@sofereditor/core';
1
+ import { RefObject, JSX, ReactNode } from 'react';
2
+ import { EditorDocument, EditorHistory, SerializedDocument, Selection, MarkName, MarkAttrs, BlockType, BlockAttrs, AlignValue, ListKind, PageSettings, TableLocation, TableRect, ImageEmbed, EmbedLoc, SerializedBlock, DeltaOp, Position } from '@sofereditor/core';
3
+
4
+ /**
5
+ * Subconjunto mínimo da Awareness do y-protocols que o overlay usa. Tipar assim
6
+ * evita que `@sofereditor/react` dependa de `y-protocols` — o objeto vem de fora
7
+ * (de `useCollab().binding.awareness`) e é estruturalmente compatível.
8
+ */
9
+ interface AwarenessLike {
10
+ clientID: number;
11
+ getStates(): Map<number, Record<string, unknown>>;
12
+ on(event: "change", cb: () => void): void;
13
+ off(event: "change", cb: () => void): void;
14
+ setLocalStateField(field: string, value: unknown): void;
15
+ }
16
+ interface RemoteCursorsOverlayProps {
17
+ rootRef: RefObject<HTMLDivElement>;
18
+ doc: EditorDocument;
19
+ awareness: AwarenessLike;
20
+ /** Muda a cada edição/repaginação → re-medir os carets remotos. */
21
+ revision?: unknown;
22
+ }
23
+ /**
24
+ * Desenha o caret + seleção + nome de cada usuário remoto sobre o conteúdo
25
+ * paginado. Posições remotas chegam via awareness (campo `cursor`, codificado
26
+ * com Y.RelativePosition pelo core) e são resolvidas para coordenadas DOM com
27
+ * o mesmo bridge da seleção local — ciente de fragmentação por página.
28
+ */
29
+ declare function RemoteCursorsOverlay({ rootRef, doc, awareness, revision, }: RemoteCursorsOverlayProps): JSX.Element | null;
3
30
 
4
31
  /**
5
32
  * Sub-phase 3.2 — page layout with intra-paragraph fragmentation.
@@ -105,6 +132,8 @@ type PendingMarks = Partial<Record<MarkName, MarkAttrs[MarkName] | null>>;
105
132
  interface LinkRequest {
106
133
  initialHref: string;
107
134
  resolve: (href: string | null) => void;
135
+ /** Model selection captured when the link was requested (bug #6). */
136
+ selection: Selection;
108
137
  }
109
138
  interface PageConfigRequest {
110
139
  initial: PageSettings;
@@ -145,6 +174,8 @@ interface UseEditorResult {
145
174
  getBlockAttr: <K extends keyof BlockAttrs>(key: K) => BlockAttrs[K] | "mixed" | undefined;
146
175
  setBlockType: (type: BlockType, attrs?: BlockAttrs) => void;
147
176
  setBlockAttr: <K extends keyof BlockAttrs>(key: K, value: BlockAttrs[K] | null) => void;
177
+ setAlign: (value: AlignValue) => void;
178
+ getAlign: () => AlignValue | "mixed" | undefined;
148
179
  isListActive: (kind: ListKind) => boolean;
149
180
  toggleList: (kind: ListKind) => void;
150
181
  indentList: () => void;
@@ -202,6 +233,11 @@ interface UseEditorResult {
202
233
  mergeSelection: () => boolean;
203
234
  insertImage: (embed: ImageEmbed) => void;
204
235
  setImageAttrs: (blockIndex: number, offset: number, partial: Partial<ImageEmbed>, cellIndex?: number, newOffset?: number) => void;
236
+ /**
237
+ * Move a floating image embed from one anchor to another (re-anchor across
238
+ * blocks/pages) in a single transaction. No-op for inline embeds.
239
+ */
240
+ moveEmbedAnchor: (from: EmbedLoc, to: EmbedLoc, newOffsetX: number, newOffsetY: number) => void;
205
241
  /** Read a File (image) and insert it inline at the caret as a data-URL embed. */
206
242
  insertImageFromFile: (file: File) => Promise<void>;
207
243
  /**
@@ -244,8 +280,14 @@ interface EditorProps {
244
280
  * `"<n> / <total>"` centered. Pass `null` to omit.
245
281
  */
246
282
  renderPageFooter?: PageRenderProp | null;
283
+ /**
284
+ * Awareness do Yjs (de `useCollab().binding.awareness`). Quando presente,
285
+ * o editor publica a seleção local e desenha os cursores/seleções dos outros
286
+ * usuários (presença colaborativa). Omitir = sem cursores remotos.
287
+ */
288
+ awareness?: AwarenessLike;
247
289
  }
248
- declare function Editor({ editor: providedEditor, className, pageGeometry, renderPageHeader, renderPageFooter, }: EditorProps): JSX.Element;
290
+ declare function Editor({ editor: providedEditor, className, pageGeometry, renderPageHeader, renderPageFooter, awareness, }: EditorProps): JSX.Element;
249
291
 
250
292
  /**
251
293
  * Modal dialog for entering a link URL. Replaces the bare `window.prompt`
@@ -368,6 +410,11 @@ declare function getCellElement(root: HTMLElement, blockIndex: number, cellIndex
368
410
  */
369
411
  declare function textOffsetWithin(container: HTMLElement, node: Node, offsetInNode: number): number;
370
412
  declare function readDomSelection(root: HTMLElement): Selection | null;
413
+ interface DomPoint {
414
+ node: Node;
415
+ offset: number;
416
+ }
417
+ declare function locatePoint(root: HTMLElement, pos: Position): DomPoint | null;
371
418
  declare function selectionsEqual(a: Selection, b: Selection): boolean;
372
419
  /**
373
420
  * `true` when the selection is a rectangular table-cell range — both endpoints
@@ -379,4 +426,4 @@ declare function selectionsEqual(a: Selection, b: Selection): boolean;
379
426
  declare function isTableRectSelection(sel: Selection): boolean;
380
427
  declare function applyDomSelection(root: HTMLElement, modelSel: Selection): void;
381
428
 
382
- export { A4_PAGE, type BlockFragment, type CaptionAlign, Editor, type EditorProps, EditorProvider, type EditorProviderProps, ImageCaptionDialog, type ImageCaptionRequest, type ImageCaptionResult, LinkDialog, type LinkRequest, NodeView, type NodeViewFragment, PageConfigDialog, type PageConfigRequest, type PageEntry, type PageGeometry, type PageLayout, type PageLayoutResult, type PageRenderContext, type PageRenderProp, type PageSlot, type PaginationPhase, type PendingMarks, type TableRowFragment, Toolbar, type ToolbarProps, type UseEditorOptions, type UseEditorResult, applyDomSelection, contentHeight, contentWidth, defaultPageLayout, deltaLength, findBlockIndex, getBlockElement, getCellElement, getFragmentForOffset, isTableRectSelection, readDomSelection, renderInline, selectionsEqual, sliceDelta, textOffsetWithin, useEditor, useEditorContext, usePageLayout, usePageSettings };
429
+ export { A4_PAGE, type BlockFragment, type CaptionAlign, Editor, type EditorProps, EditorProvider, type EditorProviderProps, ImageCaptionDialog, type ImageCaptionRequest, type ImageCaptionResult, LinkDialog, type LinkRequest, NodeView, type NodeViewFragment, PageConfigDialog, type PageConfigRequest, type PageEntry, type PageGeometry, type PageLayout, type PageLayoutResult, type PageRenderContext, type PageRenderProp, type PageSlot, type PaginationPhase, type PendingMarks, RemoteCursorsOverlay, type TableRowFragment, Toolbar, type ToolbarProps, type UseEditorOptions, type UseEditorResult, applyDomSelection, contentHeight, contentWidth, defaultPageLayout, deltaLength, findBlockIndex, getBlockElement, getCellElement, getFragmentForOffset, isTableRectSelection, locatePoint, readDomSelection, renderInline, selectionsEqual, sliceDelta, textOffsetWithin, useEditor, useEditorContext, usePageLayout, usePageSettings };