@libraz/mejiro-react 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/index.d.ts +352 -134
- package/dist/index.js +2062 -1605
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as react from 'react';
|
|
|
4
4
|
import { ReactNode, CSSProperties, PointerEvent, TextareaHTMLAttributes, MutableRefObject, RefObject } from 'react';
|
|
5
5
|
import { EpubBook, AssetResolver, EpubParseLimits, EditableEpub, ManuscriptDialect, EpubChapter, EditableEpubBook, EditableEpubSelection, AnnotatedParagraph, AddImageInput, EditableEpubImage, EpubExportOptions, EpubProjectMetadata, EpubProjectAsset, EpubProject } from '@libraz/mejiro/epub';
|
|
6
6
|
export { EditableEpubSelection } from '@libraz/mejiro/epub';
|
|
7
|
-
import { ChapterLayout, SpreadResult, BookOptions, ComputePageSizeOptions, InChapterAnchor, ReadingAnchor, ManuscriptChapter, PageResult, AnchorRect, AnchorRange, MejiroBook } from '@libraz/mejiro/book';
|
|
7
|
+
import { ChapterLayout, SpreadResult, BookOptions, MejiroBookOptions, ComputePageSizeOptions, InChapterAnchor, ReadingAnchor, ManuscriptChapter, PageResult, AnchorRect, AnchorRange, MejiroBook } from '@libraz/mejiro/book';
|
|
8
8
|
import { RenderPage } from '@libraz/mejiro/render';
|
|
9
9
|
import { FontFamily, InlineAnnotation } from '@libraz/mejiro/browser';
|
|
10
10
|
|
|
@@ -32,6 +32,10 @@ declare function resolveMessages(locale: MejiroLocale | undefined, overrides: Pa
|
|
|
32
32
|
/** Replace `{name}` placeholders in a template. */
|
|
33
33
|
declare function format(template: string, vars: Record<string, string | number>): string;
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Layout of {@link MejiroChapterNav}: `'select'` is a compact dropdown,
|
|
37
|
+
* `'panel'` a chapter list with titles, headings and a text preview.
|
|
38
|
+
*/
|
|
35
39
|
type MejiroChapterNavVariant = 'select' | 'panel';
|
|
36
40
|
/** Props for {@link MejiroChapterNav}. */
|
|
37
41
|
interface MejiroChapterNavProps {
|
|
@@ -58,7 +62,7 @@ declare function MejiroChapterNav({ epub, chapter, onChange, variant, }: MejiroC
|
|
|
58
62
|
interface MejiroDropZoneProps {
|
|
59
63
|
/** File `accept` filter for the picker. @defaultValue '.epub' */
|
|
60
64
|
accept?: string;
|
|
61
|
-
/** Validator. Defaults to `
|
|
65
|
+
/** Validator. Defaults to the `accept` filter, with extensions matched case-insensitively. */
|
|
62
66
|
validateFile?: (file: File) => boolean;
|
|
63
67
|
/** Called with the selected/dropped file. */
|
|
64
68
|
onFile: (file: File) => void;
|
|
@@ -96,6 +100,7 @@ interface MejiroSettingsPanelProps {
|
|
|
96
100
|
*/
|
|
97
101
|
declare function MejiroSettingsPanel({ open, settings, onChange, fonts, minFontSize, maxFontSize, }: MejiroSettingsPanelProps): ReactNode;
|
|
98
102
|
|
|
103
|
+
/** Props for {@link MejiroEditor}. */
|
|
99
104
|
interface MejiroEditorProps {
|
|
100
105
|
/** URL fetched and loaded on mount. */
|
|
101
106
|
epubUrl?: string;
|
|
@@ -152,7 +157,10 @@ interface MejiroEditorProps {
|
|
|
152
157
|
onLoad?: (editor: EditableEpub) => void;
|
|
153
158
|
/** Called after export completes. */
|
|
154
159
|
onExport?: (buffer: ArrayBuffer) => void;
|
|
155
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* Called when loading, image insertion or export fails. The error is also
|
|
162
|
+
* shown in the editor.
|
|
163
|
+
*/
|
|
156
164
|
onError?: (error: Error) => void;
|
|
157
165
|
}
|
|
158
166
|
/**
|
|
@@ -227,8 +235,9 @@ interface UseImageOverlayReturn {
|
|
|
227
235
|
* with automatic text reflow via {@link ChapterLayout.syncImages}.
|
|
228
236
|
*
|
|
229
237
|
* While an overlay is active the exclusion is re-issued whenever `layout` is
|
|
230
|
-
* replaced or `
|
|
231
|
-
* the overlay drawn without its matching
|
|
238
|
+
* replaced, `spreadIdx` changes or `options.margin` changes, so a re-layout, a
|
|
239
|
+
* page turn or a new margin never leaves the overlay drawn without its matching
|
|
240
|
+
* text reflow.
|
|
232
241
|
*
|
|
233
242
|
* @param layout - Current chapter layout (or `null` if not yet loaded).
|
|
234
243
|
* @param spreadIdx - Current spread index.
|
|
@@ -262,6 +271,10 @@ interface MejiroImageOverlayProps {
|
|
|
262
271
|
*/
|
|
263
272
|
declare function MejiroImageOverlay({ rect, label, onOverlayPointerDown, onResizePointerDown, onClose, }: MejiroImageOverlayProps): ReactNode;
|
|
264
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Where {@link MejiroReader} places its chapter navigation: the header
|
|
276
|
+
* dropdown (`'select'`), the side chapter list (`'panel'`), both, or neither.
|
|
277
|
+
*/
|
|
265
278
|
type MejiroChapterNavMode = 'select' | 'panel' | 'both' | 'none';
|
|
266
279
|
/**
|
|
267
280
|
* Reading-flow mode for {@link MejiroReader}.
|
|
@@ -272,8 +285,9 @@ type MejiroReaderMode = 'paginated' | 'scroll';
|
|
|
272
285
|
/**
|
|
273
286
|
* Two-page vs single-page rendering of a spread.
|
|
274
287
|
* - `double` — always render two pages (default).
|
|
275
|
-
* - `single` — render
|
|
276
|
-
* - `auto` — switch based on the surface aspect ratio (single when portrait)
|
|
288
|
+
* - `single` — render one page at a time, centered; spread indices count pages.
|
|
289
|
+
* - `auto` — switch based on the surface aspect ratio (single when portrait),
|
|
290
|
+
* converting the index so the page on screen stays visible.
|
|
277
291
|
*/
|
|
278
292
|
type MejiroSpreadMode = 'double' | 'single' | 'auto';
|
|
279
293
|
/**
|
|
@@ -305,9 +319,13 @@ type MejiroTheme = MejiroThemeName | {
|
|
|
305
319
|
};
|
|
306
320
|
/** Reading position exposed by {@link MejiroReaderHandle.getReadingPosition}. */
|
|
307
321
|
interface ReadingPosition {
|
|
322
|
+
/** Zero-based index of the current chapter. */
|
|
308
323
|
chapter: number;
|
|
324
|
+
/** Zero-based index of the current spread within the chapter. */
|
|
309
325
|
spreadIdx: number;
|
|
326
|
+
/** Number of pages in the current chapter's layout. */
|
|
310
327
|
totalPages: number;
|
|
328
|
+
/** Number of spreads in the current chapter's layout. */
|
|
311
329
|
totalSpreads: number;
|
|
312
330
|
}
|
|
313
331
|
/**
|
|
@@ -342,29 +360,33 @@ interface MejiroReaderHandle {
|
|
|
342
360
|
next(): void;
|
|
343
361
|
/** Go back one spread. */
|
|
344
362
|
prev(): void;
|
|
345
|
-
/** Jump to a chapter (resets spread index to 0). */
|
|
363
|
+
/** Jump to a chapter (clamped to the book's chapters; resets spread index to 0). */
|
|
346
364
|
goToChapter(index: number): void;
|
|
347
365
|
/** Read the current reading position. */
|
|
348
366
|
getReadingPosition(): ReadingPosition;
|
|
349
367
|
/**
|
|
350
368
|
* Navigate to a {@link ReadingAnchor}. If the chapter differs from the
|
|
351
369
|
* current one, the chapter is switched first; once the new layout is ready
|
|
352
|
-
* the anchor is resolved and the matching spread is opened.
|
|
370
|
+
* the anchor is resolved and the matching spread is opened. A call made
|
|
371
|
+
* before the book has loaded is applied once it has.
|
|
353
372
|
*
|
|
354
|
-
* Returns a promise that resolves once the spread has been applied
|
|
355
|
-
*
|
|
356
|
-
*
|
|
373
|
+
* Returns a promise that resolves once the spread has been applied, or
|
|
374
|
+
* without moving when the anchor's chapter or position does not exist in the
|
|
375
|
+
* book. If another `goToAnchor` is invoked before the previous one settles,
|
|
376
|
+
* the earlier promise resolves immediately (superseded). Resolves on unmount.
|
|
357
377
|
*/
|
|
358
378
|
goToAnchor(anchor: ReadingAnchor): Promise<void>;
|
|
359
379
|
/**
|
|
360
|
-
* Returns the {@link ReadingAnchor} at the start of the current
|
|
361
|
-
* or `null` if the layout is not ready.
|
|
380
|
+
* Returns the {@link ReadingAnchor} at the start of the text on the current
|
|
381
|
+
* spread, or `null` if the layout is not ready. When an image blocks every
|
|
382
|
+
* page of the spread, the anchor is where the text resumes after it; `null`
|
|
383
|
+
* again if none follows.
|
|
362
384
|
*/
|
|
363
385
|
getAnchor(): ReadingAnchor | null;
|
|
364
386
|
/**
|
|
365
387
|
* Returns the half-open range of {@link ReadingAnchor}s visible on the
|
|
366
|
-
* current spread. `end` points at the start of the
|
|
367
|
-
* of the chapter
|
|
388
|
+
* current spread. `end` points at the start of the text on the next spread
|
|
389
|
+
* that has any (or the end of the chapter when none does).
|
|
368
390
|
*/
|
|
369
391
|
getVisibleRange(): {
|
|
370
392
|
start: ReadingAnchor;
|
|
@@ -376,8 +398,9 @@ interface MejiroReaderHandle {
|
|
|
376
398
|
*
|
|
377
399
|
* Successive calls are coalesced into a single application; the returned
|
|
378
400
|
* promise resolves once that application has settled. A failed application
|
|
379
|
-
* (
|
|
380
|
-
* {@link MejiroReaderProps.onError} rather than rejecting
|
|
401
|
+
* (such as a font that measures as a fallback under `strictFontCheck`) is
|
|
402
|
+
* reported through {@link MejiroReaderProps.onError} rather than rejecting
|
|
403
|
+
* the promise.
|
|
381
404
|
*/
|
|
382
405
|
setOptions(partial: Partial<BookOptions>): Promise<void>;
|
|
383
406
|
/**
|
|
@@ -413,8 +436,10 @@ interface MejiroReaderCommonProps {
|
|
|
413
436
|
* ```ts
|
|
414
437
|
* { ...DEFAULT_BOOK_OPTIONS, fontFamily: '"Noto Serif JP"', fontSize: 18 }
|
|
415
438
|
* ```
|
|
439
|
+
*
|
|
440
|
+
* `strictFontCheck` is read once, when the reader mounts.
|
|
416
441
|
*/
|
|
417
|
-
options?: Partial<
|
|
442
|
+
options?: Partial<MejiroBookOptions>;
|
|
418
443
|
/**
|
|
419
444
|
* Page-geometry overrides forwarded to `MejiroBook.computePageSize`. Use to
|
|
420
445
|
* tune how the spread is sized inside the surface — most usefully to shrink
|
|
@@ -434,7 +459,9 @@ interface MejiroReaderCommonProps {
|
|
|
434
459
|
/**
|
|
435
460
|
* Controlled spread index. When supplied, the reader is driven by this
|
|
436
461
|
* value and emits {@link MejiroReaderProps.onSpreadIdxChange} on user
|
|
437
|
-
* navigation.
|
|
462
|
+
* navigation. A spread index does not survive reflow, so persist the
|
|
463
|
+
* reading position with `useReadingPosition` and the handle's
|
|
464
|
+
* `getAnchor` / `goToAnchor` instead.
|
|
438
465
|
*/
|
|
439
466
|
spreadIdx?: number;
|
|
440
467
|
/**
|
|
@@ -451,8 +478,10 @@ interface MejiroReaderCommonProps {
|
|
|
451
478
|
*/
|
|
452
479
|
mode?: MejiroReaderMode;
|
|
453
480
|
/**
|
|
454
|
-
* Spread layout. `double` (default) renders two pages; `single` renders
|
|
455
|
-
*
|
|
481
|
+
* Spread layout. `double` (default) renders two pages; `single` renders one
|
|
482
|
+
* page at a time, and `spreadIdx`, `goToSpread`, `onSpreadIdxChange` and
|
|
483
|
+
* `spreadChanged` then count pages; `auto` flips to `single` for portrait
|
|
484
|
+
* viewports, keeping the page on screen visible.
|
|
456
485
|
*/
|
|
457
486
|
spreadMode?: MejiroSpreadMode;
|
|
458
487
|
/**
|
|
@@ -489,7 +518,7 @@ interface MejiroReaderCommonProps {
|
|
|
489
518
|
* component directly, so hosts that accept them should tighten the
|
|
490
519
|
* defaults here.
|
|
491
520
|
*/
|
|
492
|
-
limits?: EpubParseLimits
|
|
521
|
+
limits?: Partial<EpubParseLimits>;
|
|
493
522
|
/**
|
|
494
523
|
* Custom EPUB fetcher used in place of the global `fetch`. Overrides
|
|
495
524
|
* {@link fetchOptions} when set.
|
|
@@ -585,7 +614,8 @@ interface MejiroReaderCommonProps {
|
|
|
585
614
|
onLoad?: (book: EpubBook) => void;
|
|
586
615
|
/**
|
|
587
616
|
* Called when loading or parsing an EPUB fails, and when applying an option
|
|
588
|
-
* change fails (
|
|
617
|
+
* change fails (such as a font that measures as a fallback under
|
|
618
|
+
* `strictFontCheck`; without it, a font that fails to load is not an error).
|
|
589
619
|
*/
|
|
590
620
|
onError?: (error: Error) => void;
|
|
591
621
|
/** Called when the chapter index changes. */
|
|
@@ -655,18 +685,31 @@ interface MejiroReaderManuscriptProps extends MejiroReaderCommonProps {
|
|
|
655
685
|
* modes — TypeScript prevents passing more than one source at once.
|
|
656
686
|
*/
|
|
657
687
|
type MejiroReaderProps = MejiroReaderControlledProps | MejiroReaderUrlProps | MejiroReaderFileProps | MejiroReaderManuscriptProps;
|
|
688
|
+
/**
|
|
689
|
+
* Full-page EPUB reader. Composes the package's primitives into a working
|
|
690
|
+
* reader; features opt out via the `enableX` props or all chrome via `bare`.
|
|
691
|
+
* The `ref` exposes {@link MejiroReaderHandle} for imperative navigation.
|
|
692
|
+
*/
|
|
658
693
|
declare const MejiroReader: react.ForwardRefExoticComponent<MejiroReaderProps & react.RefAttributes<MejiroReaderHandle>>;
|
|
659
694
|
|
|
695
|
+
/** One chapter of the manuscript being edited. */
|
|
660
696
|
interface ManuscriptEditorChapter {
|
|
697
|
+
/** Stable identifier; survives reordering and title edits. */
|
|
661
698
|
id: string;
|
|
699
|
+
/** Chapter title; an empty title falls back to the localized "untitled" label. */
|
|
662
700
|
title: string;
|
|
701
|
+
/** Chapter body in the editor's manuscript notation. */
|
|
663
702
|
body: string;
|
|
664
703
|
}
|
|
665
704
|
/** Autosave payload emitted by {@link MejiroManuscriptEditor}. */
|
|
666
705
|
interface ManuscriptAutosaveDraft {
|
|
706
|
+
/** Book title as currently entered. */
|
|
667
707
|
title: string;
|
|
708
|
+
/** Author name as currently entered. */
|
|
668
709
|
author: string;
|
|
710
|
+
/** Selected cover image, or `null` when none is set. */
|
|
669
711
|
cover: File | null;
|
|
712
|
+
/** Chapters in reading order, as plain (non-reactive) copies. */
|
|
670
713
|
chapters: ManuscriptEditorChapter[];
|
|
671
714
|
}
|
|
672
715
|
/**
|
|
@@ -676,14 +719,23 @@ interface ManuscriptAutosaveDraft {
|
|
|
676
719
|
* supplied here.
|
|
677
720
|
*/
|
|
678
721
|
interface ManuscriptPreviewProps {
|
|
722
|
+
/** Header subtitle of the preview reader. */
|
|
679
723
|
subtitle?: string;
|
|
724
|
+
/** Header title of the preview reader. */
|
|
680
725
|
title?: string;
|
|
726
|
+
/** Where the preview places its chapter navigation. @defaultValue 'panel' */
|
|
681
727
|
chapterNavMode?: 'select' | 'panel' | 'both' | 'none';
|
|
728
|
+
/** Show the preview header. */
|
|
682
729
|
enableHeader?: boolean;
|
|
730
|
+
/** Show the preview chapter navigation. */
|
|
683
731
|
enableChapterNav?: boolean;
|
|
732
|
+
/** Show the preview settings panel toggle. */
|
|
684
733
|
enableSettings?: boolean;
|
|
734
|
+
/** Show the preview layout statistics. */
|
|
685
735
|
enableStats?: boolean;
|
|
736
|
+
/** Enable arrow-key page turns in the preview. */
|
|
686
737
|
enableKeyboard?: boolean;
|
|
738
|
+
/** Show the preview page indicator. */
|
|
687
739
|
enablePageIndicator?: boolean;
|
|
688
740
|
/** Book options forwarded to the embedded reader preview. */
|
|
689
741
|
options?: Partial<BookOptions>;
|
|
@@ -698,6 +750,7 @@ interface ManuscriptPreviewProps {
|
|
|
698
750
|
* to `true` to demo the fullscreen-reader behavior.
|
|
699
751
|
*/
|
|
700
752
|
enableSurfaceTap?: boolean;
|
|
753
|
+
/** Render the preview without any reader chrome. */
|
|
701
754
|
bare?: boolean;
|
|
702
755
|
}
|
|
703
756
|
/** Props for {@link MejiroManuscriptEditor}. */
|
|
@@ -861,6 +914,60 @@ interface MejiroPageViewProps {
|
|
|
861
914
|
*/
|
|
862
915
|
declare function MejiroPageView({ result, fontFamily, lineSpacing, slotMode, className, style, }: MejiroPageViewProps): ReactNode;
|
|
863
916
|
|
|
917
|
+
/** A single image overlay placed on a specific spread. */
|
|
918
|
+
interface MultiImageItem {
|
|
919
|
+
/** Stable ID for the overlay (auto-assigned on add). */
|
|
920
|
+
id: string;
|
|
921
|
+
/** Position and size in pixels, relative to the right page. */
|
|
922
|
+
rect: ImageRect;
|
|
923
|
+
}
|
|
924
|
+
/** Options for {@link useMultiImageOverlay}. */
|
|
925
|
+
interface UseMultiImageOverlayOptions {
|
|
926
|
+
/** Default image width. @defaultValue 120 */
|
|
927
|
+
defaultWidth?: number;
|
|
928
|
+
/** Default image height. @defaultValue 160 */
|
|
929
|
+
defaultHeight?: number;
|
|
930
|
+
/** Default x. @defaultValue 80 */
|
|
931
|
+
defaultX?: number;
|
|
932
|
+
/** Default y. @defaultValue 100 */
|
|
933
|
+
defaultY?: number;
|
|
934
|
+
/** Margin around each image, in pixels. Defaults to the book's font size. */
|
|
935
|
+
margin?: number;
|
|
936
|
+
/** Called after every reflow caused by adding/removing/moving an image. */
|
|
937
|
+
onUpdate?: (spread: SpreadResult) => void;
|
|
938
|
+
}
|
|
939
|
+
/** Return value of {@link useMultiImageOverlay}. */
|
|
940
|
+
interface UseMultiImageOverlayReturn {
|
|
941
|
+
/**
|
|
942
|
+
* Map of all images keyed by spread index. A new map whenever the images or
|
|
943
|
+
* the margin they are applied with change, and a replacement layout has them
|
|
944
|
+
* before any view renders from it, so this map and the layout together key
|
|
945
|
+
* anything derived from the layout.
|
|
946
|
+
*/
|
|
947
|
+
imagesBySpread: Map<number, MultiImageItem[]>;
|
|
948
|
+
/** Images on the current spread; a new array whenever `imagesBySpread` changes. */
|
|
949
|
+
currentImages: MultiImageItem[];
|
|
950
|
+
/** Whether any spread has at least one image. */
|
|
951
|
+
hasImages: boolean;
|
|
952
|
+
/** Add a new image on the current spread. */
|
|
953
|
+
addImage: (overrides?: Partial<ImageRect>) => MultiImageItem;
|
|
954
|
+
/** Remove the image with the given id. */
|
|
955
|
+
removeImage: (id: string) => void;
|
|
956
|
+
/** Replace an image's rectangle. */
|
|
957
|
+
updateImage: (id: string, rect: Partial<ImageRect>) => void;
|
|
958
|
+
/** Remove every image (or only those on `spreadIdx` if given). */
|
|
959
|
+
clearImages: (spreadIdx?: number) => void;
|
|
960
|
+
/** Pointer-down handler for the overlay body (drag). */
|
|
961
|
+
onOverlayPointerDown: (id: string, e: PointerEvent) => void;
|
|
962
|
+
/** Pointer-down handler for the resize handle. */
|
|
963
|
+
onResizePointerDown: (id: string, e: PointerEvent) => void;
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* React hook that manages multiple draggable/resizable image overlays
|
|
967
|
+
* per spread with automatic reflow via {@link ChapterLayout.setImages}.
|
|
968
|
+
*/
|
|
969
|
+
declare function useMultiImageOverlay(layout: ChapterLayout | null, spreadIdx: number, options?: UseMultiImageOverlayOptions): UseMultiImageOverlayReturn;
|
|
970
|
+
|
|
864
971
|
/** Props for {@link MejiroScrollView}. */
|
|
865
972
|
interface MejiroScrollViewProps {
|
|
866
973
|
/** Layout containing the pages to render. */
|
|
@@ -891,6 +998,31 @@ interface MejiroScrollViewProps {
|
|
|
891
998
|
scrollToPage?: number;
|
|
892
999
|
/** Vertical gap between pages (px). @defaultValue 24 */
|
|
893
1000
|
pageGap?: number;
|
|
1001
|
+
/**
|
|
1002
|
+
* Selection rectangles to highlight. Compute via
|
|
1003
|
+
* {@link ChapterLayout.selectionRects}; each entry is painted on the page its
|
|
1004
|
+
* `pageIdx` addresses. An entry may carry a `color` fill.
|
|
1005
|
+
*/
|
|
1006
|
+
selectionRects?: readonly (AnchorRect & {
|
|
1007
|
+
color?: string;
|
|
1008
|
+
})[];
|
|
1009
|
+
/** Zero-based spread whose pages carry {@link MejiroScrollViewProps.images}. */
|
|
1010
|
+
spreadIdx?: number;
|
|
1011
|
+
/**
|
|
1012
|
+
* Image overlays on the spread at {@link MejiroScrollViewProps.spreadIdx}.
|
|
1013
|
+
* Each renders on the page whose area contains its centre (see
|
|
1014
|
+
* `overlayPageSide`), matching {@link MejiroSpread}'s single-page routing.
|
|
1015
|
+
* The layout reflows in place when its images change, so a new array here is
|
|
1016
|
+
* also what re-reads the pages; `useMultiImageOverlay`'s `currentImages`
|
|
1017
|
+
* provides one on every change.
|
|
1018
|
+
*/
|
|
1019
|
+
images?: MultiImageItem[];
|
|
1020
|
+
/** Pointer-down on an image overlay. */
|
|
1021
|
+
onImagePointerDown?: (id: string, e: PointerEvent) => void;
|
|
1022
|
+
/** Pointer-down on an image resize handle. */
|
|
1023
|
+
onImageResizePointerDown?: (id: string, e: PointerEvent) => void;
|
|
1024
|
+
/** Image overlay close button. */
|
|
1025
|
+
onImageClose?: (id: string) => void;
|
|
894
1026
|
}
|
|
895
1027
|
/**
|
|
896
1028
|
* Continuous-scroll variant of {@link MejiroSpread}. Stacks every page in
|
|
@@ -898,7 +1030,7 @@ interface MejiroScrollViewProps {
|
|
|
898
1030
|
* detected via `IntersectionObserver` and reported through
|
|
899
1031
|
* {@link MejiroScrollViewProps.onVisiblePageChange}.
|
|
900
1032
|
*/
|
|
901
|
-
declare function MejiroScrollView({ layout, pageWidth, pageHeight, contentHeight, fontFamily, fontSize, lineSpacing, slotMode, onVisiblePageChange, scrollToPage, pageGap, }: MejiroScrollViewProps): ReactNode;
|
|
1033
|
+
declare function MejiroScrollView({ layout, pageWidth, pageHeight, contentHeight, fontFamily, fontSize, lineSpacing, slotMode, onVisiblePageChange, scrollToPage, pageGap, selectionRects, spreadIdx, images, onImagePointerDown, onImageResizePointerDown, onImageClose, }: MejiroScrollViewProps): ReactNode;
|
|
902
1034
|
|
|
903
1035
|
/** Props for {@link MejiroSelectionLayer}. */
|
|
904
1036
|
interface MejiroSelectionLayerProps {
|
|
@@ -986,7 +1118,7 @@ interface MejiroShelfProps<T = unknown> {
|
|
|
986
1118
|
currentId?: string;
|
|
987
1119
|
/** Called when the user picks a volume. */
|
|
988
1120
|
onSelect?: (volume: VolumeInfo<T>) => void;
|
|
989
|
-
/** Heading shown above the grid.
|
|
1121
|
+
/** Heading shown above the grid. Defaults to the active message catalog's `shelfTitle`. */
|
|
990
1122
|
title?: string;
|
|
991
1123
|
}
|
|
992
1124
|
/**
|
|
@@ -995,55 +1127,6 @@ interface MejiroShelfProps<T = unknown> {
|
|
|
995
1127
|
*/
|
|
996
1128
|
declare function MejiroShelf<T = unknown>({ volumes, currentId, onSelect, title, }: MejiroShelfProps<T>): ReactNode;
|
|
997
1129
|
|
|
998
|
-
/** A single image overlay placed on a specific spread. */
|
|
999
|
-
interface MultiImageItem {
|
|
1000
|
-
/** Stable ID for the overlay (auto-assigned on add). */
|
|
1001
|
-
id: string;
|
|
1002
|
-
/** Position and size in pixels, relative to the right page. */
|
|
1003
|
-
rect: ImageRect;
|
|
1004
|
-
}
|
|
1005
|
-
/** Options for {@link useMultiImageOverlay}. */
|
|
1006
|
-
interface UseMultiImageOverlayOptions {
|
|
1007
|
-
/** Default image width. @defaultValue 120 */
|
|
1008
|
-
defaultWidth?: number;
|
|
1009
|
-
/** Default image height. @defaultValue 160 */
|
|
1010
|
-
defaultHeight?: number;
|
|
1011
|
-
/** Default x. @defaultValue 80 */
|
|
1012
|
-
defaultX?: number;
|
|
1013
|
-
/** Default y. @defaultValue 100 */
|
|
1014
|
-
defaultY?: number;
|
|
1015
|
-
/** Margin around each image, in pixels. Defaults to the book's font size. */
|
|
1016
|
-
margin?: number;
|
|
1017
|
-
/** Called after every reflow caused by adding/removing/moving an image. */
|
|
1018
|
-
onUpdate?: (spread: SpreadResult) => void;
|
|
1019
|
-
}
|
|
1020
|
-
/** Return value of {@link useMultiImageOverlay}. */
|
|
1021
|
-
interface UseMultiImageOverlayReturn {
|
|
1022
|
-
/** Map of all images keyed by spread index. */
|
|
1023
|
-
imagesBySpread: Map<number, MultiImageItem[]>;
|
|
1024
|
-
/** Images on the current spread. */
|
|
1025
|
-
currentImages: MultiImageItem[];
|
|
1026
|
-
/** Whether any spread has at least one image. */
|
|
1027
|
-
hasImages: boolean;
|
|
1028
|
-
/** Add a new image on the current spread. */
|
|
1029
|
-
addImage: (overrides?: Partial<ImageRect>) => MultiImageItem;
|
|
1030
|
-
/** Remove the image with the given id. */
|
|
1031
|
-
removeImage: (id: string) => void;
|
|
1032
|
-
/** Replace an image's rectangle. */
|
|
1033
|
-
updateImage: (id: string, rect: Partial<ImageRect>) => void;
|
|
1034
|
-
/** Remove every image (or only those on `spreadIdx` if given). */
|
|
1035
|
-
clearImages: (spreadIdx?: number) => void;
|
|
1036
|
-
/** Pointer-down handler for the overlay body (drag). */
|
|
1037
|
-
onOverlayPointerDown: (id: string, e: PointerEvent) => void;
|
|
1038
|
-
/** Pointer-down handler for the resize handle. */
|
|
1039
|
-
onResizePointerDown: (id: string, e: PointerEvent) => void;
|
|
1040
|
-
}
|
|
1041
|
-
/**
|
|
1042
|
-
* React hook that manages multiple draggable/resizable image overlays
|
|
1043
|
-
* per spread with automatic reflow via {@link ChapterLayout.setImages}.
|
|
1044
|
-
*/
|
|
1045
|
-
declare function useMultiImageOverlay(layout: ChapterLayout | null, spreadIdx: number, options?: UseMultiImageOverlayOptions): UseMultiImageOverlayReturn;
|
|
1046
|
-
|
|
1047
1130
|
/** Props for {@link MejiroSpread}. */
|
|
1048
1131
|
interface MejiroSpreadProps {
|
|
1049
1132
|
/** Spread data to render. */
|
|
@@ -1066,7 +1149,11 @@ interface MejiroSpreadProps {
|
|
|
1066
1149
|
rightHeader?: PageHeaderData;
|
|
1067
1150
|
/** Header data for the left page. */
|
|
1068
1151
|
leftHeader?: PageHeaderData;
|
|
1069
|
-
/**
|
|
1152
|
+
/**
|
|
1153
|
+
* Image overlays on the current spread, relative to the right page. With
|
|
1154
|
+
* {@link MejiroSpreadProps.singlePage}, only those whose centre lies on the
|
|
1155
|
+
* page shown are drawn.
|
|
1156
|
+
*/
|
|
1070
1157
|
images?: MultiImageItem[];
|
|
1071
1158
|
/**
|
|
1072
1159
|
* Force slot-mode rendering on both pages. When omitted, each page falls
|
|
@@ -1117,11 +1204,16 @@ interface MejiroSpreadProps {
|
|
|
1117
1204
|
*/
|
|
1118
1205
|
onSelectionChange?: (range: AnchorRange | null) => void;
|
|
1119
1206
|
/**
|
|
1120
|
-
*
|
|
1121
|
-
* for portrait viewports or
|
|
1122
|
-
* mode.
|
|
1207
|
+
* Render only one page of the spread (centered), chosen by
|
|
1208
|
+
* {@link MejiroSpreadProps.singleSide}. Use this for portrait viewports or
|
|
1209
|
+
* when a reader explicitly opts into single-page mode.
|
|
1123
1210
|
*/
|
|
1124
1211
|
singlePage?: boolean;
|
|
1212
|
+
/**
|
|
1213
|
+
* Page of the spread shown when {@link MejiroSpreadProps.singlePage} is set
|
|
1214
|
+
* (`useSpread` reports it as `singleSide`). @defaultValue 'right'
|
|
1215
|
+
*/
|
|
1216
|
+
singleSide?: 'right' | 'left';
|
|
1125
1217
|
/**
|
|
1126
1218
|
* Called when the user makes a quick swipe gesture on the spread.
|
|
1127
1219
|
* `direction === 'next'` means the user swiped from right to left (the
|
|
@@ -1132,10 +1224,11 @@ interface MejiroSpreadProps {
|
|
|
1132
1224
|
onSurfaceTap?: () => void;
|
|
1133
1225
|
}
|
|
1134
1226
|
/**
|
|
1135
|
-
* Renders a two-page spread
|
|
1136
|
-
* zones, and image overlays. Used inside
|
|
1227
|
+
* Renders a two-page spread (or one page of it in single-page mode) with the
|
|
1228
|
+
* book frame, page chrome, navigation zones, and image overlays. Used inside
|
|
1229
|
+
* `mejiro-reader-surface`.
|
|
1137
1230
|
*/
|
|
1138
|
-
declare function MejiroSpread({ spread, pageWidth, pageHeight, contentHeight, fontFamily, fontSize, lineSpacing, turning, rightHeader, leftHeader, images, slotMode, renderPageHeader, indicator, onPrev, onNext, onImagePointerDown, onImageResizePointerDown, onImageClose, anchorAtCoord, spreadIdx, selectionRects, onSelectionChange, singlePage, onSwipe, onSurfaceTap, }: MejiroSpreadProps): ReactNode;
|
|
1231
|
+
declare function MejiroSpread({ spread, pageWidth, pageHeight, contentHeight, fontFamily, fontSize, lineSpacing, turning, rightHeader, leftHeader, images, slotMode, renderPageHeader, indicator, onPrev, onNext, onImagePointerDown, onImageResizePointerDown, onImageClose, anchorAtCoord, spreadIdx, selectionRects, onSelectionChange, singlePage, singleSide, onSwipe, onSurfaceTap, }: MejiroSpreadProps): ReactNode;
|
|
1139
1232
|
|
|
1140
1233
|
/** Props for {@link MejiroStats}. */
|
|
1141
1234
|
interface MejiroStatsProps {
|
|
@@ -1165,9 +1258,9 @@ interface MejiroTocProps {
|
|
|
1165
1258
|
currentAnchor?: ReadingAnchor | null;
|
|
1166
1259
|
/** Show a search input that filters chapter titles. @defaultValue false */
|
|
1167
1260
|
searchable?: boolean;
|
|
1168
|
-
/** Heading displayed above the list.
|
|
1261
|
+
/** Heading displayed above the list. Defaults to the active message catalog's `tocTitle`. */
|
|
1169
1262
|
title?: string;
|
|
1170
|
-
/** Placeholder shown in the search input.
|
|
1263
|
+
/** Placeholder shown in the search input. Defaults to the active message catalog's `tocSearchPlaceholder`. */
|
|
1171
1264
|
searchPlaceholder?: string;
|
|
1172
1265
|
/** Called when the user picks a chapter. */
|
|
1173
1266
|
onSelect?: (chapter: number) => void;
|
|
@@ -1247,17 +1340,26 @@ interface UseChapterLayoutOptions {
|
|
|
1247
1340
|
*/
|
|
1248
1341
|
pageGeometry?: () => ComputePageSizeOptions | undefined;
|
|
1249
1342
|
/**
|
|
1250
|
-
* Capture the
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1254
|
-
* Never called for blank (content-change) re-layouts.
|
|
1255
|
-
*
|
|
1256
|
-
* A reflow yields a brand-new {@link ChapterLayout} object, which resets any
|
|
1257
|
-
* downstream spread index to 0; capturing here and restoring after keeps the
|
|
1258
|
-
* reader on the same passage across resizes and font / option changes.
|
|
1343
|
+
* Capture the reading position from the outgoing layout, just before a
|
|
1344
|
+
* **reflow** (non-blank) re-layout replaces it. The anchor is held in
|
|
1345
|
+
* `pendingRestore` until the new layout is in place, then handed to
|
|
1346
|
+
* `restorePosition` when one is given. Return `null` to skip preservation.
|
|
1347
|
+
* Never called for blank (content-change) re-layouts, which start at spread 0.
|
|
1259
1348
|
*/
|
|
1260
1349
|
capturePosition?: (layout: ChapterLayout) => InChapterAnchor | null;
|
|
1350
|
+
/**
|
|
1351
|
+
* Apply an anchor captured by `capturePosition` to the new layout, e.g. by
|
|
1352
|
+
* locating it and jumping to its spread. Called once the new layout is in
|
|
1353
|
+
* place — after it commits, before paint — and `pendingRestore` is cleared
|
|
1354
|
+
* first. Without it, consume `pendingRestore` yourself.
|
|
1355
|
+
*/
|
|
1356
|
+
restorePosition?: (layout: ChapterLayout, position: InChapterAnchor) => void;
|
|
1357
|
+
/**
|
|
1358
|
+
* Called once when a layout of the current source fails, whichever path
|
|
1359
|
+
* started it (source change, resize or `recompute`); a superseded layout
|
|
1360
|
+
* reports nothing. When supplied, `recompute` resolves instead of rejecting.
|
|
1361
|
+
*/
|
|
1362
|
+
onError?: (error: Error) => void;
|
|
1261
1363
|
}
|
|
1262
1364
|
/** Options for {@link UseChapterLayoutReturn.recompute}. */
|
|
1263
1365
|
interface RecomputeOptions {
|
|
@@ -1271,8 +1373,11 @@ interface RecomputeOptions {
|
|
|
1271
1373
|
}
|
|
1272
1374
|
/** Page dimensions returned by {@link MejiroBook.computePageSize}. */
|
|
1273
1375
|
interface PageDimensions {
|
|
1376
|
+
/** Width of one page, in CSS pixels. */
|
|
1274
1377
|
pageWidth: number;
|
|
1378
|
+
/** Height of one page, in CSS pixels. */
|
|
1275
1379
|
pageHeight: number;
|
|
1380
|
+
/** Height of the text area inside a page, in CSS pixels. */
|
|
1276
1381
|
contentHeight: number;
|
|
1277
1382
|
}
|
|
1278
1383
|
/** Return value of {@link useChapterLayout}. */
|
|
@@ -1287,12 +1392,16 @@ interface UseChapterLayoutReturn {
|
|
|
1287
1392
|
contentHeight: number;
|
|
1288
1393
|
/** Most recent layout time (ms). */
|
|
1289
1394
|
elapsedMs: number;
|
|
1290
|
-
/**
|
|
1395
|
+
/**
|
|
1396
|
+
* Force a fresh layout computation. A failure goes to `onError` when one is
|
|
1397
|
+
* supplied; otherwise the returned promise rejects.
|
|
1398
|
+
*/
|
|
1291
1399
|
recompute: (opts?: RecomputeOptions) => Promise<void>;
|
|
1292
1400
|
/**
|
|
1293
|
-
* Anchor captured before the most recent reflow
|
|
1294
|
-
* restoration into the new
|
|
1295
|
-
*
|
|
1401
|
+
* Anchor captured by `capturePosition` before the most recent reflow,
|
|
1402
|
+
* awaiting restoration into the new layout. `restorePosition`, when given,
|
|
1403
|
+
* consumes it; otherwise read it once the new layout is in place and set it
|
|
1404
|
+
* back to `null`.
|
|
1296
1405
|
*
|
|
1297
1406
|
* Declared as a `MutableRefObject` because consumers are expected to write to
|
|
1298
1407
|
* it — `@types/react@18` models `RefObject.current` as read-only, so a
|
|
@@ -1311,13 +1420,16 @@ interface UseChapterLayoutReturn {
|
|
|
1311
1420
|
* mounted before its container had a final box is still sized correctly on
|
|
1312
1421
|
* first paint), and later size changes trigger a debounced **full re-layout**.
|
|
1313
1422
|
*
|
|
1314
|
-
*
|
|
1315
|
-
*
|
|
1316
|
-
*
|
|
1317
|
-
*
|
|
1318
|
-
*
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1423
|
+
* Size and option changes lay the chapter out again rather than calling
|
|
1424
|
+
* `ChapterLayout.resize()`, so page geometry is re-derived from the surface and
|
|
1425
|
+
* the book's current options. The book replays the line-breaking hints it
|
|
1426
|
+
* already derived for the chapter, so a reflow never re-runs the analyzer.
|
|
1427
|
+
* Because each re-layout yields a new {@link ChapterLayout} object (resetting
|
|
1428
|
+
* any downstream spread index to 0), the reading position is carried across
|
|
1429
|
+
* reflows by {@link UseChapterLayoutOptions.capturePosition},
|
|
1430
|
+
* {@link UseChapterLayoutOptions.restorePosition} and
|
|
1431
|
+
* {@link UseChapterLayoutReturn.pendingRestore}, identically in the Vue
|
|
1432
|
+
* composable.
|
|
1321
1433
|
*
|
|
1322
1434
|
* @param book - The book instance to lay out with.
|
|
1323
1435
|
* @param epub - The current parsed EPUB.
|
|
@@ -1327,6 +1439,7 @@ interface UseChapterLayoutReturn {
|
|
|
1327
1439
|
*/
|
|
1328
1440
|
declare function useChapterLayout(book: MejiroBook, epub: EpubBook | null, chapterIndex: number, surface: RefObject<HTMLElement | null>, options?: UseChapterLayoutOptions): UseChapterLayoutReturn;
|
|
1329
1441
|
|
|
1442
|
+
/** Options for {@link useEditableEpub}. */
|
|
1330
1443
|
interface UseEditableEpubOptions {
|
|
1331
1444
|
/** URL fetched and loaded on mount. */
|
|
1332
1445
|
defaultUrl?: string;
|
|
@@ -1342,32 +1455,58 @@ interface UseEditableEpubOptions {
|
|
|
1342
1455
|
* fields keep their `DEFAULT_EPUB_PARSE_LIMITS` value.
|
|
1343
1456
|
*/
|
|
1344
1457
|
limits?: Partial<EpubParseLimits>;
|
|
1458
|
+
/**
|
|
1459
|
+
* Resolves URL-only images into bytes when {@link UseEditableEpubReturn.exportEpub}
|
|
1460
|
+
* packages the book. An `assetResolver` passed to `exportEpub` itself wins.
|
|
1461
|
+
*/
|
|
1462
|
+
assetResolver?: AssetResolver;
|
|
1345
1463
|
}
|
|
1464
|
+
/** Return value of {@link useEditableEpub}. */
|
|
1346
1465
|
interface UseEditableEpubReturn {
|
|
1466
|
+
/** Loaded editor, or `null` before any load. */
|
|
1347
1467
|
editor: EditableEpub | null;
|
|
1468
|
+
/** The editor's live document, or `null` before any load. */
|
|
1348
1469
|
book: EditableEpubBook | null;
|
|
1470
|
+
/** Snapshot of `book` re-cloned on every edit, for feeding a preview reader. */
|
|
1349
1471
|
previewBook: EditableEpubBook | null;
|
|
1472
|
+
/** Whether a load is in progress. */
|
|
1350
1473
|
loading: boolean;
|
|
1474
|
+
/** Whether an export is in progress. */
|
|
1351
1475
|
exporting: boolean;
|
|
1476
|
+
/** Last load error, if any. */
|
|
1352
1477
|
error: Error | null;
|
|
1478
|
+
/** Counter bumped on every load, edit, undo and redo. */
|
|
1353
1479
|
revision: number;
|
|
1480
|
+
/** Undo / redo availability, or `null` before any load. */
|
|
1354
1481
|
history: {
|
|
1355
1482
|
canUndo: boolean;
|
|
1356
1483
|
canRedo: boolean;
|
|
1357
1484
|
depth: number;
|
|
1358
1485
|
redoDepth: number;
|
|
1359
1486
|
} | null;
|
|
1487
|
+
/** Paragraph targeted by the editing commands. */
|
|
1360
1488
|
selection: EditableEpubSelection;
|
|
1489
|
+
/** The paragraph at `selection`, or `null` when there is none. */
|
|
1361
1490
|
selectedParagraph: AnnotatedParagraph | null;
|
|
1491
|
+
/** Moves the selection, clamped to the loaded book. */
|
|
1362
1492
|
setSelection: (selection: EditableEpubSelection) => void;
|
|
1493
|
+
/** Loads an EPUB from an in-memory buffer. */
|
|
1363
1494
|
loadBuffer: (buffer: ArrayBuffer) => Promise<EditableEpub | null>;
|
|
1495
|
+
/** Loads an EPUB from a {@link File}. */
|
|
1364
1496
|
loadFile: (file: File) => Promise<EditableEpub | null>;
|
|
1497
|
+
/** Fetches and loads an EPUB; a non-2xx response is reported as an error. */
|
|
1365
1498
|
loadUrl: (url: string) => Promise<EditableEpub | null>;
|
|
1499
|
+
/** Replaces the selected paragraph's text and, optionally, its inline annotations. */
|
|
1366
1500
|
updateParagraph: (text: string, inlineAnnotations?: readonly InlineAnnotation[]) => void;
|
|
1501
|
+
/** Replaces the selected paragraph's inline annotations. */
|
|
1367
1502
|
setInlineAnnotations: (inlineAnnotations: readonly InlineAnnotation[]) => void;
|
|
1503
|
+
/** Inserts an image into the selected chapter. */
|
|
1368
1504
|
addImage: (image: AddImageInput | EditableEpubImage) => void;
|
|
1505
|
+
/** Reverts the last edit. Returns `false` when there is nothing to undo. */
|
|
1369
1506
|
undo: () => boolean;
|
|
1507
|
+
/** Re-applies the last undone edit. Returns `false` when there is nothing to redo. */
|
|
1370
1508
|
redo: () => boolean;
|
|
1509
|
+
/** Packages the edited document as an EPUB buffer. */
|
|
1371
1510
|
exportEpub: (options?: EpubExportOptions) => Promise<ArrayBuffer | null>;
|
|
1372
1511
|
}
|
|
1373
1512
|
/** Headless editable-EPUB state for custom proofreading/editor UIs. */
|
|
@@ -1375,11 +1514,11 @@ declare function useEditableEpub(options?: UseEditableEpubOptions): UseEditableE
|
|
|
1375
1514
|
|
|
1376
1515
|
/** Options for {@link useEpub}. */
|
|
1377
1516
|
interface UseEpubOptions {
|
|
1378
|
-
/** URL fetched on mount.
|
|
1517
|
+
/** URL fetched on mount. */
|
|
1379
1518
|
defaultUrl?: string;
|
|
1380
1519
|
/** Called after a successful load. */
|
|
1381
1520
|
onLoad?: (book: EpubBook) => void;
|
|
1382
|
-
/** Called when a load fails
|
|
1521
|
+
/** Called when a load fails, including a non-2xx URL response. */
|
|
1383
1522
|
onError?: (error: Error) => void;
|
|
1384
1523
|
/**
|
|
1385
1524
|
* Extra options merged into the `fetch` call when loading by URL. Useful
|
|
@@ -1424,8 +1563,11 @@ declare function useEpub(options?: UseEpubOptions): UseEpubReturn;
|
|
|
1424
1563
|
|
|
1425
1564
|
/** One chapter of the manuscript draft the hook keeps in React state. */
|
|
1426
1565
|
interface EpubProjectChapterDraft {
|
|
1566
|
+
/** Stable chapter identifier. */
|
|
1427
1567
|
id: string;
|
|
1568
|
+
/** Chapter title. */
|
|
1428
1569
|
title: string;
|
|
1570
|
+
/** Chapter body in the manuscript notation. */
|
|
1429
1571
|
body: string;
|
|
1430
1572
|
}
|
|
1431
1573
|
/** Options for {@link useEpubProject}. */
|
|
@@ -1465,19 +1607,32 @@ interface UseEpubProjectOptions {
|
|
|
1465
1607
|
}
|
|
1466
1608
|
/** State and actions returned by {@link useEpubProject}. */
|
|
1467
1609
|
interface UseEpubProjectReturn {
|
|
1610
|
+
/** Current book metadata. */
|
|
1468
1611
|
metadata: EpubProjectMetadata;
|
|
1612
|
+
/** Current chapter drafts, in reading order. */
|
|
1469
1613
|
chapters: EpubProjectChapterDraft[];
|
|
1614
|
+
/** Index of the chapter being edited. */
|
|
1470
1615
|
selectedChapter: number;
|
|
1616
|
+
/** The chapter at `selectedChapter`, or `null` when there is none. */
|
|
1471
1617
|
currentChapter: EpubProjectChapterDraft | null;
|
|
1472
1618
|
/** Current cover asset, or `null` when the project has no cover. */
|
|
1473
1619
|
cover: EpubProjectAsset | null;
|
|
1474
1620
|
/** Current non-cover assets, in registration order. */
|
|
1475
1621
|
assets: EpubProjectAsset[];
|
|
1622
|
+
/** Parsed EPUB built from the current project, refreshed after each debounced change. */
|
|
1476
1623
|
previewBook: EpubBook | null;
|
|
1624
|
+
/** Last preview build failure, if any. */
|
|
1477
1625
|
previewError: Error | null;
|
|
1626
|
+
/** Whether a preview build is pending or running. */
|
|
1478
1627
|
previewing: boolean;
|
|
1628
|
+
/**
|
|
1629
|
+
* Merges `patch` into the metadata. A missing or blank `identifier` keeps the
|
|
1630
|
+
* current one.
|
|
1631
|
+
*/
|
|
1479
1632
|
setMetadata: (patch: Partial<EpubProjectMetadata>) => void;
|
|
1633
|
+
/** Replaces every chapter; an empty list becomes one generated chapter. */
|
|
1480
1634
|
setChapters: (chapters: EpubProjectChapterDraft[]) => void;
|
|
1635
|
+
/** Selects a chapter, clamped to the chapter range. */
|
|
1481
1636
|
setSelectedChapter: (index: number) => void;
|
|
1482
1637
|
/**
|
|
1483
1638
|
* Replaces the cover asset, or drops it when passed `null`. The new cover is
|
|
@@ -1489,8 +1644,14 @@ interface UseEpubProjectReturn {
|
|
|
1489
1644
|
* project, so URL-only entries reach `assetResolver` at export time.
|
|
1490
1645
|
*/
|
|
1491
1646
|
setAssets: (assets: EpubProjectAsset[]) => void;
|
|
1647
|
+
/** Merges `patch` into the chapter at `index`. */
|
|
1492
1648
|
patchChapter: (index: number, patch: Partial<EpubProjectChapterDraft>) => void;
|
|
1649
|
+
/** Appends a chapter (generated defaults fill omitted fields) and selects it. */
|
|
1493
1650
|
addChapter: (chapter?: Partial<EpubProjectChapterDraft>) => void;
|
|
1651
|
+
/**
|
|
1652
|
+
* Removes the chapter at `index` (the selected one by default); the last chapter is never
|
|
1653
|
+
* removed.
|
|
1654
|
+
*/
|
|
1494
1655
|
removeChapter: (index?: number) => void;
|
|
1495
1656
|
/**
|
|
1496
1657
|
* Moves a chapter from `from` to `to`. An out-of-range `from` selects no
|
|
@@ -1498,7 +1659,9 @@ interface UseEpubProjectReturn {
|
|
|
1498
1659
|
* the same contract as `EpubProject.reorderChapters()`.
|
|
1499
1660
|
*/
|
|
1500
1661
|
reorderChapters: (from: number, to: number) => void;
|
|
1662
|
+
/** Builds an `EpubProject` from the current state. */
|
|
1501
1663
|
buildProject: () => EpubProject;
|
|
1664
|
+
/** Packages the current project as an EPUB buffer. */
|
|
1502
1665
|
exportEpub: () => Promise<ArrayBuffer>;
|
|
1503
1666
|
}
|
|
1504
1667
|
/** Headless manuscript-to-EPUB project state for custom authoring UIs. */
|
|
@@ -1526,14 +1689,24 @@ interface UseManuscriptDraftOptions<TAutosave = ManuscriptEditorChapter[]> {
|
|
|
1526
1689
|
}
|
|
1527
1690
|
/** Return value of {@link useManuscriptDraft}. */
|
|
1528
1691
|
interface UseManuscriptDraftReturn {
|
|
1692
|
+
/** Current chapters, in reading order. */
|
|
1529
1693
|
chapters: ManuscriptEditorChapter[];
|
|
1530
1694
|
/** Index of the chapter currently being edited. */
|
|
1531
1695
|
selected: number;
|
|
1696
|
+
/** Selects a chapter, clamped to the chapter range. */
|
|
1532
1697
|
setSelected(index: number): void;
|
|
1698
|
+
/**
|
|
1699
|
+
* Replaces every chapter; an empty list becomes one generated chapter. The
|
|
1700
|
+
* selected chapter is kept by id when it survives.
|
|
1701
|
+
*/
|
|
1533
1702
|
setChapters(chapters: ManuscriptEditorChapter[]): void;
|
|
1703
|
+
/** Merges `patch` into the chapter at `index`. */
|
|
1534
1704
|
patchChapter(index: number, patch: Partial<ManuscriptEditorChapter>): void;
|
|
1705
|
+
/** Appends a chapter (generated defaults fill omitted fields) and selects it. */
|
|
1535
1706
|
addChapter(chapter?: Partial<ManuscriptEditorChapter>): void;
|
|
1707
|
+
/** Removes the chapter at `index`; the last remaining chapter is never removed. */
|
|
1536
1708
|
removeChapter(index: number): void;
|
|
1709
|
+
/** Moves the chapter at `from` to `to`, keeping the same chapter selected. */
|
|
1537
1710
|
reorderChapters(from: number, to: number): void;
|
|
1538
1711
|
/** Last autosave failure, if any. */
|
|
1539
1712
|
autosaveError: Error | null;
|
|
@@ -1558,13 +1731,26 @@ interface UseManuscriptLayoutOptions {
|
|
|
1558
1731
|
/** Debounce window (ms) applied to size-triggered re-flows. @defaultValue 120 */
|
|
1559
1732
|
resizeDebounce?: number;
|
|
1560
1733
|
/**
|
|
1561
|
-
* Capture the
|
|
1562
|
-
*
|
|
1563
|
-
*
|
|
1564
|
-
*
|
|
1565
|
-
* Never called for blank (content-change) re-layouts.
|
|
1734
|
+
* Capture the reading position from the outgoing layout, just before a
|
|
1735
|
+
* **reflow** (non-blank) re-layout replaces it. The anchor is held in
|
|
1736
|
+
* `pendingRestore` until the new layout is in place, then handed to
|
|
1737
|
+
* `restorePosition` when one is given. Return `null` to skip preservation.
|
|
1738
|
+
* Never called for blank (content-change) re-layouts, which start at spread 0.
|
|
1566
1739
|
*/
|
|
1567
1740
|
capturePosition?: (layout: ChapterLayout) => InChapterAnchor | null;
|
|
1741
|
+
/**
|
|
1742
|
+
* Apply an anchor captured by `capturePosition` to the new layout, e.g. by
|
|
1743
|
+
* locating it and jumping to its spread. Called once the new layout is in
|
|
1744
|
+
* place — after it commits, before paint — and `pendingRestore` is cleared
|
|
1745
|
+
* first. Without it, consume `pendingRestore` yourself.
|
|
1746
|
+
*/
|
|
1747
|
+
restorePosition?: (layout: ChapterLayout, position: InChapterAnchor) => void;
|
|
1748
|
+
/**
|
|
1749
|
+
* Called once when a layout of the current source fails, whichever path
|
|
1750
|
+
* started it (source change, resize or `recompute`); a superseded layout
|
|
1751
|
+
* reports nothing. When supplied, `recompute` resolves instead of rejecting.
|
|
1752
|
+
*/
|
|
1753
|
+
onError?: (error: Error) => void;
|
|
1568
1754
|
}
|
|
1569
1755
|
/** Options for {@link UseManuscriptLayoutReturn.recompute}. */
|
|
1570
1756
|
interface ManuscriptRecomputeOptions {
|
|
@@ -1578,8 +1764,11 @@ interface ManuscriptRecomputeOptions {
|
|
|
1578
1764
|
}
|
|
1579
1765
|
/** Page dimensions returned by {@link MejiroBook.computePageSize}. */
|
|
1580
1766
|
interface ManuscriptPageDimensions {
|
|
1767
|
+
/** Width of one page, in CSS pixels. */
|
|
1581
1768
|
pageWidth: number;
|
|
1769
|
+
/** Height of one page, in CSS pixels. */
|
|
1582
1770
|
pageHeight: number;
|
|
1771
|
+
/** Height of the text area inside a page, in CSS pixels. */
|
|
1583
1772
|
contentHeight: number;
|
|
1584
1773
|
}
|
|
1585
1774
|
/** Return value of {@link useManuscriptLayout}. */
|
|
@@ -1594,12 +1783,16 @@ interface UseManuscriptLayoutReturn {
|
|
|
1594
1783
|
contentHeight: number;
|
|
1595
1784
|
/** Most recent layout time (ms). */
|
|
1596
1785
|
elapsedMs: number;
|
|
1597
|
-
/**
|
|
1786
|
+
/**
|
|
1787
|
+
* Force a fresh layout computation. A failure goes to `onError` when one is
|
|
1788
|
+
* supplied; otherwise the returned promise rejects.
|
|
1789
|
+
*/
|
|
1598
1790
|
recompute: (opts?: ManuscriptRecomputeOptions) => Promise<void>;
|
|
1599
1791
|
/**
|
|
1600
|
-
* Anchor captured before the most recent reflow
|
|
1601
|
-
* restoration into the new
|
|
1602
|
-
*
|
|
1792
|
+
* Anchor captured by `capturePosition` before the most recent reflow,
|
|
1793
|
+
* awaiting restoration into the new layout. `restorePosition`, when given,
|
|
1794
|
+
* consumes it; otherwise read it once the new layout is in place and set it
|
|
1795
|
+
* back to `null`.
|
|
1603
1796
|
*/
|
|
1604
1797
|
pendingRestore: MutableRefObject<InChapterAnchor | null>;
|
|
1605
1798
|
}
|
|
@@ -1619,8 +1812,10 @@ interface UseManuscriptLayoutReturn {
|
|
|
1619
1812
|
* is computed (no blank flash) and yields a new {@link ChapterLayout} object,
|
|
1620
1813
|
* which resets any downstream spread index to 0; the reading position is
|
|
1621
1814
|
* preserved across such reflows via
|
|
1622
|
-
* {@link UseManuscriptLayoutOptions.capturePosition}
|
|
1623
|
-
* {@link
|
|
1815
|
+
* {@link UseManuscriptLayoutOptions.capturePosition},
|
|
1816
|
+
* {@link UseManuscriptLayoutOptions.restorePosition} and
|
|
1817
|
+
* {@link UseManuscriptLayoutReturn.pendingRestore}, identically in the Vue
|
|
1818
|
+
* composable.
|
|
1624
1819
|
*/
|
|
1625
1820
|
declare function useManuscriptLayout(book: MejiroBook, chapter: ManuscriptChapter | null, surface: RefObject<HTMLElement | null>, options?: UseManuscriptLayoutOptions): UseManuscriptLayoutReturn;
|
|
1626
1821
|
|
|
@@ -1636,11 +1831,10 @@ interface UseMejiroBookOptions {
|
|
|
1636
1831
|
*/
|
|
1637
1832
|
debounceMs?: number;
|
|
1638
1833
|
/**
|
|
1639
|
-
* Called when applying options to the book fails
|
|
1640
|
-
*
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1643
|
-
* rejection behind.
|
|
1834
|
+
* Called when applying options to the book fails. When supplied, failures are
|
|
1835
|
+
* reported here and the promise returned by
|
|
1836
|
+
* {@link UseMejiroBookReturn.setOptions} resolves instead of rejecting, so
|
|
1837
|
+
* fire-and-forget callers cannot leave an unhandled rejection behind.
|
|
1644
1838
|
*/
|
|
1645
1839
|
onError?: (error: Error) => void;
|
|
1646
1840
|
}
|
|
@@ -1648,7 +1842,10 @@ interface UseMejiroBookOptions {
|
|
|
1648
1842
|
interface UseMejiroBookReturn {
|
|
1649
1843
|
/** The managed {@link MejiroBook} instance. Stable across renders. */
|
|
1650
1844
|
book: MejiroBook;
|
|
1651
|
-
/**
|
|
1845
|
+
/**
|
|
1846
|
+
* Reactive snapshot of the current options. Once the latest application
|
|
1847
|
+
* settles it holds what the book applied, so a rejected change rolls back.
|
|
1848
|
+
*/
|
|
1652
1849
|
options: Readonly<BookOptions>;
|
|
1653
1850
|
/**
|
|
1654
1851
|
* Update options on the underlying book and the snapshot. The snapshot is
|
|
@@ -1667,7 +1864,7 @@ interface UseMejiroBookReturn {
|
|
|
1667
1864
|
* @param initial - Initial book options (passed to the {@link MejiroBook} constructor).
|
|
1668
1865
|
* @param options - Behavior overrides (debouncing, error reporting).
|
|
1669
1866
|
*/
|
|
1670
|
-
declare function useMejiroBook(initial:
|
|
1867
|
+
declare function useMejiroBook(initial: MejiroBookOptions, options?: UseMejiroBookOptions): UseMejiroBookReturn;
|
|
1671
1868
|
|
|
1672
1869
|
/** Minimal storage interface required by {@link useReadingPosition}. */
|
|
1673
1870
|
type ReadingPositionStorage = MejiroStorage;
|
|
@@ -1707,9 +1904,10 @@ interface UseReadingPositionReturn {
|
|
|
1707
1904
|
* const { position, save } = useReadingPosition({ key: `mejiro:${bookId}` });
|
|
1708
1905
|
* const reader = useRef<MejiroReaderHandle>(null);
|
|
1709
1906
|
*
|
|
1907
|
+
* // Restore once per mount: depending on `position` would re-run after every save().
|
|
1710
1908
|
* useEffect(() => {
|
|
1711
1909
|
* if (position) reader.current?.goToAnchor(position);
|
|
1712
|
-
* }, [
|
|
1910
|
+
* }, []);
|
|
1713
1911
|
*
|
|
1714
1912
|
* useEffect(() => {
|
|
1715
1913
|
* const off = reader.current?.subscribe('spreadChanged', () => {
|
|
@@ -1732,33 +1930,53 @@ interface UseSpreadOptions {
|
|
|
1732
1930
|
enableKeyboard?: boolean;
|
|
1733
1931
|
/** Page-turn animation duration in ms. @defaultValue 180 */
|
|
1734
1932
|
turnDuration?: number;
|
|
1933
|
+
/**
|
|
1934
|
+
* Show one page at a time: the navigation index then counts pages instead
|
|
1935
|
+
* of two-page spreads. Toggling it converts the index so the page on
|
|
1936
|
+
* screen stays visible. @defaultValue false
|
|
1937
|
+
*/
|
|
1938
|
+
single?: boolean;
|
|
1735
1939
|
/** Called when the spread index changes (after the turn animation midpoint). */
|
|
1736
1940
|
onChange?: (spreadIdx: number) => void;
|
|
1737
1941
|
}
|
|
1738
1942
|
/** Return value of {@link useSpread}. */
|
|
1739
1943
|
interface UseSpreadReturn {
|
|
1740
|
-
/** Current spread index. */
|
|
1944
|
+
/** Current navigation index: a page index in single mode, a spread index otherwise. */
|
|
1741
1945
|
spreadIdx: number;
|
|
1742
|
-
/**
|
|
1946
|
+
/** Layout spread holding the visible page(s), or `null` until the layout is ready. */
|
|
1743
1947
|
spread: SpreadResult | null;
|
|
1744
|
-
/**
|
|
1948
|
+
/** First page shown, in reading order. */
|
|
1949
|
+
firstPage: number;
|
|
1950
|
+
/** Index of {@link UseSpreadReturn.spread} in the layout (`ChapterLayout.getSpread`). */
|
|
1951
|
+
layoutSpreadIdx: number;
|
|
1952
|
+
/** Side of {@link UseSpreadReturn.spread} shown in single mode; `null` in double mode. */
|
|
1953
|
+
singleSide: 'right' | 'left' | null;
|
|
1954
|
+
/** Total number of pages, as of {@link UseSpreadReturn.spread}. */
|
|
1745
1955
|
totalPages: number;
|
|
1746
|
-
/**
|
|
1956
|
+
/** Number of navigation positions: pages in single mode, two-page spreads otherwise. */
|
|
1747
1957
|
totalSpreads: number;
|
|
1748
1958
|
/** Whether the turn animation is currently in flight. */
|
|
1749
1959
|
turning: boolean;
|
|
1750
|
-
/** Advance one spread forward. */
|
|
1960
|
+
/** Advance one position (page or spread) forward. */
|
|
1751
1961
|
next: () => void;
|
|
1752
|
-
/** Go back one
|
|
1962
|
+
/** Go back one position. */
|
|
1753
1963
|
prev: () => void;
|
|
1754
|
-
/** Jump to an arbitrary
|
|
1964
|
+
/** Jump to an arbitrary navigation index (clamped). */
|
|
1755
1965
|
goTo: (index: number) => void;
|
|
1756
1966
|
/**
|
|
1757
|
-
* Set the
|
|
1758
|
-
* `[0, totalSpreads − 1]`. Use to restore a reading position after a reflow
|
|
1967
|
+
* Set the navigation index immediately, with no page-turn animation, clamped
|
|
1968
|
+
* to `[0, totalSpreads − 1]`. Use to restore a reading position after a reflow
|
|
1759
1969
|
* re-layout (where an animated {@link goTo} would briefly flash spread 0).
|
|
1760
1970
|
*/
|
|
1761
1971
|
setSpread: (index: number) => void;
|
|
1972
|
+
/** Navigation index that shows the given page index. */
|
|
1973
|
+
indexOfPage: (pageIdx: number) => number;
|
|
1974
|
+
/**
|
|
1975
|
+
* Anchor at the start of the text shown at navigation index `index`. A page an
|
|
1976
|
+
* image blocks entirely holds no text, so the anchor then comes from the next
|
|
1977
|
+
* page that does, even past `index`; `null` when no page from there on holds text.
|
|
1978
|
+
*/
|
|
1979
|
+
anchorAt: (index: number) => InChapterAnchor | null;
|
|
1762
1980
|
/** Manually refresh `spread` from `layout` at the current index. */
|
|
1763
1981
|
refresh: () => void;
|
|
1764
1982
|
}
|