@stll/folio-vue 0.8.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/ListButtons-BcB7qvzQ.cjs +4 -0
  2. package/dist/{ListButtons-DXqMvba3.js → ListButtons-rpVlLZJ8.js} +689 -710
  3. package/dist/SplitCellDialog-B_TOoiMw.cjs +15 -0
  4. package/dist/{WatermarkDialog-r4wmldt4.js → SplitCellDialog-DRQuZsA3.js} +1537 -1604
  5. package/dist/components/AutocompleteCaretOverlay.types.d.ts +18 -0
  6. package/dist/components/DocxEditor/pagedEditorRef.d.ts +16 -3
  7. package/dist/components/DocxEditor/types.d.ts +27 -0
  8. package/dist/composables/index.d.ts +2 -2
  9. package/dist/composables/useColorMode.d.ts +17 -4
  10. package/dist/composables/useContextMenus.d.ts +3 -0
  11. package/dist/composables/useDocxEditor.d.ts +47 -0
  12. package/dist/composables/useDocxEditorRefApi.d.ts +14 -0
  13. package/dist/composables/useFindReplace.d.ts +24 -22
  14. package/dist/composables/useFontLifecycle.d.ts +21 -0
  15. package/dist/composables/useKeyboardShortcuts.d.ts +0 -1
  16. package/dist/composables/usePagesPointer.d.ts +14 -13
  17. package/dist/composables/useRemoteSelectionSync.d.ts +10 -0
  18. package/dist/composables/useSelectionSync.d.ts +17 -30
  19. package/dist/composables.cjs +2 -2
  20. package/dist/composables.js +93 -81
  21. package/dist/dialogs.cjs +1 -1
  22. package/dist/dialogs.js +2 -2
  23. package/dist/folio-vue.css +1 -1
  24. package/dist/index.cjs +1 -1
  25. package/dist/index.d.ts +4 -1
  26. package/dist/index.js +2249 -1401
  27. package/dist/renderAsync.d.ts +4 -0
  28. package/dist/styles/zIndex.d.ts +1 -0
  29. package/dist/styles.cjs +1 -1
  30. package/dist/styles.js +1 -1
  31. package/dist/ui/folio-ui.d.ts +1 -1
  32. package/dist/ui.cjs +1 -1
  33. package/dist/ui.js +10 -10
  34. package/dist/useFindReplace-CL8Rbc3y.js +59 -0
  35. package/dist/useFindReplace-ZCrdvwEk.cjs +1 -0
  36. package/dist/useZoom-DBbzwfMG.cjs +1 -0
  37. package/dist/useZoom-DwDDS7hq.js +749 -0
  38. package/dist/utils/colorMode.d.ts +3 -4
  39. package/dist/utils/embeddedFonts.d.ts +7 -0
  40. package/dist/utils/fontFaces.d.ts +10 -0
  41. package/dist/utils/hostFonts.d.ts +1 -5
  42. package/dist/zIndex-CYoLNG_N.cjs +1 -0
  43. package/dist/{zIndex-BY0qa8Au.js → zIndex-Ei9BbHSW.js} +1 -0
  44. package/package.json +1 -1
  45. package/dist/ListButtons-BvsV1yti.cjs +0 -4
  46. package/dist/WatermarkDialog-DHfk8jrg.cjs +0 -15
  47. package/dist/components/sidebar/resolveItemPositions.d.ts +0 -22
  48. package/dist/composables/useHostCallbacks.d.ts +0 -24
  49. package/dist/composables/useMenuActions.d.ts +0 -36
  50. package/dist/useZoom-C7jhL696.cjs +0 -1
  51. package/dist/useZoom-zJvuJlUd.js +0 -615
  52. package/dist/zIndex-dFsQbASx.cjs +0 -1
@@ -0,0 +1,18 @@
1
+ export type AutocompleteCaretRect = {
2
+ /** Overlay-relative pixel x. */
3
+ x: number;
4
+ /** Overlay-relative pixel y (top of the cursor line). */
5
+ y: number;
6
+ /** Line height in pixels at the anchor. */
7
+ lineHeight: number;
8
+ /** Available width from the caret to the page's right content edge. */
9
+ maxWidth?: number | undefined;
10
+ };
11
+ export type AutocompleteCaretOverlayProps = {
12
+ /** Position of the autocomplete anchor, or null while idle. */
13
+ caret: AutocompleteCaretRect | null;
14
+ /** The full streamed ghost text so far. */
15
+ text: string;
16
+ /** Whether tokens are still arriving. */
17
+ isStreaming: boolean;
18
+ };
@@ -13,9 +13,8 @@ import { Document } from '@stll/folio-core/types/document';
13
13
  * `useDocxEditorRefApi.ts` synthesizes one from the primitives it already
14
14
  * holds (the headless `FolioEditor` controller, `editorView`, `layout`, and
15
15
  * the pages-scroll helpers) rather than tearing a component ref off a
16
- * component that does not exist. `getHfView` is the one method with no
17
- * backing implementation yet (no persistent hidden header/footer PM view in
18
- * Vue) and stays a documented no-op; see its call site for the exact reason.
16
+ * component that does not exist. `getHfView` delegates to the shared
17
+ * persistent header/footer editor manager.
19
18
  *
20
19
  * TODO(vue): re-home to the Vue PagedEditor component when it lands.
21
20
  */
