@stll/folio-vue 0.2.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 (109) hide show
  1. package/dist/ListButtons-B498PX1d.js +4256 -0
  2. package/dist/ListButtons-D-zMJ7rl.cjs +4 -0
  3. package/dist/PageSetupDialog-CGBaBVzo.cjs +15 -0
  4. package/dist/PageSetupDialog-DsjAfJy0.js +4873 -0
  5. package/dist/TablePropertiesDialog-A-1Pm1f9.cjs +1 -0
  6. package/dist/TablePropertiesDialog-PyXEJC_o.js +887 -0
  7. package/dist/components/DocxEditor/pagedEditorRef.d.ts +75 -0
  8. package/dist/components/DocxEditor/types.d.ts +528 -0
  9. package/dist/components/EditorToolbarContext.d.ts +9 -0
  10. package/dist/components/FormattingBar.types.d.ts +67 -0
  11. package/dist/components/Toolbar/presets.d.ts +25 -0
  12. package/dist/components/dialogs/index.d.ts +24 -0
  13. package/dist/components/imageContextMenuTypes.d.ts +30 -0
  14. package/dist/components/imageSelectionTypes.d.ts +13 -0
  15. package/dist/components/insertTableState.d.ts +9 -0
  16. package/dist/components/sidebar/cardStyles.d.ts +1 -0
  17. package/dist/components/sidebar/cardUtils.d.ts +1 -0
  18. package/dist/components/sidebar/resolveItemPositions.d.ts +22 -0
  19. package/dist/components/sidebar/sidebarUtils.d.ts +4 -0
  20. package/dist/components/tableStylePresets.d.ts +60 -0
  21. package/dist/components/toolbarUtils.d.ts +3 -0
  22. package/dist/components/ui/AlignmentButtons.types.d.ts +13 -0
  23. package/dist/components/ui/StylePicker.types.d.ts +16 -0
  24. package/dist/components/ui/ZoomControl.types.d.ts +21 -0
  25. package/dist/components/ui/fontPickerValue.d.ts +1 -0
  26. package/dist/components/ui/hyperlinkPopupTypes.d.ts +20 -0
  27. package/dist/composables/commentMarks.d.ts +32 -0
  28. package/dist/composables/imageOverlayRect.d.ts +44 -0
  29. package/dist/composables/index.d.ts +30 -0
  30. package/dist/composables/useAutoSave.d.ts +39 -0
  31. package/dist/composables/useClipboard.d.ts +21 -0
  32. package/dist/composables/useColorMode.d.ts +8 -0
  33. package/dist/composables/useCommentLifecycle.d.ts +39 -0
  34. package/dist/composables/useCommentManagement.d.ts +47 -0
  35. package/dist/composables/useCommentSidebarItems.d.ts +24 -0
  36. package/dist/composables/useContextMenus.d.ts +64 -0
  37. package/dist/composables/useControllableBoolean.d.ts +16 -0
  38. package/dist/composables/useDocumentLifecycle.d.ts +11 -0
  39. package/dist/composables/useDocxEditor.d.ts +123 -0
  40. package/dist/composables/useDocxEditorRefApi.d.ts +68 -0
  41. package/dist/composables/useDragAutoScroll.d.ts +11 -0
  42. package/dist/composables/useFileIO.d.ts +43 -0
  43. package/dist/composables/useFindReplace.d.ts +22 -0
  44. package/dist/composables/useFixedDropdown.d.ts +14 -0
  45. package/dist/composables/useFormattingActions.d.ts +21 -0
  46. package/dist/composables/useHistory.d.ts +9 -0
  47. package/dist/composables/useHostCallbacks.d.ts +24 -0
  48. package/dist/composables/useHyperlinkManagement.d.ts +40 -0
  49. package/dist/composables/useImageActions.d.ts +25 -0
  50. package/dist/composables/useKeyboardShortcuts.d.ts +25 -0
  51. package/dist/composables/useMenuActions.d.ts +36 -0
  52. package/dist/composables/useOutlineSidebar.d.ts +24 -0
  53. package/dist/composables/usePageSetupControls.d.ts +28 -0
  54. package/dist/composables/usePagesPointer.d.ts +87 -0
  55. package/dist/composables/useParagraphStyleOptions.d.ts +18 -0
  56. package/dist/composables/usePortalClass.d.ts +8 -0
  57. package/dist/composables/useSelectionHighlight.d.ts +19 -0
  58. package/dist/composables/useSelectionSync.d.ts +30 -0
  59. package/dist/composables/useTableResize.d.ts +7 -0
  60. package/dist/composables/useTableSelection.d.ts +10 -0
  61. package/dist/composables/useToolbarDropdowns.d.ts +15 -0
  62. package/dist/composables/useToolbarFontSize.d.ts +15 -0
  63. package/dist/composables/useTrackedChanges.d.ts +12 -0
  64. package/dist/composables/useVisualLineNavigation.d.ts +11 -0
  65. package/dist/composables/useWheelZoom.d.ts +10 -0
  66. package/dist/composables/useZoom.d.ts +16 -0
  67. package/dist/composables.cjs +61 -0
  68. package/dist/composables.js +378 -0
  69. package/dist/dialogs.cjs +1 -0
  70. package/dist/dialogs.js +3 -0
  71. package/dist/folio-vue.css +2 -0
  72. package/dist/i18n/index.d.ts +36 -0
  73. package/dist/i18n/messages.d.ts +1 -0
  74. package/dist/index.cjs +1 -0
  75. package/dist/index.d.ts +50 -0
  76. package/dist/index.js +4088 -0
  77. package/dist/messages.cjs +1 -0
  78. package/dist/messages.js +1 -0
  79. package/dist/renderAsync.d.ts +35 -0
  80. package/dist/styles/index.d.ts +12 -0
  81. package/dist/styles/zIndex.d.ts +18 -0
  82. package/dist/styles.cjs +1 -0
  83. package/dist/styles.js +5 -0
  84. package/dist/ui/folio-ui.d.ts +139 -0
  85. package/dist/ui.cjs +1 -0
  86. package/dist/ui.d.ts +67 -0
  87. package/dist/ui.js +446 -0
  88. package/dist/useZoom-BryUw3Cu.cjs +1 -0
  89. package/dist/useZoom-CIIRid8U.js +626 -0
  90. package/dist/utils/aiEditRange.d.ts +26 -0
  91. package/dist/utils/autoScroll.d.ts +22 -0
  92. package/dist/utils/cardStyles.d.ts +3 -0
  93. package/dist/utils/colorMode.d.ts +32 -0
  94. package/dist/utils/comments.d.ts +20 -0
  95. package/dist/utils/cssTypes.d.ts +7 -0
  96. package/dist/utils/domQueries.d.ts +39 -0
  97. package/dist/utils/fontOptions.d.ts +26 -0
  98. package/dist/utils/hostFonts.d.ts +25 -0
  99. package/dist/utils/imageClipboard.d.ts +9 -0
  100. package/dist/utils/index.d.ts +13 -0
  101. package/dist/utils/listState.d.ts +22 -0
  102. package/dist/utils/reportIssue.d.ts +18 -0
  103. package/dist/utils/selectionHighlight.d.ts +44 -0
  104. package/dist/utils/sidebarConstants.d.ts +8 -0
  105. package/dist/utils/stylePreview.d.ts +53 -0
  106. package/dist/utils/textSelection.d.ts +40 -0
  107. package/dist/zIndex-BY0qa8Au.js +12 -0
  108. package/dist/zIndex-dFsQbASx.cjs +1 -0
  109. package/package.json +99 -0
