@fileverse-dev/ddoc 4.7.4 → 4.7.6

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.
@@ -1,4 +1,4 @@
1
- import { k as Ql, b as Zl, s as eh } from "./index-BJWSI0qv.mjs";
1
+ import { k as Ql, b as Zl, s as eh } from "./index-DYufB7JF.mjs";
2
2
  let An = [], Xr = [];
3
3
  (() => {
4
4
  let s = "lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o".split(",").map((e) => e ? parseInt(e, 36) : 1);
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D as e, a as o, E as t, F as d, P as r, f as i, i as n, g as E, j as m, h as C, m as c, e as l, l as p, c as u, d as f, u as D, v as F } from "./index-BJWSI0qv.mjs";
1
+ import { D as e, a as o, E as t, F as d, P as r, f as i, i as n, g as E, j as m, h as C, m as c, e as l, l as p, c as u, d as f, u as D, v as F } from "./index-DYufB7JF.mjs";
2
2
  export {
3
3
  e as DdocEditor,
4
4
  o as DdocExportModal,
@@ -3,7 +3,7 @@ var Wr = (t, e, O) => e in t ? Vr(t, e, { enumerable: !0, configurable: !0, writ
3
3
  var gt = (t, e, O) => Wr(t, typeof e != "symbol" ? e + "" : e, O);
4
4
  import { jsx as Cr } from "react/jsx-runtime";
5
5
  import { useRef as pe, useEffect as St } from "react";
6
- import { s as y, A as pO, T as dO, a as Gr, S as et, b as Lr, P as fO, E as j, i as QO, c as _, D as le, k as tt, F as Ar, M as Pt, W as Er, R as Ur, d as mO, N as oe, e as V, f as Mr, g as Ot, h as ce, p as $O, j as Y, t as h, l as Ir, I as rt, L as at, m as ye, n as ue, o as Qe, q as gO, r as te, u as SO, v as Br, w as Nr, x as PO, y as kO, z as Dr, B as Fr, C as Kr, G as Oe, H as ZO, J as Jr, K as kt, O as Hr, Q as ea, U as ta, V as Oa, X as ra, Y as aa, Z as ia, _ as sa, $ as na, a0 as la, a1 as oa, a2 as ca } from "./index-BYGWNqrf.mjs";
6
+ import { s as y, A as pO, T as dO, a as Gr, S as et, b as Lr, P as fO, E as j, i as QO, c as _, D as le, k as tt, F as Ar, M as Pt, W as Er, R as Ur, d as mO, N as oe, e as V, f as Mr, g as Ot, h as ce, p as $O, j as Y, t as h, l as Ir, I as rt, L as at, m as ye, n as ue, o as Qe, q as gO, r as te, u as SO, v as Br, w as Nr, x as PO, y as kO, z as Dr, B as Fr, C as Kr, G as Oe, H as ZO, J as Jr, K as kt, O as Hr, Q as ea, U as ta, V as Oa, X as ra, Y as aa, Z as ia, _ as sa, $ as na, a0 as la, a1 as oa, a2 as ca } from "./index-DqOL-hci.mjs";
7
7
  class ua {
8
8
  /**
9
9
  Create a new completion context. (Mostly useful for testing
@@ -5,3 +5,16 @@ export declare const shouldShow: ({ editor }: {
5
5
  editor: Editor;
6
6
  }) => boolean;
7
7
  export declare const shouldShowIgnoringFocus: (editor: Editor) => boolean;
8
+ /**
9
+ * Whether the bubble menu should take itself out of the way.
10
+ *
11
+ * It floats at an inline `z-index: 61` while @fileverse/ui dialogs stack at
12
+ * `z-50`, so a modal cannot paint over it — anything that owns the screen has
13
+ * to hide the menu explicitly or it overlaps the dialog.
14
+ */
15
+ export declare const isBubbleMenuHidden: ({ isCommentOpen, isLinkPopupOpen, isBubbleMenuSuppressed, isCustomSpacingOpen, }: {
16
+ isCommentOpen: boolean;
17
+ isLinkPopupOpen: boolean;
18
+ isBubbleMenuSuppressed: boolean;
19
+ isCustomSpacingOpen: boolean;
20
+ }) => boolean;
@@ -0,0 +1,14 @@
1
+ import { Editor } from '@tiptap/core';
2
+
3
+ export declare const CustomSpacingDialog: ({ editor, open, onOpenChange, }: {
4
+ editor: Editor | null;
5
+ open: boolean;
6
+ onOpenChange: (open: boolean) => void;
7
+ }) => import("react/jsx-runtime").JSX.Element;
8
+ /**
9
+ * The single mounted instance, wired to the store. Subscribing here rather
10
+ * than at the mount site keeps the open/close re-render off the editor tree.
11
+ */
12
+ export declare const CustomSpacingDialogHost: ({ editor, }: {
13
+ editor: Editor | null;
14
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,9 @@
1
+ import { Editor } from '@tiptap/core';
1
2
  import { IEditorToolElement } from '../editor-utils';
2
3
 
3
- export declare const LineHeightDropdown: ({ tool, currentLineHeight, onSetLineHeight, }: {
4
+ export declare const LineHeightDropdown: ({ tool, editor, currentLineHeight, onSetLineHeight, }: {
4
5
  tool: IEditorToolElement;
6
+ editor: Editor | null;
5
7
  currentLineHeight?: string;
6
8
  onSetLineHeight: (lineHeight: string) => void;
7
9
  }) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { Editor } from '@tiptap/core';
2
+
3
+ export type SpacingToggle = {
4
+ edge: 'before' | 'after';
5
+ label: string;
6
+ onSelect: () => void;
7
+ };
8
+ /**
9
+ * Write one half of the toggle.
10
+ *
11
+ * Both halves write an explicit value. Removing writes 0, because null hands
12
+ * the block back to the stylesheet — the very gap being removed. Adding writes
13
+ * SPACING_ADD_PT for the mirror-image reason: "Add" is only offered when the
14
+ * stylesheet already gives nothing, so null would leave it at zero.
15
+ *
16
+ * Exported so the second-level nav's registry entry writes exactly what the
17
+ * toolbar dropdown and bubble menu write, without rebuilding the toggle list.
18
+ */
19
+ export declare const applySpacingToggle: (editor: Editor | null, edge: "before" | "after", action: "add" | "remove") => boolean | undefined;
20
+ /** The menu wording for one half, shared so every surface reads identically. */
21
+ export declare const spacingToggleLabel: (edge: "before" | "after", action: "add" | "remove") => string;
22
+ /**
23
+ * The Google Docs "Add / Remove space before|after paragraph" pair, shared by
24
+ * the toolbar dropdown and the bubble menu so the label logic exists once.
25
+ *
26
+ * The label reflects what the block actually renders with, stylesheet
27
+ * included, so a fresh paragraph offers "Remove" first — its gap comes from
28
+ * editor.css rather than from an attribute.
29
+ */
30
+ export declare const getSpacingToggles: (editor: Editor | null) => SpacingToggle[];
@@ -152,12 +152,13 @@ export declare const FontSizePicker: ({ editor, setVisibility, elementRef, curre
152
152
  currentSize?: string;
153
153
  onSetFontSize: (fontSize: string) => void;
154
154
  }) => import("react/jsx-runtime").JSX.Element;
155
- export declare const LineHeightPicker: ({ setVisibility, elementRef, currentLineHeight, onSetLineHeight, }: {
155
+ export declare const LineHeightPicker: ({ editor, setVisibility, elementRef, currentLineHeight, onSetLineHeight, onOpenCustomSpacing, }: {
156
156
  editor: Editor;
157
157
  elementRef: React.RefObject<HTMLDivElement>;
158
158
  setVisibility: Dispatch<SetStateAction<IEditorTool>>;
159
159
  currentLineHeight?: string;
160
160
  onSetLineHeight: (lineHeight: string) => void;
161
+ onOpenCustomSpacing?: () => void;
161
162
  }) => import("react/jsx-runtime").JSX.Element;
162
163
  export declare const TextFormatingPopup: ({ editor, isOpen, setIsOpen, setToolVisibility, }: {
163
164
  editor: Editor | null;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Paragraph spacing read straight out of the OOXML.
3
+ *
4
+ * Mammoth is a *semantic* converter — its README is explicit that it uses "the
5
+ * semantic information in the document, and ignoring other details" — so it
6
+ * never parses w:spacing at all. Structure still comes from mammoth; only the
7
+ * presentational values we model are read here, from the same arrayBuffer.
8
+ */
9
+ export type DocxParagraphSpacing = {
10
+ spaceBefore: number | null;
11
+ spaceAfter: number | null;
12
+ lineHeight: string | null;
13
+ /** Paragraph text, used to verify alignment against mammoth's output. */
14
+ text: string;
15
+ };
16
+ /**
17
+ * One entry per w:p, in document order — the same order mammoth emits its
18
+ * blocks in, which is what makes them zippable.
19
+ */
20
+ export declare const readDocxSpacing: (documentXml: string, stylesXml: string) => DocxParagraphSpacing[];
21
+ /**
22
+ * Zip the spacing onto mammoth's HTML as inline styles, which the LineHeight
23
+ * and ParagraphSpacing attributes already parse back on import.
24
+ *
25
+ * Alignment is positional, so it is verified rather than trusted: mammoth
26
+ * relocates text boxes and appends footnotes, and `ignoreEmptyParagraphs`
27
+ * has to stay off for the counts to line up at all. On any divergence the
28
+ * HTML is returned untouched — no spacing is better than spacing on the
29
+ * wrong paragraphs, which is silent and hard to trace.
30
+ */
31
+ export declare const applyDocxSpacingToHtml: (html: string, spacings: DocxParagraphSpacing[]) => string;
32
+ /**
33
+ * Read the spacing out of the .docx archive and zip it onto mammoth's HTML.
34
+ *
35
+ * Reuses the arrayBuffer mammoth is already given, so the file is not read
36
+ * twice. Every failure path returns the original HTML: losing spacing is
37
+ * recoverable, losing the import is not.
38
+ */
39
+ export declare const readDocxSpacingFromArchive: (arrayBuffer: ArrayBuffer, html: string) => Promise<string>;
@@ -18,5 +18,12 @@ declare module '@tiptap/core' {
18
18
  * Carrying the current line-height onto the next block is handled by the
19
19
  * dBlock `Enter` handler (extensions/d-block/dblock.ts), alongside the
20
20
  * fontFamily/fontSize persistence — not by an inheritance plugin here.
21
+ *
22
+ * Scope is selection-based, like textAlign: a collapsed cursor styles the block
23
+ * it sits in, and whole-document is Cmd+A. It used to restyle the entire
24
+ * document on a collapsed cursor, which stopped being defensible once the
25
+ * selection-scoped "Custom spacing" item joined these presets in one dropdown.
21
26
  */
27
+ /** 1.15 in the UI. Exported so serializers can tell "default" from "authored". */
28
+ export declare const DEFAULT_LINE_HEIGHT = "138%";
22
29
  export declare const LineHeight: Extension<any, any>;
@@ -47,6 +47,12 @@ export declare const stripFrontmatter: (markdown: string) => string;
47
47
  export declare function handleMarkdownContent(view: any, content: string, ipfsImageUploadFn?: (file: File) => Promise<IpfsImageUploadResponse>, options?: {
48
48
  breaks?: boolean;
49
49
  replaceAll?: boolean;
50
+ /** Keep authored blank lines. DOCX import sets this: a blank line the
51
+ * author typed is content, and mammoth is asked to emit it
52
+ * (ignoreEmptyParagraphs: false) precisely so it survives. Markdown
53
+ * paste leaves it off — markdown-it emits stray empty paragraphs of its
54
+ * own that nobody typed. */
55
+ preserveEmptyParagraphs?: boolean;
50
56
  }): Promise<void>;
51
57
  export default MarkdownPasteHandler;
52
58
  export declare function searchForSecureImageNodeAndEmbedImageContent(originalDoc: PMNode, ipfsImageFetchFn?: (_data: IpfsImageFetchPayload) => Promise<{
@@ -0,0 +1,52 @@
1
+ import { Extension } from '@tiptap/core';
2
+ import { Node as ProseMirrorNode } from '@tiptap/pm/model';
3
+
4
+ export type ParagraphSpacingAttrs = {
5
+ /** Space above the block, in pt. `null` unsets it; omit to leave as-is. */
6
+ spaceBefore?: number | null;
7
+ /** Space below the block, in pt. `null` unsets it; omit to leave as-is. */
8
+ spaceAfter?: number | null;
9
+ };
10
+ declare module '@tiptap/core' {
11
+ interface Commands<ReturnType> {
12
+ paragraphSpacing: {
13
+ /**
14
+ * Set space before/after on the blocks in the current selection.
15
+ */
16
+ setParagraphSpacing: (attrs: ParagraphSpacingAttrs) => ReturnType;
17
+ /**
18
+ * Clear both space before and space after on the current selection.
19
+ */
20
+ unsetParagraphSpacing: () => ReturnType;
21
+ };
22
+ }
23
+ }
24
+ /**
25
+ * `spaceBefore` / `spaceAfter` as inline margins, in pt.
26
+ *
27
+ * Unlike `lineHeight`, the default is `null` — an untouched block renders no
28
+ * inline margin at all, so the stylesheet in editor.css (including its
29
+ * responsive overrides and :first-child resets) stays in charge. `0` is a
30
+ * distinct, explicit value: it renders `margin-*: 0` and overrides that CSS.
31
+ */
32
+ export declare const ParagraphSpacing: Extension<any, any>;
33
+ /**
34
+ * Whether a block the selection passes through is one the selection is really
35
+ * IN, rather than a container wrapped around it.
36
+ *
37
+ * nodesBetween reports every ancestor spanning the range. That is harmless for
38
+ * paragraphs and headings, which cannot nest — but a list item holds its
39
+ * sublist inside it, so a cursor in a sub-bullet also reports the parent item,
40
+ * the grandparent item, and so on to the top of the list. Left unchecked, one
41
+ * "add space" puts a gap on every bullet up the chain, and reading back drags
42
+ * the dialog to 'mixed' and flips the Add/Remove toggle using an ancestor's
43
+ * value.
44
+ *
45
+ * An item owns the selection only where the range touches its OWN content — a
46
+ * direct textblock child. A range that merely passes through a non-textblock
47
+ * child (the nested list) belongs to the item inside it, not to this one.
48
+ *
49
+ * Written against node shape rather than node names so it holds for any
50
+ * nesting container, in either schema version.
51
+ */
52
+ export declare const ownsSpacingAt: (node: ProseMirrorNode, pos: number, from: number, to: number) => boolean;
@@ -7,7 +7,7 @@ export type EditorCommand = {
7
7
  isEnabled: boolean;
8
8
  current?: string | null;
9
9
  };
10
- export type EditorCommandId = 'edit.undo' | 'edit.redo' | 'edit.selectAll' | 'edit.cut' | 'edit.copy' | 'edit.paste' | 'edit.pasteWithoutFormatting' | 'edit.delete' | 'edit.findReplace' | 'insert.image' | 'insert.table' | 'insert.link' | 'insert.comment' | 'insert.callout' | 'insert.quote' | 'insert.code' | 'insert.codeBlock' | 'insert.video' | 'insert.mermaid' | 'insert.plainText' | 'insert.tweet' | 'insert.soundcloud' | 'insert.divider' | 'insert.pageBreak' | 'insert.columns2' | 'insert.columns3' | 'format.bold' | 'format.italic' | 'format.underline' | 'format.strike' | 'format.superscript' | 'format.subscript' | 'format.heading' | 'format.align' | 'format.direction' | 'format.lineHeight' | 'format.fontFamily' | 'format.fontSize.increase' | 'format.fontSize.decrease' | 'format.list.bullet' | 'format.list.numbered' | 'format.list.check' | 'format.clearFormatting' | 'table.addRowAbove' | 'table.addRowBelow' | 'table.mergeCells' | 'table.deleteRow' | 'table.addColumnLeft' | 'table.addColumnRight' | 'table.deleteColumn' | 'table.toggleHeaderRow' | 'table.toggleHeaderColumn' | 'table.toggleHeaderCell' | 'table.deleteTable';
10
+ export type EditorCommandId = 'edit.undo' | 'edit.redo' | 'edit.selectAll' | 'edit.cut' | 'edit.copy' | 'edit.paste' | 'edit.pasteWithoutFormatting' | 'edit.delete' | 'edit.findReplace' | 'insert.image' | 'insert.table' | 'insert.link' | 'insert.comment' | 'insert.callout' | 'insert.quote' | 'insert.code' | 'insert.codeBlock' | 'insert.video' | 'insert.mermaid' | 'insert.plainText' | 'insert.tweet' | 'insert.soundcloud' | 'insert.divider' | 'insert.pageBreak' | 'insert.columns2' | 'insert.columns3' | 'format.bold' | 'format.italic' | 'format.underline' | 'format.strike' | 'format.superscript' | 'format.subscript' | 'format.heading' | 'format.align' | 'format.direction' | 'format.lineHeight' | 'format.customSpacing' | 'format.spaceBefore' | 'format.spaceAfter' | 'format.fontFamily' | 'format.fontSize.increase' | 'format.fontSize.decrease' | 'format.list.bullet' | 'format.list.numbered' | 'format.list.check' | 'format.clearFormatting' | 'table.addRowAbove' | 'table.addRowBelow' | 'table.mergeCells' | 'table.deleteRow' | 'table.addColumnLeft' | 'table.addColumnRight' | 'table.deleteColumn' | 'table.toggleHeaderRow' | 'table.toggleHeaderColumn' | 'table.toggleHeaderCell' | 'table.deleteTable';
11
11
  export type UseEditorCommandsOptions = UploadImageOptions;
12
12
  /**
13
13
  * Reactive, editor-derived command registry (architecture doc §2 bucket 1).
@@ -0,0 +1,14 @@
1
+ type Store = {
2
+ isCustomSpacingOpen: boolean;
3
+ setCustomSpacingOpen: (val: boolean) => void;
4
+ };
5
+ /**
6
+ * Open/closed state for the one CustomSpacingDialog, which ddoc-editor mounts.
7
+ * Module-level like search-replace-store: the entry points are scattered (the
8
+ * toolbar dropdown, the bubble menu, and a host app's own menu rendered
9
+ * outside the editor tree), so they share a flag rather than each owning a
10
+ * dialog instance.
11
+ */
12
+ export declare const useCustomSpacingStore: import('zustand').UseBoundStore<import('zustand').StoreApi<Store>>;
13
+ export declare const openCustomSpacingDialog: () => void;
14
+ export {};
@@ -10,6 +10,14 @@ export declare const getFontSizeOptions: (editor?: Editor) => {
10
10
  }[];
11
11
  export declare const getCurrentFontSize: (editor: Editor | null, currentSize: string) => string;
12
12
  export declare const uiValueToPercentage: (uiValue: string) => string;
13
+ /**
14
+ * CSS line-height comes in three shapes and ddoc stores percentages, so the
15
+ * attribute needs one meaning. A unitless ratio is exactly percentage / 100,
16
+ * so it normalises losslessly — Google Docs pastes `line-height:1.38`, which
17
+ * is `138%`. Absolute units cannot become a ratio without knowing the font
18
+ * size, so they are passed through untouched rather than guessed at.
19
+ */
20
+ export declare const normalizeLineHeight: (value: string | null | undefined) => string | null;
13
21
  export declare const percentageToUiValue: (percentage: string) => string;
14
22
  export declare const LINE_HEIGHT_OPTIONS: {
15
23
  value: string;
@@ -23,4 +31,52 @@ export declare const getLineHeightOptions: () => {
23
31
  uiValue: string;
24
32
  description: string;
25
33
  }[];
34
+ export declare const SPACING_MIN_PT = 0;
35
+ export declare const SPACING_MAX_PT = 100;
36
+ /**
37
+ * What "Add space before/after paragraph" writes, matching Google Docs.
38
+ *
39
+ * A real value rather than null: null would hand the block back to the
40
+ * stylesheet, and the toggle only offers "Add" when the stylesheet is already
41
+ * giving it nothing — so restoring null would leave the gap at zero and the
42
+ * menu item would appear to do nothing.
43
+ */
44
+ export declare const SPACING_ADD_PT = 12;
45
+ /** A value shared by every block in the selection, or `'mixed'`. */
46
+ export type SpacingReading<T> = T | 'mixed';
47
+ export type SpacingSelection = {
48
+ spaceBefore: SpacingReading<number | null>;
49
+ spaceAfter: SpacingReading<number | null>;
50
+ lineHeight: SpacingReading<string | null>;
51
+ };
52
+ /**
53
+ * Read spacing across the current selection, the single place the dialog and
54
+ * any read-back should use. `'mixed'` means the selected blocks disagree — the
55
+ * caller must render that as an empty field and leave the attribute alone on
56
+ * apply, rather than stamping one block's value onto the rest.
57
+ */
58
+ export declare const readSpacingSelection: (editor: Editor | null) => SpacingSelection;
26
59
  export declare const getCurrentLineHeight: (editor: Editor | null, currentLineHeight?: string) => string;
60
+ export type EffectiveSpacing = {
61
+ spaceBefore: SpacingReading<number>;
62
+ spaceAfter: SpacingReading<number>;
63
+ };
64
+ /**
65
+ * The spacing a block actually renders with: its explicit attribute when set,
66
+ * otherwise whatever the stylesheet resolves to.
67
+ *
68
+ * Read from the rendered DOM because there is no single default to hardcode —
69
+ * the gap depends on viewport, schema version, element type, and whether the
70
+ * block is the first or last child. Both the "add/remove space" menu items and
71
+ * the custom spacing dialog need the real number, not the attribute.
72
+ */
73
+ export declare const readEffectiveSpacing: (editor: Editor | null) => EffectiveSpacing;
74
+ /**
75
+ * Which half of the Google-Docs-style toggle to offer.
76
+ *
77
+ * "Add space before paragraph" only appears once the block genuinely has no
78
+ * gap — the stylesheet's default counts, so a fresh paragraph offers "Remove"
79
+ * first. A mixed selection counts as having a gap, since removing is the
80
+ * action that leaves every block in the same state.
81
+ */
82
+ export declare const spacingToggleAction: (effective: SpacingReading<number>) => "add" | "remove";
@@ -1,7 +1,7 @@
1
1
  import { jsx as m, jsxs as L } from "react/jsx-runtime";
2
2
  import { useRef as D, useState as E, useEffect as A } from "react";
3
3
  import { DynamicDropdown as P, Tooltip as O, IconButton as T } from "@fileverse/ui";
4
- import { a3 as _, a4 as w, c as R } from "./index-BYGWNqrf.mjs";
4
+ import { a3 as _, a4 as w, c as R } from "./index-DqOL-hci.mjs";
5
5
  const p = (e, n, o = n) => {
6
6
  const { state: i } = e, l = i.changeByRange((t) => {
7
7
  const d = i.sliceDoc(t.from, t.to), r = i.sliceDoc(