@@ -28,6 +27,10 @@ export type PagedEditorRef = {
28
27
  getState: () => EditorState | null;
29
28
  /** Get the ProseMirror EditorView. */
30
29
  getView: () => EditorView | null;
30
+ /** Get the currently active body, header/footer, or note-story view. */
31
+ getActiveView: () => EditorView | null;
32
+ /** Close the visible note story, if one is active. */
33
+ closeNoteStory: () => void;
31
34
  /**
32
35
  * Look up the persistent hidden HF EditorView by `rId`. Returns null when the
33
36
  * slot isn't mounted (no HF for that rId, or the hidden host hasn't mounted).
@@ -71,6 +74,16 @@ export type PagedEditorRef = {
71
74
  * Returns whether a matching paragraph exists in the ProseMirror document.
72
75
  */
73
76
  scrollToParaId: (paraId: string, options?: ScrollToParaIdOptions) => boolean;
77
+ /**
78
+ * Set (or clear, with `null`) the persistent passage highlight overlay. The
79
+ * range is projected onto the painted pages and painted with a translucent
80
+ * wash; it does not move the PM selection. Replaces any previous highlight.
81
+ * The overlay is cleared automatically on the next doc-changing transaction.
82
+ */
83
+ setPassageHighlight: (range: {
84
+ from: number;
85
+ to: number;
86
+ } | null) => void;
74
87
  /**
75
88
  * Resolve the page number (1-indexed) that contains the given PM position, or
76
89
  * null if no layout is available yet. Works for unrendered pages too via the
@@ -307,6 +307,21 @@ export type DocxEditorApplyDocumentOperationsOptions = {
307
307
  batch: FolioDocumentOperationBatch;
308
308
  author?: string;
309
309
  };
310
+ /**
311
+ * Outcome of {@link DocxEditorRef.highlightPassage}:
312
+ * - `"passage"`: the text matched inside the block; scrolled there and painted
313
+ * the range highlight.
314
+ * - `"block"`: the text did not match but the block resolved; behaved like
315
+ * {@link DocxEditorRef.scrollToBlock} (scroll + whole-paragraph flash where a
316
+ * paraId exists).
317
+ * - `"none"`: the block did not resolve; no-op.
318
+ */
319
+ export type HighlightPassageResult = "passage" | "block" | "none";
320
+ export type HighlightPassageOptions = {
321
+ blockId: string;
322
+ text: string;
323
+ snapshot?: FolioAIEditSnapshot;
324
+ };
310
325
  /**
311
326
  * Imperative handle exposed by the DocxEditor component.
312
327
  */
@@ -411,6 +426,18 @@ export type DocxEditorRef = {
411
426
  * accept. Without `snapshot`, falls back to a fresh-from-live-doc snapshot.
412
427
  */
413
428
  scrollToBlock: (blockId: string, snapshot?: FolioAIEditSnapshot) => boolean;
429
+ /**
430
+ * Resolve a text passage inside a block, scroll to it, and paint a persistent
431
+ * translucent highlight over the matched range. Unlike {@link scrollToBlock},
432
+ * the passage outcome does not move the PM selection, so the highlight is not
433
+ * confused with a selection. Replaces any previous passage highlight. Returns
434
+ * which outcome happened; see {@link HighlightPassageResult}. The highlight is
435
+ * ephemeral view state: cleared on the next doc-changing transaction and by
436
+ * {@link clearPassageHighlight}.
437
+ */
438
+ highlightPassage: (options: HighlightPassageOptions) => HighlightPassageResult;
439
+ /** Clear the passage highlight painted by {@link highlightPassage}, if any. */
440
+ clearPassageHighlight: () => void;
414
441
  /** Resolve a stable block or text-range target and reveal it in the editor. */
415
442
  showInDocument: (target: FolioDocumentNavigationTarget, snapshot?: FolioAIEditSnapshot) => boolean;
416
443
  /**
@@ -4,8 +4,7 @@
4
4
  * Vue composables mirroring the React `hooks` subpath — history, table
5
5
  * selection, find/replace, clipboard, zoom, tracked-changes, visual-line
6
6
  * navigation, and the high-level `useDocxEditor` host composable. Only the
7
- * composables the fork has ported are re-exported (React's `useAutoSave` and
8
- * `useCommentSidebarItems` have no Vue equivalent yet).
7
+ * composables the fork has ported are re-exported.
9
8
  *
10
9
  * @example
11
10
  * ```ts
@@ -16,6 +15,7 @@
16
15
  * @public
17
16
  */
18
17
  export * from './useClipboard';
18
+ export * from './useColorMode';
19
19
  export * from './useDocxEditor';
20
20
  export * from './useDragAutoScroll';
21
21
  export * from './useFindReplace';
@@ -1,8 +1,21 @@
1
- import { ComputedRef } from 'vue';
1
+ import { App, ComputedRef, MaybeRefOrGetter } from 'vue';
2
2
  import { ColorMode } from '../utils/colorMode';
3
+ /** Color mode used when a host does not provide one. */
4
+ export declare const defaultColorMode: ColorMode;
3
5
  /**
4
- * Resolve the effective dark flag from a reactive `colorMode`. `'system'`
6
+ * Provide a reactive color mode to descendant folio components.
7
+ *
8
+ * Call this from a parent component's setup function. For app-wide setup, use
9
+ * {@link colorModePlugin} instead.
10
+ */
11
+ export declare const provideColorMode: (colorMode?: MaybeRefOrGetter<ColorMode>) => void;
12
+ /** Vue plugin form: `app.use(colorModePlugin, "system")`. */
13
+ export declare const colorModePlugin: {
14
+ install(app: App, colorMode?: MaybeRefOrGetter<ColorMode>): void;
15
+ };
16
+ /**
17
+ * Resolve the effective dark flag from the inherited color mode. `'system'`
5
18
  * follows the OS via `subscribeSystemDark` (SSR-safe; re-syncs on entry).
6
- * Mirrors the React adapter's inline colorMode logic via the shared core helpers.
7
19
  */
8
- export declare function useColorMode(colorMode: () => ColorMode): ComputedRef<boolean>;
20
+ export declare function useColorMode(): ComputedRef<boolean>;
21
+ export type { ColorMode } from '../utils/colorMode';
@@ -48,6 +48,9 @@ export type UseContextMenusOptions = {
48
48
  from: number;
49
49
  to: number;
50
50
  }) => void;
51
+ onCopy?: () => void;
52
+ onCut?: () => void;
53
+ onPaste?: () => void;
51
54
  };