@@ -0,0 +1,25 @@
1
+ import { FontOption } from '../../utils/fontOptions';
2
+ /**
3
+ * Minimal translation-key type for the Vue adapter. folio's `useTranslation().t`
4
+ * accepts a namespaced key path as a string; a stricter union can replace this
5
+ * once the toolbar catalog keys are generated.
6
+ */
7
+ export type TranslationKey = string;
8
+ export declare const defaultFonts: FontOption[];
9
+ export declare const fontSizePresets: number[];
10
+ export type ParagraphStylePreset = {
11
+ id: string;
12
+ /** Fallback label used if the i18n key resolves to nothing. */
13
+ label: string;
14
+ nameKey: TranslationKey;
15
+ };
16
+ export declare const paragraphStyles: ParagraphStylePreset[];
17
+ export type LineSpacingPreset = {
18
+ /** Fallback label; localized presets carry a `labelKey` instead. */
19
+ label: string;
20
+ labelKey?: TranslationKey;
21
+ value: number;
22
+ };
23
+ export declare const lineSpacingOptions: LineSpacingPreset[];
24
+ export declare const ZOOM_PRESETS: number[];
25
+ export declare const DEFAULT_ZOOM_PERCENT = 100;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @stll/folio-vue dialogs
3
+ *
4
+ * Modal dialog components — find/replace, page setup, table/image properties,
5
+ * image position, footnote/endnote properties, insert table, insert symbol, and
6
+ * hyperlinks. Mirrors the React dialogs subpath.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * import { HyperlinkDialog, FindReplaceDialog } from '@stll/folio-vue/dialogs';
11
+ * ```
12
+ *
13
+ * @packageDocumentation
14
+ * @public
15
+ */
16
+ export { default as FindReplaceDialog } from './FindReplaceDialog.vue';
17
+ export { default as FootnotePropertiesDialog } from './FootnotePropertiesDialog.vue';
18
+ export { default as HyperlinkDialog } from './HyperlinkDialog.vue';
19
+ export { default as ImagePositionDialog } from './ImagePositionDialog.vue';
20
+ export { default as ImagePropertiesDialog } from './ImagePropertiesDialog.vue';
21
+ export { default as InsertSymbolDialog } from './InsertSymbolDialog.vue';
22
+ export { default as InsertTableDialog } from './InsertTableDialog.vue';
23
+ export { default as PageSetupDialog } from './PageSetupDialog.vue';
24
+ export { default as TablePropertiesDialog } from './TablePropertiesDialog.vue';
@@ -0,0 +1,30 @@
1
+ import { WrapType } from '@stll/folio-core/docx/wrapTypes';
2
+ type ImageAttrsCssFloat = "left" | "right" | "none" | null;
3
+ export type ImageContextMenuState = {
4
+ open: boolean;
5
+ position: {
6
+ x: number;
7
+ y: number;
8
+ };
9
+ pmPos: number;
10
+ currentWrapType: WrapType;
11
+ currentCssFloat?: ImageAttrsCssFloat;
12
+ inlinePositionEmu?: {
13
+ horizontalEmu: number;
14
+ verticalEmu: number;
15
+ };
16
+ };
17
+ /**
18
+ * Item appended below a divider — mirrors the React side
19
+ * (`ImageContextMenuTextAction`). `dividerAfter` lets the host group
20
+ * the items the same way Word does (Cut/Copy/Paste then divider then
21
+ * Delete).
22
+ */
23
+ export type ImageContextMenuTextAction = {
24
+ action: string;
25
+ label: string;
26
+ shortcut?: string;
27
+ disabled?: boolean;
28
+ dividerAfter?: boolean;
29
+ };
30
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Shared `ImageSelectionInfo` type — imported by `ImageSelectionOverlay.vue`
3
+ * (for `defineProps`) and `useImageActions.ts` (for the composable's
4
+ * `selectedImage` ref). Pulled out of the `.vue` SFC so a plain `.ts` module can
5
+ * reference it without going through the `*.vue` wildcard shim, which does not
6
+ * carry named type exports.
7
+ */
8
+ export type ImageSelectionInfo = {
9
+ element: HTMLElement;
10
+ pmPos: number;
11
+ width: number;
12
+ height: number;
13
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Last-used Insert-Table dimensions. Module-level so the dialog reopens with
3
+ * whatever the user picked last time (mirrors React lifting this to component
4
+ * state that survives reopen).
5
+ */
6
+ export declare const rememberedTableSize: {
7
+ rows: number;
8
+ cols: number;
9
+ };
@@ -0,0 +1 @@
1
+ export { CARD_STYLE_COLLAPSED, CARD_STYLE_EXPANDED, } from '../../utils/cardStyles';
@@ -0,0 +1 @@
1
+ export * from './sidebarUtils';
@@ -0,0 +1,22 @@
1
+ /** Minimal shape the layout pass needs from a sidebar item. */
2
+ export type ResolvableSidebarItem = {
3
+ id: string;
4
+ anchorPos: number;
5
+ anchorKey?: string;
6
+ priority?: number;
7
+ fixedY?: number;
8
+ estimatedHeight?: number;
9
+ };
10
+ export type ResolvedPosition<T extends ResolvableSidebarItem = ResolvableSidebarItem> = {
11
+ item: T;
12
+ y: number;
13
+ };
14
+ /**
15
+ * Given a list of sidebar items plus their anchor sources, return resolved Y
16
+ * positions with collision avoidance applied. Items resolve their target Y from
17
+ * (1) an explicit `fixedY`, (2) an `anchorKey` lookup in `anchorPositions`
18
+ * (layout-engine coords scaled by `zoom`), or (3) the last-known cache so cards
19
+ * don't pop out during transient layout. Overlapping cards are then pushed down
20
+ * by their measured height + `MIN_CARD_GAP`.
21
+ */
22
+ export declare function resolveItemPositions<T extends ResolvableSidebarItem>(items: T[], anchorPositions: Map<string, number>, zoom: number, cardHeights: Map<string, number>, lastKnown: Map<string, number>): ResolvedPosition<T>[];
@@ -0,0 +1,4 @@
1
+ import { CSSProperties } from 'vue';
2
+ export { getCommentText, formatDate, getInitials, getAvatarColor, truncateText, type TrackedChangeEntry, } from '../../utils/comments';
3
+ /** Inline style for an avatar bubble — mirrors React's avatarStyle(). */
4
+ export declare function avatarStyle(name: string, size?: 32 | 28): CSSProperties;
@@ -0,0 +1,60 @@
1
+ import { CSSProperties } from 'vue';
2
+ export type TableStyleBorder = {
3
+ style: string;
4
+ size?: number;
5
+ color?: {
6
+ rgb: string;
7
+ };
8
+ };
9
+ export type TableStylePreset = {
10
+ id: string;
11
+ name: string;
12
+ /** Table-level borders */
13
+ tableBorders?: {
14
+ top?: TableStyleBorder;
15
+ bottom?: TableStyleBorder;
16
+ left?: TableStyleBorder;
17
+ right?: TableStyleBorder;
18
+ insideH?: TableStyleBorder;
19
+ insideV?: TableStyleBorder;
20
+ };
21
+ /** Conditional formatting per cell position */
22
+ conditionals?: Record<string, {
23
+ backgroundColor?: string;
24
+ borders?: {
25
+ top?: TableStyleBorder | null;
26
+ bottom?: TableStyleBorder | null;
27
+ left?: TableStyleBorder | null;
28
+ right?: TableStyleBorder | null;
29
+ };
30
+ bold?: boolean;
31
+ color?: string;
32
+ }>;
33
+ /** Which conditional formatting is active by default */
34
+ look?: {
35
+ firstRow?: boolean;
36
+ lastRow?: boolean;
37
+ firstCol?: boolean;
38
+ lastCol?: boolean;
39
+ noHBand?: boolean;
40
+ noVBand?: boolean;
41
+ };
42
+ };
43
+ export declare const BUILTIN_TABLE_STYLES: TableStylePreset[];
44
+ /** Get a built-in table style preset by ID. */
45
+ export declare function getBuiltinTableStyle(styleId: string): TableStylePreset | undefined;
46
+ /**
47
+ * Map from built-in style ID to folio-catalog translation key.
48
+ *
49
+ * TODO(i18n): none of these `table.styles.*` keys exist in folio's flat `folio`
50
+ * catalog (`packages/core/src/i18n/messages/en.json`) yet, so `presetName`
51
+ * currently renders the raw key path rather than a localized name. Kept verbatim
52
+ * (not invented) so the wiring is ready once the catalog gains the entries.
53
+ */
54
+ export declare const TABLE_STYLE_NAME_KEYS: Record<string, string>;
55
+ /**
56
+ * Build the per-cell inline styles for a small preview grid of the given
57
+ * preset. Shared by TableStyleGallery and InsertTableDialog so the preview
58
+ * rendering stays in one place.
59
+ */
60
+ export declare function getPreviewCells(preset: TableStylePreset, rows?: number, cols?: number): CSSProperties[];
@@ -0,0 +1,3 @@
1
+ /** OOXML highlight color name <-> hex mapping (hex keys, no `#`, uppercase). */
2
+ export declare const HIGHLIGHT_HEX_TO_NAME: Record<string, string>;
3
+ export declare function mapHexToHighlightName(hex: string): string | null;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Types for `AlignmentButtons.vue`, kept in a plain `.ts` module so downstream
3
+ * `.ts` consumers (and the standalone `FormattingBar`) can import the type
4
+ * without resolving a `.vue` SFC. A plain `tsc` (e.g. the Nuxt adapter's
5
+ * typecheck) sees `.vue` imports only through an ambient default-export shim, so
6
+ * named type exports must live in `.ts` files.
7
+ */
8
+ /**
9
+ * Paragraph alignment the picker offers. Intentionally the narrow subset the
10
+ * minimal toolbar exposes; core's `ParagraphAlignment` is a wider superset
11
+ * (distribute + Kashida variants) that this control does not surface.
12
+ */
13
+ export type ParagraphAlignment = "left" | "center" | "right" | "both";
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Types for `StylePicker.vue`, kept in a plain `.ts` module so downstream `.ts`
3
+ * consumers (and the standalone `FormattingBar`) can import the type without
4
+ * resolving a `.vue` SFC. A plain `tsc` (e.g. the Nuxt adapter's typecheck) sees
5
+ * `.vue` imports only through an ambient default-export shim, so named type
6
+ * exports must live in `.ts` files.
7
+ */
8
+ /** A single paragraph-style option the picker can offer. */
9
+ export type StyleOption = {
10
+ styleId: string;
11
+ name: string;
12
+ fontSize?: number;
13
+ bold?: boolean;
14
+ italic?: boolean;
15
+ color?: string;
16
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Types for `ZoomControl.vue`, kept in a plain `.ts` module so the package's
3
+ * public `index.ts` can re-export them without resolving a `.vue` SFC. A plain
4
+ * `tsc` (e.g. the Nuxt adapter's typecheck) sees `.vue` imports only through an
5
+ * ambient default-export shim, so named type exports must live in `.ts` files.
6
+ */
7
+ /** A single zoom preset: `value` is a scale factor (1 = 100%). */
8
+ export type ZoomLevel = {
9
+ value: number;
10
+ label: string;
11
+ };
12
+ export type ZoomControlProps = {
13
+ /** Current zoom (1 = 100%). */
14
+ value?: number;
15
+ /** Override the preset levels offered in the dropdown. */
16
+ levels?: ZoomLevel[];
17
+ disabled?: boolean;
18
+ className?: string;
19
+ /** Render the trigger at the smaller toolbar-chrome size. */
20
+ compact?: boolean;
21
+ };
@@ -0,0 +1 @@
1
+ export declare function getPrimaryFontFamily(fontFamily: string): string;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Shared `HyperlinkPopupData` type — imported by `HyperlinkPopup.vue`
3
+ * (for `defineProps`) and `useHyperlinkManagement.ts` (for the
4
+ * composable's `hyperlinkPopupData` ref). Pulled out of the .vue SFC so
5
+ * a plain .ts module can reference it without going through the `*.vue`
6
+ * wildcard shim, which doesn't carry named type exports.
7
+ */
8
+ export type HyperlinkPopupData = {
9
+ href: string;
10
+ displayText: string;
11
+ tooltip?: string;
12
+ /** Popup position in the editor's pages-viewport coordinate space (CSS
13
+ * pixels from its top-left). Computed once at click time. The popup
14
+ * renders inside that viewport with `position: absolute`, so the
15
+ * browser handles repositioning during scroll for free. */
16
+ position: {
17
+ top: number;
18
+ left: number;
19
+ };
20
+ };
@@ -0,0 +1,32 @@
1
+ import { EditorView } from 'prosemirror-view';
2
+ export type CommentMarkRange = {
3
+ from: number;
4
+ to: number;
5
+ };
6
+ /** Clamp a range into the document and reject an empty (collapsed) span. */
7
+ export declare function clampCommentMarkRange(docSize: number, range: CommentMarkRange): CommentMarkRange | null;
8
+ /**
9
+ * Pick the range to comment on, preferring the range captured when the FAB was
10
+ * shown, then the live selection, then the last non-empty selection. Mirrors
11
+ * React's `resolveCommentCreationRange`.
12
+ */
13
+ export type ResolveCommentCreationRangeOptions = {
14
+ docSize: number;
15
+ capturedRange: CommentMarkRange;
16
+ currentRange: CommentMarkRange;
17
+ savedRange: CommentMarkRange | null;
18
+ };
19
+ export declare function resolveCommentCreationRange({ docSize, capturedRange, currentRange, savedRange, }: ResolveCommentCreationRangeOptions): CommentMarkRange | null;
20
+ export type ApplyCommentMarkOptions = {
21
+ replacePending?: boolean;
22
+ selectEnd?: boolean;
23
+ };
24
+ /**
25
+ * Add a `comment` mark for `commentId` over `range`. With `replacePending` the
26
+ * placeholder mark (PENDING_COMMENT_ID) is removed from the range first so a
27
+ * pre-existing real comment the selection overlaps is left intact. Returns
28
+ * false when the schema lacks the mark or the range is empty.
29
+ */
30
+ export declare function applyCommentMarkRange(view: EditorView, range: CommentMarkRange, commentId: number, options?: ApplyCommentMarkOptions): boolean;
31
+ /** Strip the pending placeholder comment mark from `range` (cancel add-comment). */
32
+ export declare function removePendingCommentMarkRange(view: EditorView, range: CommentMarkRange): void;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Pure geometry for the Vue image-selection overlay. Kept separate from the
3
+ * component so the scrollbar-gutter handling can be unit-tested without a DOM.
4
+ */
5
+ export type OverlayRectInputs = {
6
+ /** `image.getBoundingClientRect()` (viewport coords). */
7
+ imageRect: {
8
+ left: number;
9
+ top: number;
10
+ width: number;
11
+ height: number;
12
+ };
13
+ /** `offsetParent.getBoundingClientRect()` (the scroll container, viewport coords). */
14
+ parentRect: {
15
+ left: number;
16
+ top: number;
17
+ };
18
+ scrollLeft: number;
19
+ scrollTop: number;
20
+ /** `offsetParent.offsetWidth` / `.clientWidth` — used to derive the gutter. */
21
+ parentOffsetWidth: number;
22
+ parentClientWidth: number;
23
+ zoom: number;
24
+ };
25
+ export type OverlayRect = {
26
+ left: number;
27
+ top: number;
28
+ width: number;
29
+ height: number;
30
+ };
31
+ /**
32
+ * Position the overlay (absolute, inside the scroll container) over the image.
33
+ *
34
+ * The scroll container uses `scrollbar-gutter: stable both-edges`, which
35
+ * reserves an inline-start gutter that sits OUTSIDE the absolute-positioning
36
+ * origin. `getBoundingClientRect().left` is the border-box left (before the
37
+ * gutter), so `imageRect.left - parentRect.left` over-counts the left gutter
38
+ * and the frame lands shifted right by that width (issue #764). With
39
+ * `both-edges` the two gutters are equal, so the left gutter is half of the
40
+ * total reserved inline space (`offsetWidth - clientWidth`, no borders here).
41
+ * On overlay-scrollbar platforms (e.g. macOS) the reserved space is 0, so the
42
+ * correction is a no-op and behavior is unchanged.
43
+ */
44
+ export declare function computeImageOverlayRect(i: OverlayRectInputs): OverlayRect;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * `@stll/folio-vue/composables`
3
+ *
4
+ * Vue composables mirroring the React `hooks` subpath — history, table
5
+ * selection, find/replace, clipboard, zoom, tracked-changes, visual-line
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).
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { useHistory, useFindReplace } from "@stll/folio-vue/composables";
13
+ * ```
14
+ *
15
+ * @packageDocumentation
16
+ * @public
17
+ */
18
+ export * from './useClipboard';
19
+ export * from './useDocxEditor';
20
+ export * from './useDragAutoScroll';
21
+ export * from './useFindReplace';
22
+ export * from './useFixedDropdown';
23
+ export * from './useHistory';
24
+ export * from './useSelectionHighlight';
25
+ export * from './useTableResize';
26
+ export * from './useTableSelection';
27
+ export * from './useTrackedChanges';
28
+ export * from './useVisualLineNavigation';
29
+ export * from './useWheelZoom';
30
+ export * from './useZoom';
@@ -0,0 +1,39 @@
1
+ import { MaybeRef, Ref } from 'vue';
2
+ import { formatLastSaveTime, getAutoSaveStatusLabel, getAutoSaveStorageSize, formatStorageSize, isAutoSaveSupported, AutoSaveStatus, SavedDocumentData } from '@stll/folio-core/managers/AutoSaveManager';
3
+ import { Document } from '@stll/folio-core/types/document';
4
+ export type { AutoSaveStatus, SavedDocumentData };
5
+ export { formatLastSaveTime, getAutoSaveStatusLabel, getAutoSaveStorageSize, formatStorageSize, isAutoSaveSupported, };
6
+ export type UseAutoSaveOptions = {
7
+ /** localStorage key (default: 'docx-editor-autosave') */
8
+ storageKey?: string;
9
+ /** Auto-save interval in ms (default: 30000) */
10
+ interval?: number;
11
+ /** Whether auto-save starts enabled (default: true). */
12
+ enabled?: boolean;
13
+ /** Maximum age of auto-save before it is considered stale. */
14
+ maxAge?: number;
15
+ /** Callback when save succeeds. */
16
+ onSave?: (timestamp: Date) => void;
17
+ /** Callback when save fails. */
18
+ onError?: (error: Error) => void;
19
+ /** Callback when recovery data is found. */
20
+ onRecoveryAvailable?: (savedDocument: SavedDocumentData) => void;
21
+ /** Whether document changes trigger a debounced save. */
22
+ saveOnChange?: boolean;
23
+ /** Debounce delay for saveOnChange in milliseconds. */
24
+ debounceDelay?: number;
25
+ };
26
+ export type UseAutoSaveReturn = {
27
+ status: Ref<AutoSaveStatus>;
28
+ lastSaveTime: Ref<Date | null>;
29
+ save: () => boolean;
30
+ clearAutoSave: () => void;
31
+ hasRecoveryData: Ref<boolean>;
32
+ getRecoveryData: () => SavedDocumentData | null;
33
+ acceptRecovery: () => Document | null;
34
+ dismissRecovery: () => void;
35
+ isEnabled: Ref<boolean>;
36
+ enable: () => void;
37
+ disable: () => void;
38
+ };
39
+ export declare function useAutoSave(document: MaybeRef<Document | null | undefined>, options?: UseAutoSaveOptions): UseAutoSaveReturn;
@@ -0,0 +1,21 @@
1
+ import { Ref } from 'vue';
2
+ import { runsToClipboardContent, ParsedClipboardContent } from '@stll/folio-core/utils/clipboard';
3
+ import { getSelectionRuns, createSelectionFromDOM, ClipboardSelection } from '@stll/folio-core/managers/ClipboardManager';
4
+ export { getSelectionRuns, createSelectionFromDOM, runsToClipboardContent };
5
+ export type { ClipboardSelection };
6
+ export type UseClipboardOptions = {
7
+ onCopy?: (selection: ClipboardSelection) => void;
8
+ onCut?: (selection: ClipboardSelection) => void;
9
+ onPaste?: (content: ParsedClipboardContent, asPlainText: boolean) => void;
10
+ cleanWordFormatting?: boolean;
11
+ editable?: boolean;
12
+ onError?: (error: Error) => void;
13
+ };
14
+ export type UseClipboardReturn = {
15
+ copy: (selection: ClipboardSelection) => Promise<boolean>;
16
+ cut: (selection: ClipboardSelection) => Promise<boolean>;
17
+ paste: (asPlainText?: boolean) => Promise<ParsedClipboardContent | null>;
18
+ isProcessing: Ref<boolean>;
19
+ lastPastedContent: Ref<ParsedClipboardContent | null>;
20
+ };
21
+ export declare function useClipboard(options?: UseClipboardOptions): UseClipboardReturn;
@@ -0,0 +1,8 @@
1
+ import { ComputedRef } from 'vue';
2
+ import { ColorMode } from '../utils/colorMode';
3
+ /**
4
+ * Resolve the effective dark flag from a reactive `colorMode`. `'system'`
5
+ * 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
+ */
8
+ export declare function useColorMode(colorMode: () => ColorMode): ComputedRef<boolean>;
@@ -0,0 +1,39 @@
1
+ import { Ref } from 'vue';
2
+ import { EditorView } from 'prosemirror-view';
3
+ import { Comment } from '@stll/folio-core/types/content';
4
+ export type FloatingCommentButton = {
5
+ top: number;
6
+ left: number;
7
+ from: number;
8
+ to: number;
9
+ };
10
+ export type UseCommentLifecycleOptions = {
11
+ editorView: Ref<EditorView | null>;
12
+ /** The absolute-positioned viewport the FAB is rendered into. */
13
+ pagesViewport: Ref<HTMLElement | null>;
14
+ /** The painted `.paged-editor__pages` container (anchor coordinate space). */
15
+ pagesContainer: Ref<HTMLElement | null>;
16
+ readOnly: Ref<boolean>;
17
+ /** Build a comment with a freshly-allocated id (from useCommentManagement). */
18
+ createComment: (text: string, parentId?: number) => Comment;
19
+ /** Append a comment + emit the change (from useCommentManagement). */
20
+ pushComment: (comment: Comment) => void;
21
+ reLayout: () => void;
22
+ showSidebar: Ref<boolean>;
23
+ /** Highlight the freshly-added comment card in the sidebar. */
24
+ setActiveSidebarItem: (id: string | null) => void;
25
+ };
26
+ export type UseCommentLifecycleReturn = {
27
+ isAddingComment: Ref<boolean>;
28
+ addCommentYPosition: Ref<number | null>;
29
+ floatingCommentButton: Ref<FloatingCommentButton | null>;
30
+ /** Recompute the floating button from the current selection (call on select). */
31
+ updateFloatingButton: () => void;
32
+ /** Enter the add-comment flow for the captured / current selection. */
33
+ startAddComment: () => void;
34
+ /** Submit the typed comment text; returns false when it could not be applied. */
35
+ handleAddComment: (text: string) => boolean;
36
+ /** Abandon the in-progress comment and clear the pending highlight. */
37
+ handleCancelAddComment: () => void;
38
+ };
39
+ export declare function useCommentLifecycle(options: UseCommentLifecycleOptions): UseCommentLifecycleReturn;
@@ -0,0 +1,47 @@
1
+ import { ComputedRef, Ref } from 'vue';
2
+ import { EditorView } from 'prosemirror-view';
3
+ import { Comment } from '@stll/folio-core/types/content';
4
+ import { Document } from '@stll/folio-core/types/document';
5
+ export type UseCommentManagementOptions = {
6
+ editorView: Ref<EditorView | null>;
7
+ getDocument: () => Document | null;
8
+ author: () => string;
9
+ /** Reader for the controlled `comments` prop (undefined => uncontrolled). */
10
+ commentsProp: () => Comment[] | undefined;
11
+ /** Fires on every comment-list mutation (controlled and uncontrolled). */
12
+ onCommentsChange: (comments: Comment[]) => void;
13
+ /** Re-run layout after a mutation that changed marks in the document. */
14
+ reLayout: () => void;
15
+ };
16
+ export type UseCommentManagementReturn = {
17
+ comments: ComputedRef<Comment[]>;
18
+ /**
19
+ * True when the comment thread list has user mutations not yet serialized by
20
+ * `save()`. Mirrors React's `commentsDirtyRef`: comment edits (add / reply /
21
+ * resolve / unresolve / delete) do not touch the PM document, so they are
22
+ * invisible to the doc-dirty flag; this surfaces them. Set on every user
23
+ * comment mutation, cleared on document load (`seedFromDocument`) and on a
24
+ * successful save (`clearCommentsDirty`).
25
+ */
26
+ commentsDirty: ComputedRef<boolean>;
27
+ /** Clear {@link commentsDirty} after a successful save. */
28
+ clearCommentsDirty: () => void;
29
+ /** Build a comment with a freshly-allocated, collision-seeded id. */
30
+ createComment: (text: string, parentId?: number) => Comment;
31
+ /** Append a comment and emit the change. */
32
+ pushComment: (comment: Comment) => void;
33
+ /** Replace the whole list and emit the change (uncontrolled also stores it). */
34
+ setComments: (next: Comment[]) => void;
35
+ /** Seed internal comments + the id allocator from the loaded document. */
36
+ seedFromDocument: () => void;
37
+ handleReply: (parentId: number, text: string) => void;
38
+ handleResolve: (commentId: number) => void;
39
+ handleUnresolve: (commentId: number) => void;
40
+ handleDelete: (commentId: number) => void;
41
+ handleTrackedChangeReply: (revisionId: number, text: string) => void;
42
+ handleAcceptChangeById: (revisionId: number) => void;
43
+ handleRejectChangeById: (revisionId: number) => void;
44
+ handleAcceptChange: (from: number, to: number) => void;
45
+ handleRejectChange: (from: number, to: number) => void;
46
+ };
47
+ export declare function useCommentManagement(options: UseCommentManagementOptions): UseCommentManagementReturn;
@@ -0,0 +1,24 @@
1
+ import { ComputedRef, Ref } from 'vue';
2
+ import { Comment } from '@stll/folio-core/types/content';
3
+ import { TrackedChangeEntry } from './useTrackedChanges';
4
+ export type CommentSidebarItem = {
5
+ id: string;
6
+ anchorPos: number;
7
+ anchorKey?: string;
8
+ priority?: number;
9
+ isTemporary?: boolean;
10
+ fixedY?: number;
11
+ estimatedHeight?: number;
12
+ kind: "add-comment" | "comment" | "tracked-change";
13
+ comment?: Comment;
14
+ replies?: Comment[];
15
+ change?: TrackedChangeEntry;
16
+ };
17
+ export type UseCommentSidebarItemsOptions = {
18
+ comments: Ref<Comment[]>;
19
+ trackedChanges: Ref<TrackedChangeEntry[]>;
20
+ showResolved?: Ref<boolean>;
21
+ isAddingComment?: Ref<boolean>;
22
+ addCommentYPosition?: Ref<number | null>;
23
+ };
24
+ export declare function useCommentSidebarItems({ comments, trackedChanges, showResolved, isAddingComment, addCommentYPosition, }: UseCommentSidebarItemsOptions): ComputedRef<CommentSidebarItem[]>;
@@ -0,0 +1,64 @@
1
+ import { ComputedRef, Ref, ShallowRef, VNodeChild } from 'vue';
2
+ import { Command } from 'prosemirror-state';
3
+ import { EditorView } from 'prosemirror-view';
4
+ import { ImageLayoutTarget } from '@stll/folio-core/layout-painter/imageLayout';
5
+ import { ImageSelectionInfo } from '../components/imageSelectionTypes';
6
+ import { ImageContextMenuState, ImageContextMenuTextAction } from '../components/imageContextMenuTypes';
7
+ type CommandFactory = (...args: readonly unknown[]) => Command;
8
+ export type TextContextMenuState = {
9
+ isOpen: boolean;
10
+ position: {
11
+ x: number;
12
+ y: number;
13
+ };
14
+ hasSelection: boolean;
15
+ inTable: boolean;
16
+ onImage: boolean;
17
+ canMergeCells: boolean;
18
+ canSplitCell: boolean;
19
+ };
20
+ /**
21
+ * One host-provided context-menu entry (the `customContextMenuItems` prop).
22
+ * Structural mirror of React's `DocxEditorProps.customContextMenuItems` items;
23
+ * `icon` is a Vue `VNodeChild` rather than a React node.
24
+ */
25
+ export type CustomContextMenuItem = {
26
+ id: string;
27
+ label: string;
28
+ requiresSelection?: boolean;
29
+ icon?: VNodeChild;
30
+ };
31
+ export type UseContextMenusOptions = {
32
+ editorView: Ref<EditorView | null>;
33
+ selectedImage: ShallowRef<ImageSelectionInfo | null>;
34
+ zoom: Ref<number>;
35
+ showImageProperties: Ref<boolean>;
36
+ getCommands: () => Record<string, CommandFactory>;
37
+ clearOverlay: () => void;
38
+ setPmSelection: (anchor: number, head?: number) => void;
39
+ resolvePos: (clientX: number, clientY: number) => number | null;
40
+ /** Host-injected menu entries, appended after the built-ins (lead the menu). */
41
+ customContextMenuItems?: () => readonly CustomContextMenuItem[] | undefined;
42
+ /**
43
+ * Fires with the item id (menu-namespace stripped) and the selection range
44
+ * captured when the menu opened. Right-click can collapse the live PM
45
+ * selection, so the captured range is preferred when non-empty.
46
+ */
47
+ onCustomContextAction?: (id: string, selectionRange: {
48
+ from: number;
49
+ to: number;
50
+ }) => void;
51
+ };
52
+ export type UseContextMenusReturn = {
53
+ contextMenu: Ref<TextContextMenuState>;
54
+ imageContextMenu: Ref<ImageContextMenuState | null>;
55
+ imageContextMenuTextActions: ComputedRef<ImageContextMenuTextAction[]>;
56
+ /** Host items to lead the text menu, already filtered by `requiresSelection`. */
57
+ customTextMenuItems: ComputedRef<CustomContextMenuItem[]>;
58
+ handleContextMenu: (event: MouseEvent) => void;
59
+ handleSelectedImageContextMenu: (event: MouseEvent) => void;
60
+ handleImageWrapSelect: (target: ImageLayoutTarget) => void;
61
+ handleContextMenuAction: (action: string) => void;
62
+ };
63
+ export declare function useContextMenus(opts: UseContextMenusOptions): UseContextMenusReturn;
64
+ export {};