52
55
  export type UseContextMenusReturn = {
53
56
  contextMenu: Ref<TextContextMenuState>;
@@ -2,9 +2,13 @@ import { MaybeRefOrGetter, Ref } from 'vue';
2
2
  import { EditorState, Plugin } from 'prosemirror-state';
3
3
  import { EditorView } from 'prosemirror-view';
4
4
  import { FolioEditor } from '@stll/folio-core/controller/folioEditor';
5
+ import { HeaderFooterPartKind } from '@stll/folio-core/controller/headerFooterEditorManager';
6
+ import { NoteStoryKey } from '@stll/folio-core/controller/noteEditorManager';
7
+ import { HiddenProseMirrorCollaboration, HiddenProseMirrorRemoteSelection } from '@stll/folio-core/controller/hiddenEditorManager';
5
8
  import { FolioSelectiveSaveFlags } from '@stll/folio-core/docx/selectiveSaveFlags';
6
9
  import { TripwireResult } from '@stll/folio-core/docx/selectiveSaveTripwire';
7
10
  import { FlowBlock, Layout, Measure } from '@stll/folio-core/layout-engine/types';
11
+ import { LayoutSelectionGate } from '@stll/folio-core/paged-layout/LayoutSelectionGate';
8
12
  import { CommandMap } from '@stll/folio-core/prosemirror/extensions/types';
9
13
  import { AnonymizationMatch } from '@stll/folio-core/prosemirror/plugins/anonymizationDecorations';
10
14
  import { TemplateSlashMenuKeyAction, TemplateSlashMenuState } from '@stll/folio-core/prosemirror/plugins/templateSlashMenu';
@@ -13,12 +17,20 @@ import { DocxInput } from '@stll/folio-core/utils/docxInput';
13
17
  export type UseDocxEditorOptions = {
14
18
  /** Container element that hosts the off-screen ProseMirror editor. */
15
19
  hiddenContainer: Ref<HTMLElement | null>;
20
+ /** Optional separate host for persistent header/footer ProseMirror views. */
21
+ hiddenHeaderFooterContainer?: Ref<HTMLElement | null>;
22
+ /** Visible host for the active footnote or endnote ProseMirror story. */
23
+ noteEditorContainer?: Ref<HTMLElement | null>;
16
24
  /** Container element the paginated pages are painted into. */
17
25
  pagesContainer: Ref<HTMLElement | null>;
18
26
  /** Whether the editor is read-only. Reactive. */
19
27
  readOnly?: MaybeRefOrGetter<boolean>;
20
28
  /** Gap between pages in pixels. */
21
29
  pageGap?: number;
30
+ /** Whether to paint each page's effective body-content boundary. Reactive. */
31
+ showMarginGuides?: MaybeRefOrGetter<boolean | undefined>;
32
+ /** CSS color used for margin guides. Reactive. */
33
+ marginGuideColor?: MaybeRefOrGetter<string | undefined>;
22
34
  /**
23
35
  * Stable identity of the loaded document (same across internal edits, distinct
24
36
  * per loaded file). Threaded to the hidden-editor manager's external-load
@@ -36,6 +48,8 @@ export type UseDocxEditorOptions = {
36
48
  author?: MaybeRefOrGetter<string>;
37
49
  /** External ProseMirror plugins supplied by the host app. */
38
50
  externalPlugins?: Plugin[];
51
+ /** Reactive Yjs collaboration owner and the ProseMirror binding plugins. */
52
+ collaboration?: MaybeRefOrGetter<UseDocxEditorCollaboration | undefined>;
39
53
  /**
40
54
  * Fires with the anonymization decoration plugin's current match list on
41
55
  * mount, term push, and every doc edit. The anonymization plugin is always
@@ -62,6 +76,12 @@ export type UseDocxEditorOptions = {
62
76
  onSelectionUpdate?: (state: EditorState) => void;
63
77
  /** Callback when the hidden EditorView is created or torn down. */
64
78
  onEditorViewReady?: (view: EditorView | null) => void;
79
+ /** Fires when the editor receives a copy event. */
80
+ onCopy?: () => void;
81
+ /** Fires when an editable editor receives a cut event. */
82
+ onCut?: () => void;
83
+ /** Fires when an editable editor receives a paste event. */
84
+ onPaste?: () => void;
65
85
  /** Callback when a read-only user action would mutate the document. */
66
86
  onReadOnlyEditAttempt?: () => void;
67
87
  /**
@@ -77,6 +97,15 @@ export type UseDocxEditorOptions = {
77
97
  */
78
98
  onSelectiveSaveTripwire?: ((result: TripwireResult) => void) | undefined;
79
99
  };
100
+ export type UseDocxEditorCollaboration = HiddenProseMirrorCollaboration & {
101
+ plugins?: Plugin[] | undefined;
102
+ };
103
+ export type HeaderFooterSelectionState = {
104
+ from: number;
105
+ kind: HeaderFooterPartKind;
106
+ rId: string;
107
+ to: number;
108
+ };
80
109
  export type UseDocxEditorReturn = {
81
110
  /** The headless controller (imperative API + layout access + events). */
82
111
  editor: FolioEditor;
@@ -84,6 +113,12 @@ export type UseDocxEditorReturn = {
84
113
  editorView: Ref<EditorView | null>;
85
114
  /** Latest editor state, updated on each transaction. */
86
115
  editorState: Ref<EditorState | null>;
116
+ /** Remote collaborative cursors decoded into body ProseMirror positions. */
117
+ remoteSelections: Ref<HiddenProseMirrorRemoteSelection[]>;
118
+ /** Selection in the currently active persistent header/footer view. */
119
+ headerFooterSelection: Ref<HeaderFooterSelectionState | null>;
120
+ /** The note story currently open in the visible note editor. */
121
+ activeNoteStory: Ref<NoteStoryKey | null>;
87
122
  /** True once the hidden view is mounted and a document is loaded. */
88
123
  isReady: Ref<boolean>;
89
124
  /**
@@ -101,6 +136,8 @@ export type UseDocxEditorReturn = {
101
136
  blocks: Ref<FlowBlock[]>;
102
137
  /** Measures from the latest layout pass — the range-projection fallback. */
103
138
  measures: Ref<Measure[]>;
139
+ /** Gate that schedules overlay work only after the matching layout paint. */
140
+ syncCoordinator: LayoutSelectionGate;
104
141
  /** Load a DOCX from a binary buffer / Blob / File. */
105
142
  loadBuffer: (buffer: DocxInput) => Promise<void>;
106
143
  /** Load an already-parsed `Document` directly. */
@@ -113,6 +150,16 @@ export type UseDocxEditorReturn = {
113
150
  getDocument: () => Document | null;
114
151
  /** Publish a fresh Document object (e.g. after HF materialisation). */
115
152
  setDocument: (doc: Document) => void;
153
+ /** Resolve a persistent header/footer EditorView by relationship id. */
154
+ getHeaderFooterView: (rId: string) => EditorView | null;
155
+ /** Synchronize persistent header/footer views after a document-model change. */
156
+ syncHeaderFooterViews: () => void;
157
+ /** Open an existing footnote or endnote story. */
158
+ openNoteStory: (story: NoteStoryKey) => void;
159
+ /** Close the visible note-story editor. */
160
+ closeNoteStory: () => void;
161
+ /** Resolve the active note-story view. */
162
+ getActiveNoteView: () => EditorView | null;
116
163
  /** Access the extension command map for invoking marks / nodes / features. */
117
164
  getCommands: () => CommandMap;
118
165
  /** Focus the hidden ProseMirror view. */
@@ -42,6 +42,17 @@ export type UseDocxEditorRefApiOptions = {
42
42
  * Vue analogue of React's `PagedEditorRef.scrollToPosition`.
43
43
  */
44
44
  scrollVisiblePositionIntoView: (pmPos: number) => void;
45
+ /**
46
+ * Set (or clear, with `null`) the persistent passage-highlight range that the
47
+ * `PassageHighlightOverlay` projects and paints. Backs `highlightPassage` /
48
+ * `clearPassageHighlight`; the Vue analogue of React's
49
+ * `PagedEditorRef.setPassageHighlight`. The overlay is cleared automatically
50
+ * on the next doc-changing transaction (owned by DocxEditor.vue).
51
+ */
52
+ setPassageHighlight: (range: {
53
+ from: number;
54
+ to: number;
55
+ } | null) => void;
45
56
  /** Editor author, used as the default operation author for AI edits. */
46
57
  author: () => string;
47
58
  /**
@@ -55,6 +66,9 @@ export type UseDocxEditorRefApiOptions = {
55
66
  setComments: (comments: Comment[]) => void;
56
67
  focus: () => void;
57
68
  getDocument: () => Document | null;
69
+ getActiveView: () => EditorView | null;
70
+ closeNoteStory: () => void;
71
+ getHeaderFooterView: (rId: string) => EditorView | null;
58
72
  setZoom: (zoom: number) => void;
59
73
  /** useDocxEditor.save returns a Blob; the ref surface exposes an ArrayBuffer. */
60
74
  save: (options?: {
@@ -1,22 +1,24 @@
1
- /**
2
- * Vue port of the find/replace UI-state container.
3
- *
4
- * PORT-BLOCKED (missing `utils/findReplace` UI-util): upstream builds this
5
- * composable's entire state on three symbols from
6
- * `@eigenpal/docx-editor-core/utils/findReplace` — the `FindMatch` and
7
- * `FindOptions` data contracts and the `createDefaultFindOptions()` factory.
8
- * That util is absent from our fork: it is neither in `@stll/folio-core`
9
- * (whose search surface is the lower-level `prosemirror/findReplaceSelection`
10
- * `FindMatchPosition` + `managers/FindReplaceManager`, a different shape) nor
11
- * in our ported Vue `../utils/*`. Every field of the reactive state
12
- * (`options: createDefaultFindOptions()`, `matches: FindMatch[]`, the
13
- * `currentMatch`/`setMatches`/`goToMatch` surface) depends on those types, so
14
- * there is no working subset to port without fabricating the data contract.
15
- *
16
- * Unblock: port upstream `packages/core/src/utils/findReplace.ts` (pure, no
17
- * runtime deps) into the Vue package as `../utils/findReplace.ts`, reconciling
18
- * its `FindMatch`/`FindOptions` with core's `FindMatchPosition` /
19
- * `FindReplaceManager`, then restore the full composable — its body is a direct
20
- * `reactive()` translation of the React hook with no other blockers.
21
- */
22
- export {};
1
+ import { ComputedRef, Ref, ShallowRef } from 'vue';
2
+ import { EditorView } from 'prosemirror-view';
3
+ import { ProseMirrorFindMatch } from '@stll/folio-core/prosemirror/findReplaceSelection';
4
+ import { FindOptions } from '@stll/folio-core/utils/findReplace';
5
+ export type UseFindReplaceOptions = {
6
+ editorView: Readonly<Ref<EditorView | null>>;
7
+ scrollVisiblePositionIntoView?: (pmPos: number) => void;
8
+ };
9
+ export type UseFindReplaceReturn = {
10
+ searchText: Ref<string>;
11
+ replaceText: Ref<string>;
12
+ options: FindOptions;
13
+ matches: ShallowRef<ProseMirrorFindMatch[]>;
14
+ currentIndex: Ref<number>;
15
+ currentMatch: ComputedRef<ProseMirrorFindMatch | null>;
16
+ performSearch: () => ProseMirrorFindMatch[];
17
+ goToMatch: (index: number) => boolean;
18
+ findNext: () => ProseMirrorFindMatch | null;
19
+ findPrevious: () => ProseMirrorFindMatch | null;
20
+ replaceCurrent: () => boolean;
21
+ replaceAll: () => number;
22
+ clear: () => void;
23
+ };
24
+ export declare function useFindReplace({ editorView, scrollVisiblePositionIntoView, }: UseFindReplaceOptions): UseFindReplaceReturn;
@@ -0,0 +1,21 @@
1
+ import { Ref } from 'vue';
2
+ import { FontDefinition } from '../components/DocxEditor/types';
3
+ export type UseFontLifecycleOptions = {
4
+ isReady: Ref<boolean>;
5
+ getDocument: () => {
6
+ originalBuffer?: ArrayBuffer | null;
7
+ } | null;
8
+ fonts: () => ReadonlyArray<FontDefinition> | undefined;
9
+ remeasure: () => void;
10
+ };
11
+ export type FontLifecycleDependencies = {
12
+ loadEmbedded: (buffer: ArrayBuffer) => Promise<FontFace[]>;
13
+ loadHost: (fonts: ReadonlyArray<FontDefinition> | undefined) => Promise<FontFace[]>;
14
+ remove: (faces: readonly FontFace[]) => void;
15
+ };
16
+ /**
17
+ * Register document-embedded and host-provided fonts for the lifetime of their
18
+ * sources. Async results from a stale document or prop value are immediately
19
+ * removed, preventing one editor load from leaking faces into the next.
20
+ */
21
+ export declare function useFontLifecycle(options: UseFontLifecycleOptions, dependencies?: FontLifecycleDependencies): void;
@@ -1,6 +1,5 @@
1
1
  import { Ref } from 'vue';
2
2
  export type UseKeyboardShortcutsOptions = {
3
- showKeyboardShortcuts: Ref<boolean>;
4
3
  showFindReplace: Ref<boolean>;
5
4
  showHyperlink: Ref<boolean>;
6
5
  /** From useZoom — handles Ctrl+= / Ctrl+- / Ctrl+0. */
@@ -1,8 +1,8 @@
1
1
  import { Ref, ShallowRef } from 'vue';
2
2
  import { Command } from 'prosemirror-state';
3
3
  import { EditorView } from 'prosemirror-view';
4
- import { HeaderFooter, BlockContent } from '@stll/folio-core/types/content';
5
4
  import { Document } from '@stll/folio-core/types/document';
5
+ import { NoteStoryKey } from '@stll/folio-core/controller/noteEditorManager';
6
6
  import { Layout } from '@stll/folio-core/layout-engine';
7
7
  import { ImageSelectionInfo } from '../components/imageSelectionTypes';
8
8
  import { HyperlinkPopupData } from '../components/ui/hyperlinkPopupTypes';
@@ -19,9 +19,10 @@ export type TableInsertButton = {
19
19
  cellPmPos: number;
20
20
  };
21
21
  export type HfEditState = {
22
+ isFirstPage: boolean;
23
+ pageNumber: number;
22
24
  position: "header" | "footer";
23
25
  rId: string | null;
24
- headerFooter: HeaderFooter | null;
25
26
  targetRect: {
26
27
  top: number;
27
28
  left: number;
@@ -42,29 +43,29 @@ export type UsePagesPointerOptions = {
42
43
  imageInteracting: Ref<boolean>;
43
44
  hyperlinkPopupData: Ref<HyperlinkPopupData | null>;
44
45
  readOnly: Ref<boolean>;
46
+ showHeaderFooterEditing: Ref<boolean>;
45
47
  zoom: Ref<number>;
46
48
  layout: Ref<Layout | null>;
47
49
  tableResize: TableResizeApi;
48
50
  getCommands: () => Commands;
49
51
  getDocument: () => Document | null;
50
52
  reLayout: () => void;
51
- emit: (event: string, ...args: unknown[]) => void;
53
+ onDocumentChange: (document: Document) => void;
52
54
  clearOverlay: () => void;
53
- /**
54
- * Re-mount HF EditorViews when `package.headers/footers` content changes —
55
- * exposed by `useDocxEditor.syncHfPMs`. Called after every save so the
56
- * persistent PM points at the new HeaderFooter object. Optional so existing
57
- * consumers can no-op until they wire it through.
58
- */
59
- syncHfPMs?: () => void;
55
+ /** Synchronize persistent header/footer views after document-model changes. */
56
+ syncHfPMs: () => void;
60
57
  /** Resolve the persistent EditorView for an HF instance (for click routing). */
61
- getHfPmView?: (hf: HeaderFooter) => EditorView | null;
58
+ getHfPmView: (rId: string) => EditorView | null;
62
59
  /**
63
60
  * Replace the loaded Document — used by HF materialisation to publish a
64
61
  * fresh Document object instead of mutating in place. Optional; if absent,
65
62
  * callers fall back to in-place mutation + `syncHfPMs()`.
66
63
  */
67
- setDocument?: (doc: Document) => void;
64
+ setDocument: (doc: Document) => void;
65
+ /** Open a footnote or endnote story from a painted reference/body. */
66
+ openNoteStory: (story: NoteStoryKey) => void;
67
+ closeNoteStory: () => void;
68
+ getActiveNoteView: () => EditorView | null;
68
69
  };
69
70
  export type UsePagesPointerReturn = {
70
71
  tableInsertButton: Ref<TableInsertButton | null>;
@@ -80,7 +81,7 @@ export type UsePagesPointerReturn = {
80
81
  handlePagesDoubleClick: (event: MouseEvent) => void;
81
82
  handleTableInsertClick: (event: MouseEvent) => void;
82
83
  clearTableInsertTimer: () => void;
83
- handleHfSave: (content: BlockContent[]) => void;
84
+ handleHfSave: () => void;
84
85
  handleHfRemove: () => void;
85
86
  };
86
87
  export declare function usePagesPointer(opts: UsePagesPointerOptions): UsePagesPointerReturn;
@@ -0,0 +1,10 @@
1
+ import { Ref } from 'vue';
2
+ import { HiddenProseMirrorRemoteSelection } from '@stll/folio-core/controller/hiddenEditorManager';
3
+ import { LayoutSelectionGate } from '@stll/folio-core/paged-layout/LayoutSelectionGate';
4
+ export type UseRemoteSelectionSyncOptions = {
5
+ pagesRef: Ref<HTMLElement | null>;
6
+ remoteSelections: Ref<HiddenProseMirrorRemoteSelection[]>;
7
+ syncCoordinator: LayoutSelectionGate;
8
+ zoom: Ref<number>;
9
+ };
10
+ export declare const useRemoteSelectionSync: (options: UseRemoteSelectionSyncOptions) => void;
@@ -1,30 +1,17 @@
1
- /**
2
- * Selection-overlay composable owns the text-caret blink + selection-rect
3
- * painter, the cell-selection highlight, and the image-selection sync that
4
- * re-derives `selectedImage` from the live PM NodeSelection.
5
- *
6
- * PORT-BLOCKED (multiple absent dependencies):
7
- * - `applyCellSelectionHighlight` — absent from our core. Upstream ships it in
8
- * `layout-bridge/cellSelectionHighlight.ts`; our `layout-bridge` barrel does
9
- * not expose it (see CORE-API-MAP Table 4, PORT). The multi-cell highlight
10
- * branch cannot run without it.
11
- * - `findImageElement` — absent from our core `layout-painter` barrel (which
12
- * exposes only `renderPages`/`LayoutPainter`/registry); it is a PORT item.
13
- * The image-overlay sync (`syncSelectedImageToSelection`) depends on it.
14
- * - `../components/imageSelectionTypes` (`ImageSelectionInfo`) the Vue-package
15
- * image-selection type module has not been ported.
16
- * - `../styles/zIndex` (`Z_INDEX`) — the Vue-package z-index token module does
17
- * not exist in our fork (there is no `styles/` dir).
18
- *
19
- * The DOM primitives it also uses DO resolve, but at drifted paths
20
- * (`getSelectionRectsFromDom`/`getCaretPositionFromDom` →
21
- * `@stll/folio-core/layout-bridge/dom/clickToPositionDom`; `findBodyPmAnchor` →
22
- * `@stll/folio-core/layout-bridge/dom/findBodyPmSpans`). With the four blockers
23
- * above there is no coherent working subset, so the whole composable is blocked.
24
- *
25
- * Unblock: PORT `applyCellSelectionHighlight` and `findImageElement` into core
26
- * (or a core barrel), then port the `imageSelectionTypes` + `styles/zIndex`
27
- * Vue-package modules, and re-point the DOM-primitive imports to the drifted
28
- * paths above.
29
- */
30
- export {};
1
+ import { Ref, ShallowRef } from 'vue';
2
+ import { EditorView } from 'prosemirror-view';
3
+ import { LayoutSelectionGate } from '@stll/folio-core/paged-layout/LayoutSelectionGate';
4
+ import { ImageSelectionInfo } from '../components/imageSelectionTypes';
5
+ export type UseSelectionSyncOptions = {
6
+ editorView: Ref<EditorView | null>;
7
+ pagesRef: Ref<HTMLElement | null>;
8
+ zoom: Ref<number>;
9
+ selectedImage: ShallowRef<ImageSelectionInfo | null>;
10
+ syncCoordinator: LayoutSelectionGate;
11
+ imageInteracting?: Ref<boolean>;
12
+ };
13
+ export type UseSelectionSyncReturn = {
14
+ clearOverlay: () => void;
15
+ updateSelectionOverlay: () => void;
16
+ };
17
+ export declare const useSelectionSync: (opts: UseSelectionSyncOptions) => UseSelectionSyncReturn;
@@ -1,4 +1,4 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./useZoom-C7jhL696.cjs");let t=require("vue"),n=require("prosemirror-history"),r=require("@stll/folio-core/utils/clipboard"),i=require("@stll/folio-core/managers/ClipboardManager"),a=require("@stll/folio-core/managers/TableSelectionManager"),o=require("@stll/folio-core/prosemirror/utils/visualLineNavigation"),s=require("@stll/folio-core/prosemirror/utils/extractTrackedChanges");function c(e={}){let{onCopy:n,onCut:i,onPaste:a,cleanWordFormatting:o=!0,editable:s=!0,onError:c}=e,l=(0,t.ref)(!1),u=(0,t.ref)(null),d=c?{onError:c}:{};async function f(e){if(l.value)return!1;l.value=!0;try{let t=await(0,r.copyRuns)(e.runs,d);return t&&n?.(e),t}finally{l.value=!1}}async function p(e){if(l.value||!s)return!1;l.value=!0;try{let t=await(0,r.copyRuns)(e.runs,d);return t&&i?.(e),t}finally{l.value=!1}}async function m(e=!1){if(l.value||!s)return null;l.value=!0;try{if(navigator.clipboard&&navigator.clipboard.read){let t=await navigator.clipboard.read(),n=``,i=``;for(let e of t)e.types.includes(`text/html`)&&(n=await(await e.getType(`text/html`)).text()),e.types.includes(`text/plain`)&&(i=await(await e.getType(`text/plain`)).text());e&&(n=``);let s=(0,r.parseClipboardHtml)(n,i,o);return u.value=s,a?.(s,e),s}return null}catch(e){return c?.(e instanceof Error?e:Error(String(e))),null}finally{l.value=!1}}return{copy:f,cut:p,paste:m,isProcessing:l,lastPastedContent:u}}function l({isOpen:e,onClose:n,align:r=`left`}){let i=(0,t.ref)(null),a=(0,t.ref)(null),o=(0,t.ref)({position:`fixed`,top:`0px`,left:`0px`,zIndex:1e4});function s(e,t){o.value={position:`fixed`,top:e+`px`,left:t+`px`,zIndex:1e4}}function c(e){let t=e.target;t instanceof Node&&i.value&&!i.value.contains(t)&&a.value&&!a.value.contains(t)&&n()}function l(e){e.key===`Escape`&&n()}function u(e){let t=e.target;t instanceof Node&&a.value&&a.value.contains(t)||n()}function d(){document.addEventListener(`mousedown`,c),document.addEventListener(`keydown`,l),window.addEventListener(`scroll`,u,!0)}function f(){document.removeEventListener(`mousedown`,c),document.removeEventListener(`keydown`,l),window.removeEventListener(`scroll`,u,!0)}(0,t.watch)(e,e=>{if(!e){f();return}let t=i.value;if(!t)return;let n=t.getBoundingClientRect();r===`right`?requestAnimationFrame(()=>{let e=a.value;if(e){let t=e.getBoundingClientRect();s(n.bottom+4,n.right-t.width)}else s(n.bottom+4,n.left)}):s(n.bottom+4,n.left),d()}),(0,t.onScopeDispose)(f);function p(e){e.preventDefault(),e.stopPropagation()}return{containerRef:i,dropdownRef:a,dropdownStyle:o,handleMouseDown:p}}function u(e,r){let i=(0,t.computed)(()=>{r.value;let t=e.value;return t?(0,n.undoDepth)(t.state)>0:!1}),a=(0,t.computed)(()=>{r.value;let t=e.value;return t?(0,n.redoDepth)(t.state)>0:!1});function o(){let t=e.value;return t?(0,n.undo)(t.state,t.dispatch):!1}function s(){let t=e.value;return t?(0,n.redo)(t.state,t.dispatch):!1}return{canUndo:i,canRedo:a,undo:o,redo:s}}var d={backgroundColor:`rgba(26, 115, 232, 0.3)`,borderRadius:0,zIndex:0,opacity:1,mixBlendMode:`multiply`};function f(e){let t=window.getSelection();if(!t||t.rangeCount===0||t.isCollapsed)return[];let n=t.getRangeAt(0);if(e&&!e.contains(n.commonAncestorContainer))return[];let r=0,i=0;if(e){let t=e.getBoundingClientRect();r=t.left+e.scrollLeft,i=t.top+e.scrollTop}let a=[];for(let e of n.getClientRects())e.width===0&&e.height===0||a.push({left:e.left-r,top:e.top-i,width:e.width,height:e.height});return a}function p(e,t=2){if(e.length<=1)return e;let n=[...e].sort((e,n)=>Math.abs(e.top-n.top)<t?e.left-n.left:e.top-n.top),r=n[0];if(!r)return e;let i=[],a={...r};for(let e=1;e<n.length;e++){let r=n[e];if(!r)continue;let o=Math.abs(r.top-a.top)<t,s=r.left<=a.left+a.width+t;if(o&&s){let e=Math.max(a.left+a.width,r.left+r.width);a.width=e-a.left,a.height=Math.max(a.height,r.height)}else i.push(a),a={...r}}return i.push(a),i}function m(e){return p(f(e))}function h(){let e=window.getSelection();return e!==null&&!e.isCollapsed&&e.rangeCount>0}function g(e){let t=window.getSelection();return!t||t.rangeCount===0?!1:e.contains(t.getRangeAt(0).commonAncestorContainer)}var _=`docx-selection-styles`,v=null;function y(){v&&=(v.remove(),null),document.getElementById(_)?.remove()}function b(e=d){y();let t=`
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./useFindReplace-ZCrdvwEk.cjs"),t=require("./useZoom-DBbzwfMG.cjs");let n=require("vue"),r=require("prosemirror-history"),i=require("@stll/folio-core/utils/clipboard"),a=require("@stll/folio-core/managers/ClipboardManager"),o=require("@stll/folio-core/managers/TableSelectionManager"),s=require("@stll/folio-core/prosemirror/utils/visualLineNavigation"),c=require("@stll/folio-core/prosemirror/utils/extractTrackedChanges");function l(e={}){let{onCopy:t,onCut:r,onPaste:a,cleanWordFormatting:o=!0,editable:s=!0,onError:c}=e,l=(0,n.ref)(!1),u=(0,n.ref)(null),d=c?{onError:c}:{};async function f(e){if(l.value)return!1;l.value=!0;try{let n=await(0,i.copyRuns)(e.runs,d);return n&&t?.(e),n}finally{l.value=!1}}async function p(e){if(l.value||!s)return!1;l.value=!0;try{let t=await(0,i.copyRuns)(e.runs,d);return t&&r?.(e),t}finally{l.value=!1}}async function m(e=!1){if(l.value||!s)return null;l.value=!0;try{if(navigator.clipboard&&navigator.clipboard.read){let t=await navigator.clipboard.read(),n=``,r=``;for(let e of t)e.types.includes(`text/html`)&&(n=await(await e.getType(`text/html`)).text()),e.types.includes(`text/plain`)&&(r=await(await e.getType(`text/plain`)).text());e&&(n=``);let s=(0,i.parseClipboardHtml)(n,r,o);return u.value=s,a?.(s,e),s}return null}catch(e){return c?.(e instanceof Error?e:Error(String(e))),null}finally{l.value=!1}}return{copy:f,cut:p,paste:m,isProcessing:l,lastPastedContent:u}}function u({isOpen:e,onClose:t,align:r=`left`}){let i=(0,n.ref)(null),a=(0,n.ref)(null),o=(0,n.ref)({position:`fixed`,top:`0px`,left:`0px`,zIndex:1e4});function s(e,t){o.value={position:`fixed`,top:e+`px`,left:t+`px`,zIndex:1e4}}function c(e){let n=e.target;n instanceof Node&&i.value&&!i.value.contains(n)&&a.value&&!a.value.contains(n)&&t()}function l(e){e.key===`Escape`&&t()}function u(e){let n=e.target;n instanceof Node&&a.value&&a.value.contains(n)||t()}function d(){document.addEventListener(`mousedown`,c),document.addEventListener(`keydown`,l),window.addEventListener(`scroll`,u,!0)}function f(){document.removeEventListener(`mousedown`,c),document.removeEventListener(`keydown`,l),window.removeEventListener(`scroll`,u,!0)}(0,n.watch)(e,e=>{if(!e){f();return}let t=i.value;if(!t)return;let n=t.getBoundingClientRect();r===`right`?requestAnimationFrame(()=>{let e=a.value;if(e){let t=e.getBoundingClientRect();s(n.bottom+4,n.right-t.width)}else s(n.bottom+4,n.left)}):s(n.bottom+4,n.left),d()}),(0,n.onScopeDispose)(f);function p(e){e.preventDefault(),e.stopPropagation()}return{containerRef:i,dropdownRef:a,dropdownStyle:o,handleMouseDown:p}}function d(e,t){let i=(0,n.computed)(()=>{t.value;let n=e.value;return n?(0,r.undoDepth)(n.state)>0:!1}),a=(0,n.computed)(()=>{t.value;let n=e.value;return n?(0,r.redoDepth)(n.state)>0:!1});function o(){let t=e.value;return t?(0,r.undo)(t.state,t.dispatch):!1}function s(){let t=e.value;return t?(0,r.redo)(t.state,t.dispatch):!1}return{canUndo:i,canRedo:a,undo:o,redo:s}}var f={backgroundColor:`rgba(26, 115, 232, 0.3)`,borderRadius:0,zIndex:0,opacity:1,mixBlendMode:`multiply`};function p(e){let t=window.getSelection();if(!t||t.rangeCount===0||t.isCollapsed)return[];let n=t.getRangeAt(0);if(e&&!e.contains(n.commonAncestorContainer))return[];let r=0,i=0;if(e){let t=e.getBoundingClientRect();r=t.left+e.scrollLeft,i=t.top+e.scrollTop}let a=[];for(let e of n.getClientRects())e.width===0&&e.height===0||a.push({left:e.left-r,top:e.top-i,width:e.width,height:e.height});return a}function m(e,t=2){if(e.length<=1)return e;let n=[...e].sort((e,n)=>Math.abs(e.top-n.top)<t?e.left-n.left:e.top-n.top),r=n[0];if(!r)return e;let i=[],a={...r};for(let e=1;e<n.length;e++){let r=n[e];if(!r)continue;let o=Math.abs(r.top-a.top)<t,s=r.left<=a.left+a.width+t;if(o&&s){let e=Math.max(a.left+a.width,r.left+r.width);a.width=e-a.left,a.height=Math.max(a.height,r.height)}else i.push(a),a={...r}}return i.push(a),i}function h(e){return m(p(e))}function g(){let e=window.getSelection();return e!==null&&!e.isCollapsed&&e.rangeCount>0}function _(e){let t=window.getSelection();return!t||t.rangeCount===0?!1:e.contains(t.getRangeAt(0).commonAncestorContainer)}var v=`docx-selection-styles`,y=null;function b(){y&&=(y.remove(),null),document.getElementById(v)?.remove()}function x(e=f){b();let t=`
2
2
  /* DOCX Editor Selection Highlighting */
3
3
 
4
4
  .docx-editor [contenteditable="true"]::selection,
@@ -58,4 +58,4 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
58
58
  background-color: rgba(156, 39, 176, 0.2);
59
59
  border-bottom: 2px dashed rgba(156, 39, 176, 0.6);
60
60
  }
61
- `;v=document.createElement(`style`),v.id=_,v.textContent=t,document.head.appendChild(v)}function x(){return v!==null||document.getElementById(_)!==null}function S(){return window.getSelection()?.toString()??``}function C(e){let{containerRef:n,enabled:r=!0,config:i=d,useOverlay:a=!1,debounceMs:o=16,onSelectionChange:s}=e,c=(0,t.ref)(!1),l=(0,t.ref)(``),u=(0,t.ref)([]),f=(0,t.ref)(!1),p=null,_=0;function v(){let e=n.value,t=h(),r=S(),i=e?g(e):!1;c.value=t,l.value=r,f.value=i,u.value=a&&i&&e?m(e):[],s?.(t&&i,r)}function y(){v()}function C(){let e=performance.now();if(e-_<o){p&&clearTimeout(p),p=setTimeout(()=>{_=performance.now(),v(),p=null},o);return}_=e,v()}function w(e){let t={position:`absolute`,left:`${e.left}px`,top:`${e.top}px`,width:`${e.width}px`,height:`${e.height}px`,backgroundColor:i.backgroundColor,zIndex:i.zIndex??0,pointerEvents:`none`};return i.borderRadius&&(t.borderRadius=`${i.borderRadius}px`),i.borderColor&&(t.border=`1px solid ${i.borderColor}`),t}return(0,t.onMounted)(()=>{r&&(x()||b(i),document.addEventListener(`selectionchange`,C))}),(0,t.onBeforeUnmount)(()=>{document.removeEventListener(`selectionchange`,C),p&&clearTimeout(p)}),(0,t.watch)(n,()=>v()),{hasSelection:(0,t.computed)(()=>c.value),selectedText:(0,t.computed)(()=>l.value),highlightRects:(0,t.computed)(()=>u.value),isSelectionInContainer:(0,t.computed)(()=>f.value),refresh:y,getOverlayStyle:w}}function w(){let e=new a.TableSelectionManager,n=(0,t.ref)(null),r=()=>{let t=e.getSnapshot();n.value=t.tableIndex!==null&&t.rowIndex!==null&&t.columnIndex!==null?{tableIndex:t.tableIndex,rowIndex:t.rowIndex,columnIndex:t.columnIndex}:null},i=e.subscribe(r);r(),(0,t.onScopeDispose)(i);function o(e,t,n){}function s(t,n){(0,a.findTableFromClick)(t,n)||e.clearSelection()}function c(){e.clearSelection()}function l(t,n,r){return e.isCellSelected(t,n,r)}return{selectedCell:n,handleCellClick:o,handleClickTarget:s,clearSelection:c,isCellSelected:l}}function T(e){let t=(0,o.createVisualLineState)();function n(t){let n=e.value;return n?(0,o.getCaretClientX)(n,t):null}function r(t){let n=e.value;return n?(0,o.findLineElementAtPosition)(n,t):null}function i(e,t){return(0,o.findPositionOnLineAtClientX)(e,t)}function a(n,r){return(0,o.handleVisualLineKeyDown)(t,n,r,e.value)}return{state:t,getCaretClientX:n,findLineElementAtPosition:r,findPositionOnLineAtClientX:i,handlePMKeyDown:a}}exports.createSelectionFromDOM=i.createSelectionFromDOM,exports.extractTrackedChanges=s.extractTrackedChanges,exports.getSelectionRuns=i.getSelectionRuns,exports.runsToClipboardContent=r.runsToClipboardContent,exports.useClipboard=c,exports.useDocxEditor=e.a,exports.useDragAutoScroll=e.i,exports.useFixedDropdown=l,exports.useHistory=u,exports.useSelectionHighlight=C,exports.useTableResize=e.r,exports.useTableSelection=w,exports.useTrackedChanges=e.n,exports.useVisualLineNavigation=T,exports.useWheelZoom=e.t,exports.useZoom=e.t;
61
+ `;y=document.createElement(`style`),y.id=v,y.textContent=t,document.head.appendChild(y)}function S(){return y!==null||document.getElementById(v)!==null}function C(){return window.getSelection()?.toString()??``}function w(e){let{containerRef:t,enabled:r=!0,config:i=f,useOverlay:a=!1,debounceMs:o=16,onSelectionChange:s}=e,c=(0,n.ref)(!1),l=(0,n.ref)(``),u=(0,n.ref)([]),d=(0,n.ref)(!1),p=null,m=0;function v(){let e=t.value,n=g(),r=C(),i=e?_(e):!1;c.value=n,l.value=r,d.value=i,u.value=a&&i&&e?h(e):[],s?.(n&&i,r)}function y(){v()}function b(){let e=performance.now();if(e-m<o){p&&clearTimeout(p),p=setTimeout(()=>{m=performance.now(),v(),p=null},o);return}m=e,v()}function w(e){let t={position:`absolute`,left:`${e.left}px`,top:`${e.top}px`,width:`${e.width}px`,height:`${e.height}px`,backgroundColor:i.backgroundColor,zIndex:i.zIndex??0,pointerEvents:`none`};return i.borderRadius&&(t.borderRadius=`${i.borderRadius}px`),i.borderColor&&(t.border=`1px solid ${i.borderColor}`),t}return(0,n.onMounted)(()=>{r&&(S()||x(i),document.addEventListener(`selectionchange`,b))}),(0,n.onBeforeUnmount)(()=>{document.removeEventListener(`selectionchange`,b),p&&clearTimeout(p)}),(0,n.watch)(t,()=>v()),{hasSelection:(0,n.computed)(()=>c.value),selectedText:(0,n.computed)(()=>l.value),highlightRects:(0,n.computed)(()=>u.value),isSelectionInContainer:(0,n.computed)(()=>d.value),refresh:y,getOverlayStyle:w}}function T(){let e=new o.TableSelectionManager,t=(0,n.ref)(null),r=()=>{let n=e.getSnapshot();t.value=n.tableIndex!==null&&n.rowIndex!==null&&n.columnIndex!==null?{tableIndex:n.tableIndex,rowIndex:n.rowIndex,columnIndex:n.columnIndex}:null},i=e.subscribe(r);r(),(0,n.onScopeDispose)(i);function a(t,n,r){e.selectCellCoordinates({tableIndex:t,rowIndex:n,columnIndex:r})}function s(t,n){let r=(0,o.findTableFromClick)(t,n);if(!r){e.clearSelection();return}e.selectCellCoordinates(r)}function c(){e.clearSelection()}function l(t,n,r){return e.isCellSelected(t,n,r)}return{selectedCell:t,handleCellClick:a,handleClickTarget:s,clearSelection:c,isCellSelected:l}}function E(e){let t=(0,s.createVisualLineState)();function n(t){let n=e.value;return n?(0,s.getCaretClientX)(n,t):null}function r(t){let n=e.value;return n?(0,s.findLineElementAtPosition)(n,t):null}function i(e,t){return(0,s.findPositionOnLineAtClientX)(e,t)}function a(n,r){return(0,s.handleVisualLineKeyDown)(t,n,r,e.value)}return{state:t,getCaretClientX:n,findLineElementAtPosition:r,findPositionOnLineAtClientX:i,handlePMKeyDown:a}}exports.colorModePlugin=t.o,exports.createSelectionFromDOM=a.createSelectionFromDOM,exports.defaultColorMode=t.s,exports.extractTrackedChanges=c.extractTrackedChanges,exports.getSelectionRuns=a.getSelectionRuns,exports.provideColorMode=t.c,exports.runsToClipboardContent=i.runsToClipboardContent,exports.useClipboard=l,exports.useColorMode=t.l,exports.useDocxEditor=t.a,exports.useDragAutoScroll=t.i,exports.useFindReplace=e.t,exports.useFixedDropdown=u,exports.useHistory=d,exports.useSelectionHighlight=w,exports.useTableResize=t.r,exports.useTableSelection=T,exports.useTrackedChanges=t.n,exports.useVisualLineNavigation=E,exports.useWheelZoom=t.t,exports.useZoom=t.t;