@libraz/mejiro-react 0.8.0 → 0.9.1
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 +12 -3
- package/dist/index.d.ts +521 -151
- package/dist/index.js +1973 -1443
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { MejiroLocale, MejiroMessages, EditableSettings, FontChoice, PageHeaderData, MejiroStorage, Annotation, ReadingPositionValue } from '@libraz/mejiro';
|
|
2
|
-
export { Annotation, EditableSettings, FontChoice, MejiroLocale, MejiroMessages, PageHeaderData, ReadingPositionValue, enMessages, jaMessages } from '@libraz/mejiro';
|
|
1
|
+
import { MejiroLocale, MejiroMessages, EditableSettings, FontChoice, ImageOverlayRect, PageHeaderData, MejiroStorage, Annotation, ReadingPositionValue } from '@libraz/mejiro';
|
|
2
|
+
export { Annotation, EditableSettings, FontChoice, ImageOverlayRect, MejiroLocale, MejiroMessages, PageHeaderData, ReadingPositionValue, enMessages, jaMessages } from '@libraz/mejiro';
|
|
3
3
|
import * as react from 'react';
|
|
4
|
-
import { ReactNode, CSSProperties, PointerEvent, TextareaHTMLAttributes, RefObject } from 'react';
|
|
5
|
-
import { EpubBook, AssetResolver, EditableEpub, ManuscriptDialect, EpubChapter, EditableEpubBook, AnnotatedParagraph, AddImageInput, EditableEpubImage, EpubExportOptions, EpubProjectMetadata, EpubProject } from '@libraz/mejiro/epub';
|
|
4
|
+
import { ReactNode, CSSProperties, PointerEvent, TextareaHTMLAttributes, MutableRefObject, RefObject } from 'react';
|
|
5
|
+
import { EpubBook, AssetResolver, EpubParseLimits, EditableEpub, ManuscriptDialect, EpubChapter, EditableEpubBook, EditableEpubSelection, AnnotatedParagraph, AddImageInput, EditableEpubImage, EpubExportOptions, EpubProjectMetadata, EpubProjectAsset, EpubProject } from '@libraz/mejiro/epub';
|
|
6
|
+
export { EditableEpubSelection } from '@libraz/mejiro/epub';
|
|
6
7
|
import { ChapterLayout, SpreadResult, BookOptions, ComputePageSizeOptions, InChapterAnchor, ReadingAnchor, ManuscriptChapter, PageResult, AnchorRect, AnchorRange, MejiroBook } from '@libraz/mejiro/book';
|
|
7
8
|
import { RenderPage } from '@libraz/mejiro/render';
|
|
8
9
|
import { FontFamily, InlineAnnotation } from '@libraz/mejiro/browser';
|
|
@@ -31,6 +32,10 @@ declare function resolveMessages(locale: MejiroLocale | undefined, overrides: Pa
|
|
|
31
32
|
/** Replace `{name}` placeholders in a template. */
|
|
32
33
|
declare function format(template: string, vars: Record<string, string | number>): string;
|
|
33
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
|
+
*/
|
|
34
39
|
type MejiroChapterNavVariant = 'select' | 'panel';
|
|
35
40
|
/** Props for {@link MejiroChapterNav}. */
|
|
36
41
|
interface MejiroChapterNavProps {
|
|
@@ -57,7 +62,7 @@ declare function MejiroChapterNav({ epub, chapter, onChange, variant, }: MejiroC
|
|
|
57
62
|
interface MejiroDropZoneProps {
|
|
58
63
|
/** File `accept` filter for the picker. @defaultValue '.epub' */
|
|
59
64
|
accept?: string;
|
|
60
|
-
/** Validator. Defaults to `
|
|
65
|
+
/** Validator. Defaults to the `accept` filter, with extensions matched case-insensitively. */
|
|
61
66
|
validateFile?: (file: File) => boolean;
|
|
62
67
|
/** Called with the selected/dropped file. */
|
|
63
68
|
onFile: (file: File) => void;
|
|
@@ -69,7 +74,9 @@ interface MejiroDropZoneProps {
|
|
|
69
74
|
style?: CSSProperties;
|
|
70
75
|
}
|
|
71
76
|
/**
|
|
72
|
-
* Drop zone for EPUB files. Combines drag-and-drop with a click-to-open file
|
|
77
|
+
* Drop zone for EPUB files. Combines drag-and-drop with a click-to-open file
|
|
78
|
+
* picker. The root is a real button, so it is reachable with Tab, announced as
|
|
79
|
+
* a control by screen readers, and opens the picker on Enter / Space.
|
|
73
80
|
*/
|
|
74
81
|
declare function MejiroDropZone({ accept, validateFile, onFile, children, className, style, }: MejiroDropZoneProps): ReactNode;
|
|
75
82
|
|
|
@@ -93,6 +100,7 @@ interface MejiroSettingsPanelProps {
|
|
|
93
100
|
*/
|
|
94
101
|
declare function MejiroSettingsPanel({ open, settings, onChange, fonts, minFontSize, maxFontSize, }: MejiroSettingsPanelProps): ReactNode;
|
|
95
102
|
|
|
103
|
+
/** Props for {@link MejiroEditor}. */
|
|
96
104
|
interface MejiroEditorProps {
|
|
97
105
|
/** URL fetched and loaded on mount. */
|
|
98
106
|
epubUrl?: string;
|
|
@@ -139,18 +147,27 @@ interface MejiroEditorProps {
|
|
|
139
147
|
* custom auth headers.
|
|
140
148
|
*/
|
|
141
149
|
assetResolver?: AssetResolver;
|
|
150
|
+
/**
|
|
151
|
+
* Archive resource limits applied while opening an EPUB. Raise them for
|
|
152
|
+
* trusted, image-heavy books; tighten them for a public drop zone. Omitted
|
|
153
|
+
* fields keep their `DEFAULT_EPUB_PARSE_LIMITS` value.
|
|
154
|
+
*/
|
|
155
|
+
limits?: Partial<EpubParseLimits>;
|
|
142
156
|
/** Called after an EPUB is loaded into the editor. */
|
|
143
157
|
onLoad?: (editor: EditableEpub) => void;
|
|
144
158
|
/** Called after export completes. */
|
|
145
159
|
onExport?: (buffer: ArrayBuffer) => void;
|
|
146
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* Called when loading, image insertion or export fails. The error is also
|
|
162
|
+
* shown in the editor.
|
|
163
|
+
*/
|
|
147
164
|
onError?: (error: Error) => void;
|
|
148
165
|
}
|
|
149
166
|
/**
|
|
150
167
|
* Declarative restrictions on the export pipeline. Mejiro applies the
|
|
151
|
-
* transforms in this order: `watermark` (
|
|
152
|
-
* `encrypt` (replaces the buffer with the
|
|
153
|
-
* the browser download when `false`).
|
|
168
|
+
* transforms in this order: `watermark` (applied to an export-only copy of the
|
|
169
|
+
* book, never to the edited document) → `encrypt` (replaces the buffer with the
|
|
170
|
+
* result) → `allowDownload` (skips the browser download when `false`).
|
|
154
171
|
*/
|
|
155
172
|
interface MejiroExportPolicy {
|
|
156
173
|
/**
|
|
@@ -166,24 +183,27 @@ interface MejiroExportPolicy {
|
|
|
166
183
|
*/
|
|
167
184
|
encrypt?: (buffer: ArrayBuffer) => ArrayBuffer | Promise<ArrayBuffer>;
|
|
168
185
|
/**
|
|
169
|
-
* Embeds a visible watermark string into the EPUB. Implemented
|
|
170
|
-
*
|
|
186
|
+
* Embeds a visible watermark string into the exported EPUB. Implemented as a
|
|
187
|
+
* paragraph block prefixed with `[mejiro-watermark]` at the top of every
|
|
188
|
+
* chapter, so a downstream renderer can theme it by that prefix. The block
|
|
189
|
+
* only exists in the exported file — the edited document is unchanged.
|
|
171
190
|
*/
|
|
172
191
|
watermark?: {
|
|
173
192
|
text: string;
|
|
174
|
-
opacity?: number;
|
|
175
193
|
};
|
|
176
194
|
}
|
|
177
195
|
/** EPUB editor UI for proofreading, ruby edits, image insertion, and export. */
|
|
178
|
-
declare function MejiroEditor({ epubUrl, fonts, enableProofread, enableRuby, enableImages, enableExport, onBeforeExport, exportPolicy, assetResolver, onLoad, onExport, onError, }: MejiroEditorProps): ReactNode;
|
|
196
|
+
declare function MejiroEditor({ epubUrl, fonts, enableProofread, enableRuby, enableImages, enableExport, onBeforeExport, exportPolicy, assetResolver, limits, onLoad, onExport, onError, }: MejiroEditorProps): ReactNode;
|
|
179
197
|
|
|
180
|
-
/**
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Rectangle describing an image overlay position and size.
|
|
200
|
+
*
|
|
201
|
+
* @deprecated Alias of {@link ImageOverlayRect}, which is the single name for
|
|
202
|
+
* this shape across the package family. The core package exports an unrelated
|
|
203
|
+
* `ImageRect` (an exclusion rectangle, with margin fields), so the two names
|
|
204
|
+
* collide when both packages are imported into one module.
|
|
205
|
+
*/
|
|
206
|
+
type ImageRect = ImageOverlayRect;
|
|
187
207
|
/** Options for {@link useImageOverlay}. */
|
|
188
208
|
interface UseImageOverlayOptions {
|
|
189
209
|
/** Default image width in pixels. @defaultValue 120 */
|
|
@@ -200,7 +220,7 @@ interface UseImageOverlayOptions {
|
|
|
200
220
|
/** Return value of {@link useImageOverlay}. */
|
|
201
221
|
interface UseImageOverlayReturn {
|
|
202
222
|
/** Current image rectangle, or `null` if no overlay is active. */
|
|
203
|
-
imageRect:
|
|
223
|
+
imageRect: ImageOverlayRect | null;
|
|
204
224
|
/** Whether an image overlay is currently active. */
|
|
205
225
|
hasImage: boolean;
|
|
206
226
|
/** Toggle the image overlay on/off. */
|
|
@@ -214,6 +234,11 @@ interface UseImageOverlayReturn {
|
|
|
214
234
|
* React hook that manages a draggable/resizable image overlay
|
|
215
235
|
* with automatic text reflow via {@link ChapterLayout.syncImages}.
|
|
216
236
|
*
|
|
237
|
+
* While an overlay is active the exclusion is re-issued whenever `layout` is
|
|
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.
|
|
241
|
+
*
|
|
217
242
|
* @param layout - Current chapter layout (or `null` if not yet loaded).
|
|
218
243
|
* @param spreadIdx - Current spread index.
|
|
219
244
|
* @param onUpdate - Called with the updated {@link SpreadResult} after every reflow.
|
|
@@ -246,6 +271,10 @@ interface MejiroImageOverlayProps {
|
|
|
246
271
|
*/
|
|
247
272
|
declare function MejiroImageOverlay({ rect, label, onOverlayPointerDown, onResizePointerDown, onClose, }: MejiroImageOverlayProps): ReactNode;
|
|
248
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Where {@link MejiroReader} places its chapter navigation: the header
|
|
276
|
+
* dropdown (`'select'`), the side chapter list (`'panel'`), both, or neither.
|
|
277
|
+
*/
|
|
249
278
|
type MejiroChapterNavMode = 'select' | 'panel' | 'both' | 'none';
|
|
250
279
|
/**
|
|
251
280
|
* Reading-flow mode for {@link MejiroReader}.
|
|
@@ -256,8 +285,9 @@ type MejiroReaderMode = 'paginated' | 'scroll';
|
|
|
256
285
|
/**
|
|
257
286
|
* Two-page vs single-page rendering of a spread.
|
|
258
287
|
* - `double` — always render two pages (default).
|
|
259
|
-
* - `single` — render
|
|
260
|
-
* - `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.
|
|
261
291
|
*/
|
|
262
292
|
type MejiroSpreadMode = 'double' | 'single' | 'auto';
|
|
263
293
|
/**
|
|
@@ -289,9 +319,13 @@ type MejiroTheme = MejiroThemeName | {
|
|
|
289
319
|
};
|
|
290
320
|
/** Reading position exposed by {@link MejiroReaderHandle.getReadingPosition}. */
|
|
291
321
|
interface ReadingPosition {
|
|
322
|
+
/** Zero-based index of the current chapter. */
|
|
292
323
|
chapter: number;
|
|
324
|
+
/** Zero-based index of the current spread within the chapter. */
|
|
293
325
|
spreadIdx: number;
|
|
326
|
+
/** Number of pages in the current chapter's layout. */
|
|
294
327
|
totalPages: number;
|
|
328
|
+
/** Number of spreads in the current chapter's layout. */
|
|
295
329
|
totalSpreads: number;
|
|
296
330
|
}
|
|
297
331
|
/**
|
|
@@ -341,14 +375,16 @@ interface MejiroReaderHandle {
|
|
|
341
375
|
*/
|
|
342
376
|
goToAnchor(anchor: ReadingAnchor): Promise<void>;
|
|
343
377
|
/**
|
|
344
|
-
* Returns the {@link ReadingAnchor} at the start of the current
|
|
345
|
-
* or `null` if the layout is not ready.
|
|
378
|
+
* Returns the {@link ReadingAnchor} at the start of the text on the current
|
|
379
|
+
* spread, or `null` if the layout is not ready. When an image blocks every
|
|
380
|
+
* page of the spread, the anchor is where the text resumes after it; `null`
|
|
381
|
+
* again if none follows.
|
|
346
382
|
*/
|
|
347
383
|
getAnchor(): ReadingAnchor | null;
|
|
348
384
|
/**
|
|
349
385
|
* Returns the half-open range of {@link ReadingAnchor}s visible on the
|
|
350
|
-
* current spread. `end` points at the start of the
|
|
351
|
-
* of the chapter
|
|
386
|
+
* current spread. `end` points at the start of the text on the next spread
|
|
387
|
+
* that has any (or the end of the chapter when none does).
|
|
352
388
|
*/
|
|
353
389
|
getVisibleRange(): {
|
|
354
390
|
start: ReadingAnchor;
|
|
@@ -357,6 +393,12 @@ interface MejiroReaderHandle {
|
|
|
357
393
|
/**
|
|
358
394
|
* Updates book options at runtime. Same shape as {@link MejiroBook.setOptions}
|
|
359
395
|
* — font / size changes re-measure and re-layout asynchronously.
|
|
396
|
+
*
|
|
397
|
+
* Successive calls are coalesced into a single application; the returned
|
|
398
|
+
* promise resolves once that application has settled. A failed application
|
|
399
|
+
* (such as a font that measures as a fallback under `strictFontCheck`) is
|
|
400
|
+
* reported through {@link MejiroReaderProps.onError} rather than rejecting
|
|
401
|
+
* the promise.
|
|
360
402
|
*/
|
|
361
403
|
setOptions(partial: Partial<BookOptions>): Promise<void>;
|
|
362
404
|
/**
|
|
@@ -413,7 +455,9 @@ interface MejiroReaderCommonProps {
|
|
|
413
455
|
/**
|
|
414
456
|
* Controlled spread index. When supplied, the reader is driven by this
|
|
415
457
|
* value and emits {@link MejiroReaderProps.onSpreadIdxChange} on user
|
|
416
|
-
* navigation.
|
|
458
|
+
* navigation. A spread index does not survive reflow, so persist the
|
|
459
|
+
* reading position with `useReadingPosition` and the handle's
|
|
460
|
+
* `getAnchor` / `goToAnchor` instead.
|
|
417
461
|
*/
|
|
418
462
|
spreadIdx?: number;
|
|
419
463
|
/**
|
|
@@ -430,8 +474,10 @@ interface MejiroReaderCommonProps {
|
|
|
430
474
|
*/
|
|
431
475
|
mode?: MejiroReaderMode;
|
|
432
476
|
/**
|
|
433
|
-
* Spread layout. `double` (default) renders two pages; `single` renders
|
|
434
|
-
*
|
|
477
|
+
* Spread layout. `double` (default) renders two pages; `single` renders one
|
|
478
|
+
* page at a time, and `spreadIdx`, `goToSpread`, `onSpreadIdxChange` and
|
|
479
|
+
* `spreadChanged` then count pages; `auto` flips to `single` for portrait
|
|
480
|
+
* viewports, keeping the page on screen visible.
|
|
435
481
|
*/
|
|
436
482
|
spreadMode?: MejiroSpreadMode;
|
|
437
483
|
/**
|
|
@@ -462,6 +508,13 @@ interface MejiroReaderCommonProps {
|
|
|
462
508
|
* sending bearer tokens or cookies.
|
|
463
509
|
*/
|
|
464
510
|
fetchOptions?: RequestInit;
|
|
511
|
+
/**
|
|
512
|
+
* Resource limits applied while parsing an EPUB the reader loads itself
|
|
513
|
+
* (URL mode and the drop zone / file picker). Untrusted files reach this
|
|
514
|
+
* component directly, so hosts that accept them should tighten the
|
|
515
|
+
* defaults here.
|
|
516
|
+
*/
|
|
517
|
+
limits?: Partial<EpubParseLimits>;
|
|
465
518
|
/**
|
|
466
519
|
* Custom EPUB fetcher used in place of the global `fetch`. Overrides
|
|
467
520
|
* {@link fetchOptions} when set.
|
|
@@ -542,9 +595,10 @@ interface MejiroReaderCommonProps {
|
|
|
542
595
|
/**
|
|
543
596
|
* Reader-side annotations to render as highlights. Each annotation whose
|
|
544
597
|
* `chapter` matches the current chapter is converted to spread-local
|
|
545
|
-
* rectangles via `ChapterLayout.selectionRects
|
|
546
|
-
*
|
|
547
|
-
*
|
|
598
|
+
* rectangles via `ChapterLayout.selectionRects`; the rectangles landing on
|
|
599
|
+
* the spread on screen are drawn on top of the page content. Pair with
|
|
600
|
+
* {@link useAnnotations} for persistence, or pass any shape that satisfies
|
|
601
|
+
* `{ chapter, start, end }`.
|
|
548
602
|
*/
|
|
549
603
|
annotations?: ReadonlyArray<{
|
|
550
604
|
chapter: number;
|
|
@@ -554,7 +608,11 @@ interface MejiroReaderCommonProps {
|
|
|
554
608
|
}>;
|
|
555
609
|
/** Called after a successful EPUB load. */
|
|
556
610
|
onLoad?: (book: EpubBook) => void;
|
|
557
|
-
/**
|
|
611
|
+
/**
|
|
612
|
+
* Called when loading or parsing an EPUB fails, and when applying an option
|
|
613
|
+
* change fails (such as a font that measures as a fallback under
|
|
614
|
+
* `strictFontCheck`; without it, a font that fails to load is not an error).
|
|
615
|
+
*/
|
|
558
616
|
onError?: (error: Error) => void;
|
|
559
617
|
/** Called when the chapter index changes. */
|
|
560
618
|
onChapterChange?: (chapter: number) => void;
|
|
@@ -623,18 +681,31 @@ interface MejiroReaderManuscriptProps extends MejiroReaderCommonProps {
|
|
|
623
681
|
* modes — TypeScript prevents passing more than one source at once.
|
|
624
682
|
*/
|
|
625
683
|
type MejiroReaderProps = MejiroReaderControlledProps | MejiroReaderUrlProps | MejiroReaderFileProps | MejiroReaderManuscriptProps;
|
|
684
|
+
/**
|
|
685
|
+
* Full-page EPUB reader. Composes the package's primitives into a working
|
|
686
|
+
* reader; features opt out via the `enableX` props or all chrome via `bare`.
|
|
687
|
+
* The `ref` exposes {@link MejiroReaderHandle} for imperative navigation.
|
|
688
|
+
*/
|
|
626
689
|
declare const MejiroReader: react.ForwardRefExoticComponent<MejiroReaderProps & react.RefAttributes<MejiroReaderHandle>>;
|
|
627
690
|
|
|
691
|
+
/** One chapter of the manuscript being edited. */
|
|
628
692
|
interface ManuscriptEditorChapter {
|
|
693
|
+
/** Stable identifier; survives reordering and title edits. */
|
|
629
694
|
id: string;
|
|
695
|
+
/** Chapter title; an empty title falls back to the localized "untitled" label. */
|
|
630
696
|
title: string;
|
|
697
|
+
/** Chapter body in the editor's manuscript notation. */
|
|
631
698
|
body: string;
|
|
632
699
|
}
|
|
633
700
|
/** Autosave payload emitted by {@link MejiroManuscriptEditor}. */
|
|
634
701
|
interface ManuscriptAutosaveDraft {
|
|
702
|
+
/** Book title as currently entered. */
|
|
635
703
|
title: string;
|
|
704
|
+
/** Author name as currently entered. */
|
|
636
705
|
author: string;
|
|
706
|
+
/** Selected cover image, or `null` when none is set. */
|
|
637
707
|
cover: File | null;
|
|
708
|
+
/** Chapters in reading order, as plain (non-reactive) copies. */
|
|
638
709
|
chapters: ManuscriptEditorChapter[];
|
|
639
710
|
}
|
|
640
711
|
/**
|
|
@@ -644,14 +715,23 @@ interface ManuscriptAutosaveDraft {
|
|
|
644
715
|
* supplied here.
|
|
645
716
|
*/
|
|
646
717
|
interface ManuscriptPreviewProps {
|
|
718
|
+
/** Header subtitle of the preview reader. */
|
|
647
719
|
subtitle?: string;
|
|
720
|
+
/** Header title of the preview reader. */
|
|
648
721
|
title?: string;
|
|
722
|
+
/** Where the preview places its chapter navigation. @defaultValue 'panel' */
|
|
649
723
|
chapterNavMode?: 'select' | 'panel' | 'both' | 'none';
|
|
724
|
+
/** Show the preview header. */
|
|
650
725
|
enableHeader?: boolean;
|
|
726
|
+
/** Show the preview chapter navigation. */
|
|
651
727
|
enableChapterNav?: boolean;
|
|
728
|
+
/** Show the preview settings panel toggle. */
|
|
652
729
|
enableSettings?: boolean;
|
|
730
|
+
/** Show the preview layout statistics. */
|
|
653
731
|
enableStats?: boolean;
|
|
732
|
+
/** Enable arrow-key page turns in the preview. */
|
|
654
733
|
enableKeyboard?: boolean;
|
|
734
|
+
/** Show the preview page indicator. */
|
|
655
735
|
enablePageIndicator?: boolean;
|
|
656
736
|
/** Book options forwarded to the embedded reader preview. */
|
|
657
737
|
options?: Partial<BookOptions>;
|
|
@@ -666,8 +746,10 @@ interface ManuscriptPreviewProps {
|
|
|
666
746
|
* to `true` to demo the fullscreen-reader behavior.
|
|
667
747
|
*/
|
|
668
748
|
enableSurfaceTap?: boolean;
|
|
749
|
+
/** Render the preview without any reader chrome. */
|
|
669
750
|
bare?: boolean;
|
|
670
751
|
}
|
|
752
|
+
/** Props for {@link MejiroManuscriptEditor}. */
|
|
671
753
|
interface MejiroManuscriptEditorProps {
|
|
672
754
|
/** Font choices passed to the preview reader. */
|
|
673
755
|
fonts?: FontChoice[];
|
|
@@ -695,6 +777,12 @@ interface MejiroManuscriptEditorProps {
|
|
|
695
777
|
onCoverChange?: (cover: File | null) => void;
|
|
696
778
|
/** Initial chapters. */
|
|
697
779
|
chapters?: ManuscriptEditorChapter[];
|
|
780
|
+
/**
|
|
781
|
+
* Manuscript notation dialect. Drives the notation highlighter, the live
|
|
782
|
+
* preview, and the exported EPUB alike, so the whole editor interprets one
|
|
783
|
+
* dialect. @defaultValue `'mejiro'`
|
|
784
|
+
*/
|
|
785
|
+
dialect?: ManuscriptDialect;
|
|
698
786
|
/**
|
|
699
787
|
* Called whenever the chapter draft settles (debounced by
|
|
700
788
|
* {@link MejiroManuscriptEditorProps.autosaveDelay}). Use to persist drafts
|
|
@@ -710,17 +798,30 @@ interface MejiroManuscriptEditorProps {
|
|
|
710
798
|
*/
|
|
711
799
|
previewProps?: ManuscriptPreviewProps;
|
|
712
800
|
/**
|
|
713
|
-
*
|
|
714
|
-
* `
|
|
715
|
-
* so
|
|
716
|
-
*
|
|
801
|
+
* Resolver for URL-only assets, forwarded to `project.export()`. This editor
|
|
802
|
+
* owns a `File` cover and manuscript text only, and embeds the cover bytes
|
|
803
|
+
* itself, so nothing it registers is URL-only — build the project through
|
|
804
|
+
* `useEpubProject` (`setCover` / `setAssets`) to author `{ url }` asset
|
|
805
|
+
* references that must be fetched at export time.
|
|
717
806
|
*/
|
|
718
807
|
assetResolver?: AssetResolver;
|
|
719
808
|
/** Called after export completes. */
|
|
720
809
|
onExport?: (buffer: ArrayBuffer) => void;
|
|
810
|
+
/**
|
|
811
|
+
* Called when the EPUB export fails (asset resolution, cover reading, or
|
|
812
|
+
* packaging). The same error is shown in the editor panel, so hosts only
|
|
813
|
+
* need this to log or report it.
|
|
814
|
+
*/
|
|
815
|
+
onError?: (error: Error) => void;
|
|
816
|
+
/**
|
|
817
|
+
* Which side of the editor the manuscript panel sits on. `'right'` (the
|
|
818
|
+
* default) puts the preview on the left; `'left'` mirrors the layout.
|
|
819
|
+
* @defaultValue 'right'
|
|
820
|
+
*/
|
|
821
|
+
panelSide?: 'left' | 'right';
|
|
721
822
|
}
|
|
722
823
|
/** Manuscript-to-EPUB editor for author drafts from posting sites. */
|
|
723
|
-
declare function MejiroManuscriptEditor({ fonts, title: titleProp, onTitleChange, author: authorProp, onAuthorChange, cover: coverProp, onCoverChange, chapters: initialChapters, onAutosave, autosaveDelay, previewProps, assetResolver, onExport, }: MejiroManuscriptEditorProps): ReactNode;
|
|
824
|
+
declare function MejiroManuscriptEditor({ fonts, title: titleProp, onTitleChange, author: authorProp, onAuthorChange, cover: coverProp, onCoverChange, chapters: initialChapters, dialect, onAutosave, autosaveDelay, previewProps, assetResolver, onExport, onError, panelSide, }: MejiroManuscriptEditorProps): ReactNode;
|
|
724
825
|
|
|
725
826
|
/** Props for {@link MejiroNotationHighlighter}. */
|
|
726
827
|
interface MejiroNotationHighlighterProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'onChange'> {
|
|
@@ -809,6 +910,60 @@ interface MejiroPageViewProps {
|
|
|
809
910
|
*/
|
|
810
911
|
declare function MejiroPageView({ result, fontFamily, lineSpacing, slotMode, className, style, }: MejiroPageViewProps): ReactNode;
|
|
811
912
|
|
|
913
|
+
/** A single image overlay placed on a specific spread. */
|
|
914
|
+
interface MultiImageItem {
|
|
915
|
+
/** Stable ID for the overlay (auto-assigned on add). */
|
|
916
|
+
id: string;
|
|
917
|
+
/** Position and size in pixels, relative to the right page. */
|
|
918
|
+
rect: ImageRect;
|
|
919
|
+
}
|
|
920
|
+
/** Options for {@link useMultiImageOverlay}. */
|
|
921
|
+
interface UseMultiImageOverlayOptions {
|
|
922
|
+
/** Default image width. @defaultValue 120 */
|
|
923
|
+
defaultWidth?: number;
|
|
924
|
+
/** Default image height. @defaultValue 160 */
|
|
925
|
+
defaultHeight?: number;
|
|
926
|
+
/** Default x. @defaultValue 80 */
|
|
927
|
+
defaultX?: number;
|
|
928
|
+
/** Default y. @defaultValue 100 */
|
|
929
|
+
defaultY?: number;
|
|
930
|
+
/** Margin around each image, in pixels. Defaults to the book's font size. */
|
|
931
|
+
margin?: number;
|
|
932
|
+
/** Called after every reflow caused by adding/removing/moving an image. */
|
|
933
|
+
onUpdate?: (spread: SpreadResult) => void;
|
|
934
|
+
}
|
|
935
|
+
/** Return value of {@link useMultiImageOverlay}. */
|
|
936
|
+
interface UseMultiImageOverlayReturn {
|
|
937
|
+
/**
|
|
938
|
+
* Map of all images keyed by spread index. A new map whenever the images or
|
|
939
|
+
* the margin they are applied with change, and a replacement layout has them
|
|
940
|
+
* before any view renders from it, so this map and the layout together key
|
|
941
|
+
* anything derived from the layout.
|
|
942
|
+
*/
|
|
943
|
+
imagesBySpread: Map<number, MultiImageItem[]>;
|
|
944
|
+
/** Images on the current spread; a new array whenever `imagesBySpread` changes. */
|
|
945
|
+
currentImages: MultiImageItem[];
|
|
946
|
+
/** Whether any spread has at least one image. */
|
|
947
|
+
hasImages: boolean;
|
|
948
|
+
/** Add a new image on the current spread. */
|
|
949
|
+
addImage: (overrides?: Partial<ImageRect>) => MultiImageItem;
|
|
950
|
+
/** Remove the image with the given id. */
|
|
951
|
+
removeImage: (id: string) => void;
|
|
952
|
+
/** Replace an image's rectangle. */
|
|
953
|
+
updateImage: (id: string, rect: Partial<ImageRect>) => void;
|
|
954
|
+
/** Remove every image (or only those on `spreadIdx` if given). */
|
|
955
|
+
clearImages: (spreadIdx?: number) => void;
|
|
956
|
+
/** Pointer-down handler for the overlay body (drag). */
|
|
957
|
+
onOverlayPointerDown: (id: string, e: PointerEvent) => void;
|
|
958
|
+
/** Pointer-down handler for the resize handle. */
|
|
959
|
+
onResizePointerDown: (id: string, e: PointerEvent) => void;
|
|
960
|
+
}
|
|
961
|
+
/**
|
|
962
|
+
* React hook that manages multiple draggable/resizable image overlays
|
|
963
|
+
* per spread with automatic reflow via {@link ChapterLayout.setImages}.
|
|
964
|
+
*/
|
|
965
|
+
declare function useMultiImageOverlay(layout: ChapterLayout | null, spreadIdx: number, options?: UseMultiImageOverlayOptions): UseMultiImageOverlayReturn;
|
|
966
|
+
|
|
812
967
|
/** Props for {@link MejiroScrollView}. */
|
|
813
968
|
interface MejiroScrollViewProps {
|
|
814
969
|
/** Layout containing the pages to render. */
|
|
@@ -839,6 +994,31 @@ interface MejiroScrollViewProps {
|
|
|
839
994
|
scrollToPage?: number;
|
|
840
995
|
/** Vertical gap between pages (px). @defaultValue 24 */
|
|
841
996
|
pageGap?: number;
|
|
997
|
+
/**
|
|
998
|
+
* Selection rectangles to highlight. Compute via
|
|
999
|
+
* {@link ChapterLayout.selectionRects}; each entry is painted on the page its
|
|
1000
|
+
* `pageIdx` addresses. An entry may carry a `color` fill.
|
|
1001
|
+
*/
|
|
1002
|
+
selectionRects?: readonly (AnchorRect & {
|
|
1003
|
+
color?: string;
|
|
1004
|
+
})[];
|
|
1005
|
+
/** Zero-based spread whose pages carry {@link MejiroScrollViewProps.images}. */
|
|
1006
|
+
spreadIdx?: number;
|
|
1007
|
+
/**
|
|
1008
|
+
* Image overlays on the spread at {@link MejiroScrollViewProps.spreadIdx}.
|
|
1009
|
+
* Each renders on the page whose area contains its centre (see
|
|
1010
|
+
* `overlayPageSide`), matching {@link MejiroSpread}'s single-page routing.
|
|
1011
|
+
* The layout reflows in place when its images change, so a new array here is
|
|
1012
|
+
* also what re-reads the pages; `useMultiImageOverlay`'s `currentImages`
|
|
1013
|
+
* provides one on every change.
|
|
1014
|
+
*/
|
|
1015
|
+
images?: MultiImageItem[];
|
|
1016
|
+
/** Pointer-down on an image overlay. */
|
|
1017
|
+
onImagePointerDown?: (id: string, e: PointerEvent) => void;
|
|
1018
|
+
/** Pointer-down on an image resize handle. */
|
|
1019
|
+
onImageResizePointerDown?: (id: string, e: PointerEvent) => void;
|
|
1020
|
+
/** Image overlay close button. */
|
|
1021
|
+
onImageClose?: (id: string) => void;
|
|
842
1022
|
}
|
|
843
1023
|
/**
|
|
844
1024
|
* Continuous-scroll variant of {@link MejiroSpread}. Stacks every page in
|
|
@@ -846,7 +1026,7 @@ interface MejiroScrollViewProps {
|
|
|
846
1026
|
* detected via `IntersectionObserver` and reported through
|
|
847
1027
|
* {@link MejiroScrollViewProps.onVisiblePageChange}.
|
|
848
1028
|
*/
|
|
849
|
-
declare function MejiroScrollView({ layout, pageWidth, pageHeight, contentHeight, fontFamily, fontSize, lineSpacing, onVisiblePageChange, scrollToPage, pageGap, }: MejiroScrollViewProps): ReactNode;
|
|
1029
|
+
declare function MejiroScrollView({ layout, pageWidth, pageHeight, contentHeight, fontFamily, fontSize, lineSpacing, slotMode, onVisiblePageChange, scrollToPage, pageGap, selectionRects, spreadIdx, images, onImagePointerDown, onImageResizePointerDown, onImageClose, }: MejiroScrollViewProps): ReactNode;
|
|
850
1030
|
|
|
851
1031
|
/** Props for {@link MejiroSelectionLayer}. */
|
|
852
1032
|
interface MejiroSelectionLayerProps {
|
|
@@ -854,8 +1034,14 @@ interface MejiroSelectionLayerProps {
|
|
|
854
1034
|
* Spread-local rectangles to highlight. Compute these via
|
|
855
1035
|
* {@link ChapterLayout.selectionRects} and pass the full array; the layer
|
|
856
1036
|
* picks the entries matching {@link MejiroSelectionLayerProps.side}.
|
|
1037
|
+
*
|
|
1038
|
+
* A rectangle may carry its own `color`, which becomes that rectangle's
|
|
1039
|
+
* fill. Entries without one take the fill from the shipped stylesheet
|
|
1040
|
+
* (`.mejiro-selection-rect`, themeable via `--mejiro-selection-bg`).
|
|
857
1041
|
*/
|
|
858
|
-
rects: readonly AnchorRect
|
|
1042
|
+
rects: readonly (AnchorRect & {
|
|
1043
|
+
color?: string;
|
|
1044
|
+
})[];
|
|
859
1045
|
/** Which page-side this layer is rendered into. */
|
|
860
1046
|
side: 'right' | 'left';
|
|
861
1047
|
/** Optional class added to the outer wrapper. */
|
|
@@ -864,7 +1050,7 @@ interface MejiroSelectionLayerProps {
|
|
|
864
1050
|
style?: CSSProperties;
|
|
865
1051
|
/** Optional class for each rectangle (defaults to `mejiro-selection-rect`). */
|
|
866
1052
|
rectClassName?: string;
|
|
867
|
-
/** Optional inline style for each rectangle. */
|
|
1053
|
+
/** Optional inline style for each rectangle. Takes precedence over `color`. */
|
|
868
1054
|
rectStyle?: CSSProperties;
|
|
869
1055
|
}
|
|
870
1056
|
/**
|
|
@@ -928,7 +1114,7 @@ interface MejiroShelfProps<T = unknown> {
|
|
|
928
1114
|
currentId?: string;
|
|
929
1115
|
/** Called when the user picks a volume. */
|
|
930
1116
|
onSelect?: (volume: VolumeInfo<T>) => void;
|
|
931
|
-
/** Heading shown above the grid.
|
|
1117
|
+
/** Heading shown above the grid. Defaults to the active message catalog's `shelfTitle`. */
|
|
932
1118
|
title?: string;
|
|
933
1119
|
}
|
|
934
1120
|
/**
|
|
@@ -937,55 +1123,6 @@ interface MejiroShelfProps<T = unknown> {
|
|
|
937
1123
|
*/
|
|
938
1124
|
declare function MejiroShelf<T = unknown>({ volumes, currentId, onSelect, title, }: MejiroShelfProps<T>): ReactNode;
|
|
939
1125
|
|
|
940
|
-
/** A single image overlay placed on a specific spread. */
|
|
941
|
-
interface MultiImageItem {
|
|
942
|
-
/** Stable ID for the overlay (auto-assigned on add). */
|
|
943
|
-
id: string;
|
|
944
|
-
/** Position and size in pixels, relative to the right page. */
|
|
945
|
-
rect: ImageRect;
|
|
946
|
-
}
|
|
947
|
-
/** Options for {@link useMultiImageOverlay}. */
|
|
948
|
-
interface UseMultiImageOverlayOptions {
|
|
949
|
-
/** Default image width. @defaultValue 120 */
|
|
950
|
-
defaultWidth?: number;
|
|
951
|
-
/** Default image height. @defaultValue 160 */
|
|
952
|
-
defaultHeight?: number;
|
|
953
|
-
/** Default x. @defaultValue 80 */
|
|
954
|
-
defaultX?: number;
|
|
955
|
-
/** Default y. @defaultValue 100 */
|
|
956
|
-
defaultY?: number;
|
|
957
|
-
/** Margin around each image, in pixels. Defaults to the book's font size. */
|
|
958
|
-
margin?: number;
|
|
959
|
-
/** Called after every reflow caused by adding/removing/moving an image. */
|
|
960
|
-
onUpdate?: (spread: SpreadResult) => void;
|
|
961
|
-
}
|
|
962
|
-
/** Return value of {@link useMultiImageOverlay}. */
|
|
963
|
-
interface UseMultiImageOverlayReturn {
|
|
964
|
-
/** Map of all images keyed by spread index. */
|
|
965
|
-
imagesBySpread: Map<number, MultiImageItem[]>;
|
|
966
|
-
/** Images on the current spread. */
|
|
967
|
-
currentImages: MultiImageItem[];
|
|
968
|
-
/** Whether any spread has at least one image. */
|
|
969
|
-
hasImages: boolean;
|
|
970
|
-
/** Add a new image on the current spread. */
|
|
971
|
-
addImage: (overrides?: Partial<ImageRect>) => MultiImageItem;
|
|
972
|
-
/** Remove the image with the given id. */
|
|
973
|
-
removeImage: (id: string) => void;
|
|
974
|
-
/** Replace an image's rectangle. */
|
|
975
|
-
updateImage: (id: string, rect: Partial<ImageRect>) => void;
|
|
976
|
-
/** Remove every image (or only those on `spreadIdx` if given). */
|
|
977
|
-
clearImages: (spreadIdx?: number) => void;
|
|
978
|
-
/** Pointer-down handler for the overlay body (drag). */
|
|
979
|
-
onOverlayPointerDown: (id: string, e: PointerEvent) => void;
|
|
980
|
-
/** Pointer-down handler for the resize handle. */
|
|
981
|
-
onResizePointerDown: (id: string, e: PointerEvent) => void;
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* React hook that manages multiple draggable/resizable image overlays
|
|
985
|
-
* per spread with automatic reflow via {@link ChapterLayout.setImages}.
|
|
986
|
-
*/
|
|
987
|
-
declare function useMultiImageOverlay(layout: ChapterLayout | null, spreadIdx: number, options?: UseMultiImageOverlayOptions): UseMultiImageOverlayReturn;
|
|
988
|
-
|
|
989
1126
|
/** Props for {@link MejiroSpread}. */
|
|
990
1127
|
interface MejiroSpreadProps {
|
|
991
1128
|
/** Spread data to render. */
|
|
@@ -1008,9 +1145,17 @@ interface MejiroSpreadProps {
|
|
|
1008
1145
|
rightHeader?: PageHeaderData;
|
|
1009
1146
|
/** Header data for the left page. */
|
|
1010
1147
|
leftHeader?: PageHeaderData;
|
|
1011
|
-
/**
|
|
1148
|
+
/**
|
|
1149
|
+
* Image overlays on the current spread, relative to the right page. With
|
|
1150
|
+
* {@link MejiroSpreadProps.singlePage}, only those whose centre lies on the
|
|
1151
|
+
* page shown are drawn.
|
|
1152
|
+
*/
|
|
1012
1153
|
images?: MultiImageItem[];
|
|
1013
|
-
/**
|
|
1154
|
+
/**
|
|
1155
|
+
* Force slot-mode rendering on both pages. When omitted, each page falls
|
|
1156
|
+
* through to {@link MejiroPageView}'s automatic choice: slot mode for pages
|
|
1157
|
+
* with images, native `writing-mode: vertical-rl` otherwise.
|
|
1158
|
+
*/
|
|
1014
1159
|
slotMode?: boolean;
|
|
1015
1160
|
/** Custom renderer for per-page headers. */
|
|
1016
1161
|
renderPageHeader?: (side: 'right' | 'left', header: PageHeaderData) => ReactNode;
|
|
@@ -1033,23 +1178,38 @@ interface MejiroSpreadProps {
|
|
|
1033
1178
|
* enables pointer-drag selection on the page content area.
|
|
1034
1179
|
*/
|
|
1035
1180
|
anchorAtCoord?: (x: number, y: number) => InChapterAnchor | null;
|
|
1181
|
+
/**
|
|
1182
|
+
* Zero-based index of the spread being rendered. Rectangles passed through
|
|
1183
|
+
* {@link MejiroSpreadProps.selectionRects} carry spread-local coordinates,
|
|
1184
|
+
* so this is what scopes them to this spread. When omitted, every supplied
|
|
1185
|
+
* rectangle is painted.
|
|
1186
|
+
*/
|
|
1187
|
+
spreadIdx?: number;
|
|
1036
1188
|
/**
|
|
1037
1189
|
* Selection rectangles to render as a highlight overlay. Compute via
|
|
1038
|
-
* {@link ChapterLayout.selectionRects}. Entries
|
|
1039
|
-
*
|
|
1190
|
+
* {@link ChapterLayout.selectionRects}. Entries whose `spreadIdx` differs
|
|
1191
|
+
* from {@link MejiroSpreadProps.spreadIdx} are ignored. An entry may carry
|
|
1192
|
+
* a `color` that becomes that rectangle's fill.
|
|
1040
1193
|
*/
|
|
1041
|
-
selectionRects?: readonly AnchorRect
|
|
1194
|
+
selectionRects?: readonly (AnchorRect & {
|
|
1195
|
+
color?: string;
|
|
1196
|
+
})[];
|
|
1042
1197
|
/**
|
|
1043
1198
|
* Called when the user drags-selects text on the spread.
|
|
1044
1199
|
* Called with `null` on a single-click (caret) where start equals end.
|
|
1045
1200
|
*/
|
|
1046
1201
|
onSelectionChange?: (range: AnchorRange | null) => void;
|
|
1047
1202
|
/**
|
|
1048
|
-
*
|
|
1049
|
-
* for portrait viewports or
|
|
1050
|
-
* mode.
|
|
1203
|
+
* Render only one page of the spread (centered), chosen by
|
|
1204
|
+
* {@link MejiroSpreadProps.singleSide}. Use this for portrait viewports or
|
|
1205
|
+
* when a reader explicitly opts into single-page mode.
|
|
1051
1206
|
*/
|
|
1052
1207
|
singlePage?: boolean;
|
|
1208
|
+
/**
|
|
1209
|
+
* Page of the spread shown when {@link MejiroSpreadProps.singlePage} is set
|
|
1210
|
+
* (`useSpread` reports it as `singleSide`). @defaultValue 'right'
|
|
1211
|
+
*/
|
|
1212
|
+
singleSide?: 'right' | 'left';
|
|
1053
1213
|
/**
|
|
1054
1214
|
* Called when the user makes a quick swipe gesture on the spread.
|
|
1055
1215
|
* `direction === 'next'` means the user swiped from right to left (the
|
|
@@ -1060,10 +1220,11 @@ interface MejiroSpreadProps {
|
|
|
1060
1220
|
onSurfaceTap?: () => void;
|
|
1061
1221
|
}
|
|
1062
1222
|
/**
|
|
1063
|
-
* Renders a two-page spread
|
|
1064
|
-
* zones, and image overlays. Used inside
|
|
1223
|
+
* Renders a two-page spread (or one page of it in single-page mode) with the
|
|
1224
|
+
* book frame, page chrome, navigation zones, and image overlays. Used inside
|
|
1225
|
+
* `mejiro-reader-surface`.
|
|
1065
1226
|
*/
|
|
1066
|
-
declare function MejiroSpread({ spread, pageWidth, pageHeight, contentHeight, fontFamily, fontSize, lineSpacing, turning, rightHeader, leftHeader, images, renderPageHeader, indicator, onPrev, onNext, onImagePointerDown, onImageResizePointerDown, onImageClose, anchorAtCoord, selectionRects, onSelectionChange, singlePage, onSwipe, onSurfaceTap, }: MejiroSpreadProps): ReactNode;
|
|
1227
|
+
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;
|
|
1067
1228
|
|
|
1068
1229
|
/** Props for {@link MejiroStats}. */
|
|
1069
1230
|
interface MejiroStatsProps {
|
|
@@ -1093,9 +1254,9 @@ interface MejiroTocProps {
|
|
|
1093
1254
|
currentAnchor?: ReadingAnchor | null;
|
|
1094
1255
|
/** Show a search input that filters chapter titles. @defaultValue false */
|
|
1095
1256
|
searchable?: boolean;
|
|
1096
|
-
/** Heading displayed above the list.
|
|
1257
|
+
/** Heading displayed above the list. Defaults to the active message catalog's `tocTitle`. */
|
|
1097
1258
|
title?: string;
|
|
1098
|
-
/** Placeholder shown in the search input.
|
|
1259
|
+
/** Placeholder shown in the search input. Defaults to the active message catalog's `tocSearchPlaceholder`. */
|
|
1099
1260
|
searchPlaceholder?: string;
|
|
1100
1261
|
/** Called when the user picks a chapter. */
|
|
1101
1262
|
onSelect?: (chapter: number) => void;
|
|
@@ -1116,6 +1277,8 @@ interface UseAnnotationsOptions {
|
|
|
1116
1277
|
/**
|
|
1117
1278
|
* Storage backend. Defaults to `window.localStorage` when available.
|
|
1118
1279
|
* SSR consumers can omit this and the hook will fall back to in-memory.
|
|
1280
|
+
* The latest reference is always used, so an object literal recreated on
|
|
1281
|
+
* every render is safe — only `key` triggers a re-hydration.
|
|
1119
1282
|
*/
|
|
1120
1283
|
storage?: AnnotationsStorage;
|
|
1121
1284
|
/** Throttle ms between writes. @defaultValue 250 */
|
|
@@ -1173,17 +1336,20 @@ interface UseChapterLayoutOptions {
|
|
|
1173
1336
|
*/
|
|
1174
1337
|
pageGeometry?: () => ComputePageSizeOptions | undefined;
|
|
1175
1338
|
/**
|
|
1176
|
-
* Capture the
|
|
1177
|
-
*
|
|
1178
|
-
*
|
|
1179
|
-
*
|
|
1180
|
-
* Never called for blank (content-change) re-layouts.
|
|
1181
|
-
*
|
|
1182
|
-
* A reflow yields a brand-new {@link ChapterLayout} object, which resets any
|
|
1183
|
-
* downstream spread index to 0; capturing here and restoring after keeps the
|
|
1184
|
-
* reader on the same passage across resizes and font / option changes.
|
|
1339
|
+
* Capture the reading position from the outgoing layout, just before a
|
|
1340
|
+
* **reflow** (non-blank) re-layout replaces it. The anchor is held in
|
|
1341
|
+
* `pendingRestore` until the new layout is in place, then handed to
|
|
1342
|
+
* `restorePosition` when one is given. Return `null` to skip preservation.
|
|
1343
|
+
* Never called for blank (content-change) re-layouts, which start at spread 0.
|
|
1185
1344
|
*/
|
|
1186
1345
|
capturePosition?: (layout: ChapterLayout) => InChapterAnchor | null;
|
|
1346
|
+
/**
|
|
1347
|
+
* Apply an anchor captured by `capturePosition` to the new layout, e.g. by
|
|
1348
|
+
* locating it and jumping to its spread. Called once the new layout is in
|
|
1349
|
+
* place — after it commits, before paint — and `pendingRestore` is cleared
|
|
1350
|
+
* first. Without it, consume `pendingRestore` yourself.
|
|
1351
|
+
*/
|
|
1352
|
+
restorePosition?: (layout: ChapterLayout, position: InChapterAnchor) => void;
|
|
1187
1353
|
}
|
|
1188
1354
|
/** Options for {@link UseChapterLayoutReturn.recompute}. */
|
|
1189
1355
|
interface RecomputeOptions {
|
|
@@ -1197,8 +1363,11 @@ interface RecomputeOptions {
|
|
|
1197
1363
|
}
|
|
1198
1364
|
/** Page dimensions returned by {@link MejiroBook.computePageSize}. */
|
|
1199
1365
|
interface PageDimensions {
|
|
1366
|
+
/** Width of one page, in CSS pixels. */
|
|
1200
1367
|
pageWidth: number;
|
|
1368
|
+
/** Height of one page, in CSS pixels. */
|
|
1201
1369
|
pageHeight: number;
|
|
1370
|
+
/** Height of the text area inside a page, in CSS pixels. */
|
|
1202
1371
|
contentHeight: number;
|
|
1203
1372
|
}
|
|
1204
1373
|
/** Return value of {@link useChapterLayout}. */
|
|
@@ -1216,11 +1385,17 @@ interface UseChapterLayoutReturn {
|
|
|
1216
1385
|
/** Force a fresh layout computation. */
|
|
1217
1386
|
recompute: (opts?: RecomputeOptions) => Promise<void>;
|
|
1218
1387
|
/**
|
|
1219
|
-
* Anchor captured before the most recent reflow
|
|
1220
|
-
* restoration into the new
|
|
1221
|
-
*
|
|
1388
|
+
* Anchor captured by `capturePosition` before the most recent reflow,
|
|
1389
|
+
* awaiting restoration into the new layout. `restorePosition`, when given,
|
|
1390
|
+
* consumes it; otherwise read it once the new layout is in place and set it
|
|
1391
|
+
* back to `null`.
|
|
1392
|
+
*
|
|
1393
|
+
* Declared as a `MutableRefObject` because consumers are expected to write to
|
|
1394
|
+
* it — `@types/react@18` models `RefObject.current` as read-only, so a
|
|
1395
|
+
* `RefObject` here would make the documented recipe fail to compile on the
|
|
1396
|
+
* lower end of the supported peer range.
|
|
1222
1397
|
*/
|
|
1223
|
-
pendingRestore:
|
|
1398
|
+
pendingRestore: MutableRefObject<InChapterAnchor | null>;
|
|
1224
1399
|
}
|
|
1225
1400
|
/**
|
|
1226
1401
|
* React hook that lays out the currently-selected chapter and re-flows when the
|
|
@@ -1232,13 +1407,16 @@ interface UseChapterLayoutReturn {
|
|
|
1232
1407
|
* mounted before its container had a final box is still sized correctly on
|
|
1233
1408
|
* first paint), and later size changes trigger a debounced **full re-layout**.
|
|
1234
1409
|
*
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1410
|
+
* Size and option changes lay the chapter out again rather than calling
|
|
1411
|
+
* `ChapterLayout.resize()`, so page geometry is re-derived from the surface and
|
|
1412
|
+
* the book's current options. The book replays the line-breaking hints it
|
|
1413
|
+
* already derived for the chapter, so a reflow never re-runs the analyzer.
|
|
1414
|
+
* Because each re-layout yields a new {@link ChapterLayout} object (resetting
|
|
1415
|
+
* any downstream spread index to 0), the reading position is carried across
|
|
1416
|
+
* reflows by {@link UseChapterLayoutOptions.capturePosition},
|
|
1417
|
+
* {@link UseChapterLayoutOptions.restorePosition} and
|
|
1418
|
+
* {@link UseChapterLayoutReturn.pendingRestore}, identically in the Vue
|
|
1419
|
+
* composable.
|
|
1242
1420
|
*
|
|
1243
1421
|
* @param book - The book instance to lay out with.
|
|
1244
1422
|
* @param epub - The current parsed EPUB.
|
|
@@ -1248,10 +1426,7 @@ interface UseChapterLayoutReturn {
|
|
|
1248
1426
|
*/
|
|
1249
1427
|
declare function useChapterLayout(book: MejiroBook, epub: EpubBook | null, chapterIndex: number, surface: RefObject<HTMLElement | null>, options?: UseChapterLayoutOptions): UseChapterLayoutReturn;
|
|
1250
1428
|
|
|
1251
|
-
|
|
1252
|
-
chapter: number;
|
|
1253
|
-
paragraph: number;
|
|
1254
|
-
}
|
|
1429
|
+
/** Options for {@link useEditableEpub}. */
|
|
1255
1430
|
interface UseEditableEpubOptions {
|
|
1256
1431
|
/** URL fetched and loaded on mount. */
|
|
1257
1432
|
defaultUrl?: string;
|
|
@@ -1261,32 +1436,64 @@ interface UseEditableEpubOptions {
|
|
|
1261
1436
|
onError?: (error: Error) => void;
|
|
1262
1437
|
/** Called after export completes. */
|
|
1263
1438
|
onExport?: (buffer: ArrayBuffer) => void;
|
|
1439
|
+
/**
|
|
1440
|
+
* Archive resource limits applied while opening an EPUB. Raise them for
|
|
1441
|
+
* trusted, image-heavy books; tighten them for a public drop zone. Omitted
|
|
1442
|
+
* fields keep their `DEFAULT_EPUB_PARSE_LIMITS` value.
|
|
1443
|
+
*/
|
|
1444
|
+
limits?: Partial<EpubParseLimits>;
|
|
1445
|
+
/**
|
|
1446
|
+
* Resolves URL-only images into bytes when {@link UseEditableEpubReturn.exportEpub}
|
|
1447
|
+
* packages the book. An `assetResolver` passed to `exportEpub` itself wins.
|
|
1448
|
+
*/
|
|
1449
|
+
assetResolver?: AssetResolver;
|
|
1264
1450
|
}
|
|
1451
|
+
/** Return value of {@link useEditableEpub}. */
|
|
1265
1452
|
interface UseEditableEpubReturn {
|
|
1453
|
+
/** Loaded editor, or `null` before any load. */
|
|
1266
1454
|
editor: EditableEpub | null;
|
|
1455
|
+
/** The editor's live document, or `null` before any load. */
|
|
1267
1456
|
book: EditableEpubBook | null;
|
|
1457
|
+
/** Snapshot of `book` re-cloned on every edit, for feeding a preview reader. */
|
|
1268
1458
|
previewBook: EditableEpubBook | null;
|
|
1459
|
+
/** Whether a load is in progress. */
|
|
1269
1460
|
loading: boolean;
|
|
1461
|
+
/** Whether an export is in progress. */
|
|
1270
1462
|
exporting: boolean;
|
|
1463
|
+
/** Last load error, if any. */
|
|
1271
1464
|
error: Error | null;
|
|
1465
|
+
/** Counter bumped on every load, edit, undo and redo. */
|
|
1272
1466
|
revision: number;
|
|
1467
|
+
/** Undo / redo availability, or `null` before any load. */
|
|
1273
1468
|
history: {
|
|
1274
1469
|
canUndo: boolean;
|
|
1275
1470
|
canRedo: boolean;
|
|
1276
1471
|
depth: number;
|
|
1277
1472
|
redoDepth: number;
|
|
1278
1473
|
} | null;
|
|
1474
|
+
/** Paragraph targeted by the editing commands. */
|
|
1279
1475
|
selection: EditableEpubSelection;
|
|
1476
|
+
/** The paragraph at `selection`, or `null` when there is none. */
|
|
1280
1477
|
selectedParagraph: AnnotatedParagraph | null;
|
|
1478
|
+
/** Moves the selection, clamped to the loaded book. */
|
|
1281
1479
|
setSelection: (selection: EditableEpubSelection) => void;
|
|
1480
|
+
/** Loads an EPUB from an in-memory buffer. */
|
|
1282
1481
|
loadBuffer: (buffer: ArrayBuffer) => Promise<EditableEpub | null>;
|
|
1482
|
+
/** Loads an EPUB from a {@link File}. */
|
|
1283
1483
|
loadFile: (file: File) => Promise<EditableEpub | null>;
|
|
1484
|
+
/** Fetches and loads an EPUB; a non-2xx response is reported as an error. */
|
|
1284
1485
|
loadUrl: (url: string) => Promise<EditableEpub | null>;
|
|
1486
|
+
/** Replaces the selected paragraph's text and, optionally, its inline annotations. */
|
|
1285
1487
|
updateParagraph: (text: string, inlineAnnotations?: readonly InlineAnnotation[]) => void;
|
|
1488
|
+
/** Replaces the selected paragraph's inline annotations. */
|
|
1286
1489
|
setInlineAnnotations: (inlineAnnotations: readonly InlineAnnotation[]) => void;
|
|
1490
|
+
/** Inserts an image into the selected chapter. */
|
|
1287
1491
|
addImage: (image: AddImageInput | EditableEpubImage) => void;
|
|
1492
|
+
/** Reverts the last edit. Returns `false` when there is nothing to undo. */
|
|
1288
1493
|
undo: () => boolean;
|
|
1494
|
+
/** Re-applies the last undone edit. Returns `false` when there is nothing to redo. */
|
|
1289
1495
|
redo: () => boolean;
|
|
1496
|
+
/** Packages the edited document as an EPUB buffer. */
|
|
1290
1497
|
exportEpub: (options?: EpubExportOptions) => Promise<ArrayBuffer | null>;
|
|
1291
1498
|
}
|
|
1292
1499
|
/** Headless editable-EPUB state for custom proofreading/editor UIs. */
|
|
@@ -1294,11 +1501,11 @@ declare function useEditableEpub(options?: UseEditableEpubOptions): UseEditableE
|
|
|
1294
1501
|
|
|
1295
1502
|
/** Options for {@link useEpub}. */
|
|
1296
1503
|
interface UseEpubOptions {
|
|
1297
|
-
/** URL fetched on mount.
|
|
1504
|
+
/** URL fetched on mount. */
|
|
1298
1505
|
defaultUrl?: string;
|
|
1299
1506
|
/** Called after a successful load. */
|
|
1300
1507
|
onLoad?: (book: EpubBook) => void;
|
|
1301
|
-
/** Called when a load fails
|
|
1508
|
+
/** Called when a load fails, including a non-2xx URL response. */
|
|
1302
1509
|
onError?: (error: Error) => void;
|
|
1303
1510
|
/**
|
|
1304
1511
|
* Extra options merged into the `fetch` call when loading by URL. Useful
|
|
@@ -1311,6 +1518,12 @@ interface UseEpubOptions {
|
|
|
1311
1518
|
* for hosts that already own an auth-aware HTTP client.
|
|
1312
1519
|
*/
|
|
1313
1520
|
fetchEpub?: (url: string) => Promise<ArrayBuffer>;
|
|
1521
|
+
/**
|
|
1522
|
+
* Archive resource limits applied while opening an EPUB. Raise them for
|
|
1523
|
+
* trusted, image-heavy books; tighten them for a public drop zone. Omitted
|
|
1524
|
+
* fields keep their `DEFAULT_EPUB_PARSE_LIMITS` value.
|
|
1525
|
+
*/
|
|
1526
|
+
limits?: Partial<EpubParseLimits>;
|
|
1314
1527
|
}
|
|
1315
1528
|
/** Return value of {@link useEpub}. */
|
|
1316
1529
|
interface UseEpubReturn {
|
|
@@ -1335,45 +1548,104 @@ interface UseEpubReturn {
|
|
|
1335
1548
|
*/
|
|
1336
1549
|
declare function useEpub(options?: UseEpubOptions): UseEpubReturn;
|
|
1337
1550
|
|
|
1551
|
+
/** One chapter of the manuscript draft the hook keeps in React state. */
|
|
1338
1552
|
interface EpubProjectChapterDraft {
|
|
1553
|
+
/** Stable chapter identifier. */
|
|
1339
1554
|
id: string;
|
|
1555
|
+
/** Chapter title. */
|
|
1340
1556
|
title: string;
|
|
1557
|
+
/** Chapter body in the manuscript notation. */
|
|
1341
1558
|
body: string;
|
|
1342
1559
|
}
|
|
1560
|
+
/** Options for {@link useEpubProject}. */
|
|
1343
1561
|
interface UseEpubProjectOptions {
|
|
1562
|
+
/** Initial package metadata, merged over the hook's Japanese defaults. */
|
|
1344
1563
|
metadata?: Partial<EpubProjectMetadata>;
|
|
1564
|
+
/** Initial chapter drafts. A single generated chapter is used when empty. */
|
|
1345
1565
|
chapters?: EpubProjectChapterDraft[];
|
|
1566
|
+
/** Preview rebuild debounce in milliseconds. @defaultValue 250 */
|
|
1346
1567
|
debounceMs?: number;
|
|
1568
|
+
/**
|
|
1569
|
+
* Initial cover asset. Pass `{ href, url }` to keep the bytes remote until
|
|
1570
|
+
* export, or `{ href, data }` to embed them straight away.
|
|
1571
|
+
*/
|
|
1572
|
+
cover?: EpubProjectAsset;
|
|
1573
|
+
/**
|
|
1574
|
+
* Initial non-cover assets (illustrations, extra stylesheets). Same
|
|
1575
|
+
* `data` / `url` choice as {@link UseEpubProjectOptions.cover}.
|
|
1576
|
+
*/
|
|
1577
|
+
assets?: EpubProjectAsset[];
|
|
1347
1578
|
/**
|
|
1348
1579
|
* Resolves URL-only project assets into bytes when the preview or export
|
|
1349
|
-
* pipeline materializes them. Forwarded to `project.export()`.
|
|
1350
|
-
*
|
|
1351
|
-
* the host (not the client)
|
|
1580
|
+
* pipeline materializes them. Forwarded to `project.export()`. Register the
|
|
1581
|
+
* URLs through {@link UseEpubProjectReturn.setCover} /
|
|
1582
|
+
* {@link UseEpubProjectReturn.setAssets} and let the host (not the client)
|
|
1583
|
+
* provide auth headers here.
|
|
1352
1584
|
*/
|
|
1353
1585
|
assetResolver?: AssetResolver;
|
|
1586
|
+
/** Called with each successfully rebuilt preview book. */
|
|
1354
1587
|
onPreview?: (book: EpubBook) => void;
|
|
1588
|
+
/** Called with the EPUB bytes produced by {@link UseEpubProjectReturn.exportEpub}. */
|
|
1355
1589
|
onExport?: (buffer: ArrayBuffer) => void;
|
|
1356
1590
|
/** Creates the default title for a generated chapter. */
|
|
1357
1591
|
defaultChapterTitle?: (index: number) => string;
|
|
1358
1592
|
/** Creates the default body for a generated chapter. */
|
|
1359
1593
|
defaultChapterBody?: (index: number) => string;
|
|
1360
1594
|
}
|
|
1595
|
+
/** State and actions returned by {@link useEpubProject}. */
|
|
1361
1596
|
interface UseEpubProjectReturn {
|
|
1597
|
+
/** Current book metadata. */
|
|
1362
1598
|
metadata: EpubProjectMetadata;
|
|
1599
|
+
/** Current chapter drafts, in reading order. */
|
|
1363
1600
|
chapters: EpubProjectChapterDraft[];
|
|
1601
|
+
/** Index of the chapter being edited. */
|
|
1364
1602
|
selectedChapter: number;
|
|
1603
|
+
/** The chapter at `selectedChapter`, or `null` when there is none. */
|
|
1365
1604
|
currentChapter: EpubProjectChapterDraft | null;
|
|
1605
|
+
/** Current cover asset, or `null` when the project has no cover. */
|
|
1606
|
+
cover: EpubProjectAsset | null;
|
|
1607
|
+
/** Current non-cover assets, in registration order. */
|
|
1608
|
+
assets: EpubProjectAsset[];
|
|
1609
|
+
/** Parsed EPUB built from the current project, refreshed after each debounced change. */
|
|
1366
1610
|
previewBook: EpubBook | null;
|
|
1611
|
+
/** Last preview build failure, if any. */
|
|
1367
1612
|
previewError: Error | null;
|
|
1613
|
+
/** Whether a preview build is pending or running. */
|
|
1368
1614
|
previewing: boolean;
|
|
1615
|
+
/** Merges `patch` into the metadata. */
|
|
1369
1616
|
setMetadata: (patch: Partial<EpubProjectMetadata>) => void;
|
|
1617
|
+
/** Replaces every chapter; an empty list becomes one generated chapter. */
|
|
1370
1618
|
setChapters: (chapters: EpubProjectChapterDraft[]) => void;
|
|
1619
|
+
/** Selects a chapter, clamped to the chapter range. */
|
|
1371
1620
|
setSelectedChapter: (index: number) => void;
|
|
1621
|
+
/**
|
|
1622
|
+
* Replaces the cover asset, or drops it when passed `null`. The new cover is
|
|
1623
|
+
* reflected by both the debounced preview and {@link UseEpubProjectReturn.exportEpub}.
|
|
1624
|
+
*/
|
|
1625
|
+
setCover: (asset: EpubProjectAsset | null) => void;
|
|
1626
|
+
/**
|
|
1627
|
+
* Replaces the non-cover asset list. Assets are registered on every rebuilt
|
|
1628
|
+
* project, so URL-only entries reach `assetResolver` at export time.
|
|
1629
|
+
*/
|
|
1630
|
+
setAssets: (assets: EpubProjectAsset[]) => void;
|
|
1631
|
+
/** Merges `patch` into the chapter at `index`. */
|
|
1372
1632
|
patchChapter: (index: number, patch: Partial<EpubProjectChapterDraft>) => void;
|
|
1633
|
+
/** Appends a chapter (generated defaults fill omitted fields) and selects it. */
|
|
1373
1634
|
addChapter: (chapter?: Partial<EpubProjectChapterDraft>) => void;
|
|
1635
|
+
/**
|
|
1636
|
+
* Removes the chapter at `index` (the selected one by default); the last chapter is never
|
|
1637
|
+
* removed.
|
|
1638
|
+
*/
|
|
1374
1639
|
removeChapter: (index?: number) => void;
|
|
1640
|
+
/**
|
|
1641
|
+
* Moves a chapter from `from` to `to`. An out-of-range `from` selects no
|
|
1642
|
+
* chapter and leaves the list untouched; `to` is clamped to the list bounds —
|
|
1643
|
+
* the same contract as `EpubProject.reorderChapters()`.
|
|
1644
|
+
*/
|
|
1375
1645
|
reorderChapters: (from: number, to: number) => void;
|
|
1646
|
+
/** Builds an `EpubProject` from the current state. */
|
|
1376
1647
|
buildProject: () => EpubProject;
|
|
1648
|
+
/** Packages the current project as an EPUB buffer. */
|
|
1377
1649
|
exportEpub: () => Promise<ArrayBuffer>;
|
|
1378
1650
|
}
|
|
1379
1651
|
/** Headless manuscript-to-EPUB project state for custom authoring UIs. */
|
|
@@ -1401,14 +1673,24 @@ interface UseManuscriptDraftOptions<TAutosave = ManuscriptEditorChapter[]> {
|
|
|
1401
1673
|
}
|
|
1402
1674
|
/** Return value of {@link useManuscriptDraft}. */
|
|
1403
1675
|
interface UseManuscriptDraftReturn {
|
|
1676
|
+
/** Current chapters, in reading order. */
|
|
1404
1677
|
chapters: ManuscriptEditorChapter[];
|
|
1405
1678
|
/** Index of the chapter currently being edited. */
|
|
1406
1679
|
selected: number;
|
|
1680
|
+
/** Selects a chapter, clamped to the chapter range. */
|
|
1407
1681
|
setSelected(index: number): void;
|
|
1682
|
+
/**
|
|
1683
|
+
* Replaces every chapter; an empty list becomes one generated chapter. The
|
|
1684
|
+
* selected chapter is kept by id when it survives.
|
|
1685
|
+
*/
|
|
1408
1686
|
setChapters(chapters: ManuscriptEditorChapter[]): void;
|
|
1687
|
+
/** Merges `patch` into the chapter at `index`. */
|
|
1409
1688
|
patchChapter(index: number, patch: Partial<ManuscriptEditorChapter>): void;
|
|
1689
|
+
/** Appends a chapter (generated defaults fill omitted fields) and selects it. */
|
|
1410
1690
|
addChapter(chapter?: Partial<ManuscriptEditorChapter>): void;
|
|
1691
|
+
/** Removes the chapter at `index`; the last remaining chapter is never removed. */
|
|
1411
1692
|
removeChapter(index: number): void;
|
|
1693
|
+
/** Moves the chapter at `from` to `to`, keeping the same chapter selected. */
|
|
1412
1694
|
reorderChapters(from: number, to: number): void;
|
|
1413
1695
|
/** Last autosave failure, if any. */
|
|
1414
1696
|
autosaveError: Error | null;
|
|
@@ -1432,11 +1714,39 @@ interface UseManuscriptLayoutOptions {
|
|
|
1432
1714
|
enableResize?: boolean;
|
|
1433
1715
|
/** Debounce window (ms) applied to size-triggered re-flows. @defaultValue 120 */
|
|
1434
1716
|
resizeDebounce?: number;
|
|
1717
|
+
/**
|
|
1718
|
+
* Capture the reading position from the outgoing layout, just before a
|
|
1719
|
+
* **reflow** (non-blank) re-layout replaces it. The anchor is held in
|
|
1720
|
+
* `pendingRestore` until the new layout is in place, then handed to
|
|
1721
|
+
* `restorePosition` when one is given. Return `null` to skip preservation.
|
|
1722
|
+
* Never called for blank (content-change) re-layouts, which start at spread 0.
|
|
1723
|
+
*/
|
|
1724
|
+
capturePosition?: (layout: ChapterLayout) => InChapterAnchor | null;
|
|
1725
|
+
/**
|
|
1726
|
+
* Apply an anchor captured by `capturePosition` to the new layout, e.g. by
|
|
1727
|
+
* locating it and jumping to its spread. Called once the new layout is in
|
|
1728
|
+
* place — after it commits, before paint — and `pendingRestore` is cleared
|
|
1729
|
+
* first. Without it, consume `pendingRestore` yourself.
|
|
1730
|
+
*/
|
|
1731
|
+
restorePosition?: (layout: ChapterLayout, position: InChapterAnchor) => void;
|
|
1732
|
+
}
|
|
1733
|
+
/** Options for {@link UseManuscriptLayoutReturn.recompute}. */
|
|
1734
|
+
interface ManuscriptRecomputeOptions {
|
|
1735
|
+
/**
|
|
1736
|
+
* Blank the current layout while the new one is computed. Use for content
|
|
1737
|
+
* changes (chapter swaps); skip for size changes so the previous spread stays
|
|
1738
|
+
* visible until the re-flow completes (no flicker).
|
|
1739
|
+
* @defaultValue true
|
|
1740
|
+
*/
|
|
1741
|
+
blank?: boolean;
|
|
1435
1742
|
}
|
|
1436
1743
|
/** Page dimensions returned by {@link MejiroBook.computePageSize}. */
|
|
1437
1744
|
interface ManuscriptPageDimensions {
|
|
1745
|
+
/** Width of one page, in CSS pixels. */
|
|
1438
1746
|
pageWidth: number;
|
|
1747
|
+
/** Height of one page, in CSS pixels. */
|
|
1439
1748
|
pageHeight: number;
|
|
1749
|
+
/** Height of the text area inside a page, in CSS pixels. */
|
|
1440
1750
|
contentHeight: number;
|
|
1441
1751
|
}
|
|
1442
1752
|
/** Return value of {@link useManuscriptLayout}. */
|
|
@@ -1452,7 +1762,14 @@ interface UseManuscriptLayoutReturn {
|
|
|
1452
1762
|
/** Most recent layout time (ms). */
|
|
1453
1763
|
elapsedMs: number;
|
|
1454
1764
|
/** Force a fresh layout computation. */
|
|
1455
|
-
recompute: () => Promise<void>;
|
|
1765
|
+
recompute: (opts?: ManuscriptRecomputeOptions) => Promise<void>;
|
|
1766
|
+
/**
|
|
1767
|
+
* Anchor captured by `capturePosition` before the most recent reflow,
|
|
1768
|
+
* awaiting restoration into the new layout. `restorePosition`, when given,
|
|
1769
|
+
* consumes it; otherwise read it once the new layout is in place and set it
|
|
1770
|
+
* back to `null`.
|
|
1771
|
+
*/
|
|
1772
|
+
pendingRestore: MutableRefObject<InChapterAnchor | null>;
|
|
1456
1773
|
}
|
|
1457
1774
|
/**
|
|
1458
1775
|
* React hook that lays out a single manuscript chapter directly, skipping the
|
|
@@ -1465,9 +1782,37 @@ interface UseManuscriptLayoutReturn {
|
|
|
1465
1782
|
* Re-layouts whenever `chapter`, `dialect`, or `book` change. The surface is
|
|
1466
1783
|
* observed with {@link ResizeObserver}; size changes trigger a full re-layout
|
|
1467
1784
|
* so pagination stays correct after non-trivial container changes.
|
|
1785
|
+
*
|
|
1786
|
+
* A size-driven re-layout keeps the previous layout on screen while the new one
|
|
1787
|
+
* is computed (no blank flash) and yields a new {@link ChapterLayout} object,
|
|
1788
|
+
* which resets any downstream spread index to 0; the reading position is
|
|
1789
|
+
* preserved across such reflows via
|
|
1790
|
+
* {@link UseManuscriptLayoutOptions.capturePosition},
|
|
1791
|
+
* {@link UseManuscriptLayoutOptions.restorePosition} and
|
|
1792
|
+
* {@link UseManuscriptLayoutReturn.pendingRestore}, identically in the Vue
|
|
1793
|
+
* composable.
|
|
1468
1794
|
*/
|
|
1469
1795
|
declare function useManuscriptLayout(book: MejiroBook, chapter: ManuscriptChapter | null, surface: RefObject<HTMLElement | null>, options?: UseManuscriptLayoutOptions): UseManuscriptLayoutReturn;
|
|
1470
1796
|
|
|
1797
|
+
/** Options for {@link useMejiroBook}. */
|
|
1798
|
+
interface UseMejiroBookOptions {
|
|
1799
|
+
/**
|
|
1800
|
+
* Coalescing window (ms) applied before a change reaches the underlying
|
|
1801
|
+
* {@link MejiroBook}. The exposed snapshot is always updated synchronously so
|
|
1802
|
+
* controlled settings UI stays responsive; only the book application — and the
|
|
1803
|
+
* font load it may trigger — is debounced, so dragging a continuous control
|
|
1804
|
+
* results in a single re-measurement. `0` applies immediately.
|
|
1805
|
+
* @defaultValue 0
|
|
1806
|
+
*/
|
|
1807
|
+
debounceMs?: number;
|
|
1808
|
+
/**
|
|
1809
|
+
* Called when applying options to the book fails. When supplied, failures are
|
|
1810
|
+
* reported here and the promise returned by
|
|
1811
|
+
* {@link UseMejiroBookReturn.setOptions} resolves instead of rejecting, so
|
|
1812
|
+
* fire-and-forget callers cannot leave an unhandled rejection behind.
|
|
1813
|
+
*/
|
|
1814
|
+
onError?: (error: Error) => void;
|
|
1815
|
+
}
|
|
1471
1816
|
/** Return value of {@link useMejiroBook}. */
|
|
1472
1817
|
interface UseMejiroBookReturn {
|
|
1473
1818
|
/** The managed {@link MejiroBook} instance. Stable across renders. */
|
|
@@ -1475,9 +1820,10 @@ interface UseMejiroBookReturn {
|
|
|
1475
1820
|
/** Reactive snapshot of the current options. */
|
|
1476
1821
|
options: Readonly<BookOptions>;
|
|
1477
1822
|
/**
|
|
1478
|
-
* Update options on the underlying book and the snapshot. The
|
|
1479
|
-
*
|
|
1480
|
-
* font / size changes (
|
|
1823
|
+
* Update options on the underlying book and the snapshot. The snapshot is
|
|
1824
|
+
* updated synchronously; the returned promise resolves once
|
|
1825
|
+
* {@link MejiroBook.setOptions} has propagated font / size changes (which
|
|
1826
|
+
* complete only after the font has loaded).
|
|
1481
1827
|
*/
|
|
1482
1828
|
setOptions: (next: Partial<BookOptions>) => Promise<void>;
|
|
1483
1829
|
}
|
|
@@ -1486,8 +1832,11 @@ interface UseMejiroBookReturn {
|
|
|
1486
1832
|
* options as React state. The book is created once on mount; subsequent
|
|
1487
1833
|
* option changes must go through {@link UseMejiroBookReturn.setOptions}
|
|
1488
1834
|
* (e.g. via the `MejiroReader` imperative handle).
|
|
1835
|
+
*
|
|
1836
|
+
* @param initial - Initial book options (passed to the {@link MejiroBook} constructor).
|
|
1837
|
+
* @param options - Behavior overrides (debouncing, error reporting).
|
|
1489
1838
|
*/
|
|
1490
|
-
declare function useMejiroBook(initial: BookOptions): UseMejiroBookReturn;
|
|
1839
|
+
declare function useMejiroBook(initial: BookOptions, options?: UseMejiroBookOptions): UseMejiroBookReturn;
|
|
1491
1840
|
|
|
1492
1841
|
/** Minimal storage interface required by {@link useReadingPosition}. */
|
|
1493
1842
|
type ReadingPositionStorage = MejiroStorage;
|
|
@@ -1527,9 +1876,10 @@ interface UseReadingPositionReturn {
|
|
|
1527
1876
|
* const { position, save } = useReadingPosition({ key: `mejiro:${bookId}` });
|
|
1528
1877
|
* const reader = useRef<MejiroReaderHandle>(null);
|
|
1529
1878
|
*
|
|
1879
|
+
* // Restore once per mount: depending on `position` would re-run after every save().
|
|
1530
1880
|
* useEffect(() => {
|
|
1531
1881
|
* if (position) reader.current?.goToAnchor(position);
|
|
1532
|
-
* }, [
|
|
1882
|
+
* }, []);
|
|
1533
1883
|
*
|
|
1534
1884
|
* useEffect(() => {
|
|
1535
1885
|
* const off = reader.current?.subscribe('spreadChanged', () => {
|
|
@@ -1552,33 +1902,53 @@ interface UseSpreadOptions {
|
|
|
1552
1902
|
enableKeyboard?: boolean;
|
|
1553
1903
|
/** Page-turn animation duration in ms. @defaultValue 180 */
|
|
1554
1904
|
turnDuration?: number;
|
|
1905
|
+
/**
|
|
1906
|
+
* Show one page at a time: the navigation index then counts pages instead
|
|
1907
|
+
* of two-page spreads. Toggling it converts the index so the page on
|
|
1908
|
+
* screen stays visible. @defaultValue false
|
|
1909
|
+
*/
|
|
1910
|
+
single?: boolean;
|
|
1555
1911
|
/** Called when the spread index changes (after the turn animation midpoint). */
|
|
1556
1912
|
onChange?: (spreadIdx: number) => void;
|
|
1557
1913
|
}
|
|
1558
1914
|
/** Return value of {@link useSpread}. */
|
|
1559
1915
|
interface UseSpreadReturn {
|
|
1560
|
-
/** Current spread index. */
|
|
1916
|
+
/** Current navigation index: a page index in single mode, a spread index otherwise. */
|
|
1561
1917
|
spreadIdx: number;
|
|
1562
|
-
/**
|
|
1918
|
+
/** Layout spread holding the visible page(s), or `null` until the layout is ready. */
|
|
1563
1919
|
spread: SpreadResult | null;
|
|
1564
|
-
/**
|
|
1920
|
+
/** First page shown, in reading order. */
|
|
1921
|
+
firstPage: number;
|
|
1922
|
+
/** Index of {@link UseSpreadReturn.spread} in the layout (`ChapterLayout.getSpread`). */
|
|
1923
|
+
layoutSpreadIdx: number;
|
|
1924
|
+
/** Side of {@link UseSpreadReturn.spread} shown in single mode; `null` in double mode. */
|
|
1925
|
+
singleSide: 'right' | 'left' | null;
|
|
1926
|
+
/** Total number of pages, as of {@link UseSpreadReturn.spread}. */
|
|
1565
1927
|
totalPages: number;
|
|
1566
|
-
/**
|
|
1928
|
+
/** Number of navigation positions: pages in single mode, two-page spreads otherwise. */
|
|
1567
1929
|
totalSpreads: number;
|
|
1568
1930
|
/** Whether the turn animation is currently in flight. */
|
|
1569
1931
|
turning: boolean;
|
|
1570
|
-
/** Advance one spread forward. */
|
|
1932
|
+
/** Advance one position (page or spread) forward. */
|
|
1571
1933
|
next: () => void;
|
|
1572
|
-
/** Go back one
|
|
1934
|
+
/** Go back one position. */
|
|
1573
1935
|
prev: () => void;
|
|
1574
|
-
/** Jump to an arbitrary
|
|
1936
|
+
/** Jump to an arbitrary navigation index (clamped). */
|
|
1575
1937
|
goTo: (index: number) => void;
|
|
1576
1938
|
/**
|
|
1577
|
-
* Set the
|
|
1578
|
-
* `[0, totalSpreads − 1]`. Use to restore a reading position after a reflow
|
|
1939
|
+
* Set the navigation index immediately, with no page-turn animation, clamped
|
|
1940
|
+
* to `[0, totalSpreads − 1]`. Use to restore a reading position after a reflow
|
|
1579
1941
|
* re-layout (where an animated {@link goTo} would briefly flash spread 0).
|
|
1580
1942
|
*/
|
|
1581
1943
|
setSpread: (index: number) => void;
|
|
1944
|
+
/** Navigation index that shows the given page index. */
|
|
1945
|
+
indexOfPage: (pageIdx: number) => number;
|
|
1946
|
+
/**
|
|
1947
|
+
* Anchor at the start of the text shown at navigation index `index`. A page an
|
|
1948
|
+
* image blocks entirely holds no text, so the anchor then comes from the next
|
|
1949
|
+
* page that does, even past `index`; `null` when no page from there on holds text.
|
|
1950
|
+
*/
|
|
1951
|
+
anchorAt: (index: number) => InChapterAnchor | null;
|
|
1582
1952
|
/** Manually refresh `spread` from `layout` at the current index. */
|
|
1583
1953
|
refresh: () => void;
|
|
1584
1954
|
}
|
|
@@ -1588,4 +1958,4 @@ interface UseSpreadReturn {
|
|
|
1588
1958
|
*/
|
|
1589
1959
|
declare function useSpread(layout: ChapterLayout | null, options?: UseSpreadOptions): UseSpreadReturn;
|
|
1590
1960
|
|
|
1591
|
-
export { type AnnotationsStorage, type
|
|
1961
|
+
export { type AnnotationsStorage, type EpubProjectChapterDraft, type ImageRect, type ManuscriptAutosaveDraft, type ManuscriptEditorChapter, type ManuscriptPageDimensions, type ManuscriptPreviewProps, type ManuscriptRecomputeOptions, MejiroChapterNav, type MejiroChapterNavMode, type MejiroChapterNavProps, type MejiroChapterNavVariant, MejiroDropZone, type MejiroDropZoneProps, MejiroEditor, type MejiroEditorProps, type MejiroExportPolicy, MejiroI18nProvider, MejiroImageOverlay, type MejiroImageOverlayProps, MejiroManuscriptEditor, type MejiroManuscriptEditorProps, MejiroNotationHighlighter, type MejiroNotationHighlighterProps, MejiroPage, MejiroPageIndicator, type MejiroPageIndicatorProps, type MejiroPageProps, MejiroPageView, type MejiroPageViewProps, MejiroReader, type MejiroReaderCommonProps, type MejiroReaderControlledProps, type MejiroReaderEventMap, type MejiroReaderFileProps, type MejiroReaderFit, type MejiroReaderHandle, type MejiroReaderManuscriptProps, type MejiroReaderMode, type MejiroReaderProps, type MejiroReaderSettingsSlot, type MejiroReaderUrlProps, MejiroScrollView, type MejiroScrollViewProps, MejiroSelectionLayer, type MejiroSelectionLayerProps, MejiroSettingsPanel, type MejiroSettingsPanelProps, MejiroShelf, type MejiroShelfProps, MejiroSpread, type MejiroSpreadMode, type MejiroSpreadProps, MejiroStats, type MejiroStatsProps, type MejiroTheme, type MejiroThemeName, MejiroToc, type MejiroTocProps, type MultiImageItem, type PageDimensions, type PageNumberDisplay, type ReadingPosition, type ReadingPositionStorage, type RecomputeOptions, type UseAnnotationsOptions, type UseAnnotationsReturn, type UseChapterLayoutOptions, type UseChapterLayoutReturn, type UseEditableEpubOptions, type UseEditableEpubReturn, type UseEpubOptions, type UseEpubProjectOptions, type UseEpubProjectReturn, type UseEpubReturn, type UseI18nOptions, type UseImageOverlayOptions, type UseImageOverlayReturn, type UseLibraryOptions, type UseLibraryReturn, type UseManuscriptDraftOptions, type UseManuscriptDraftReturn, type UseManuscriptLayoutOptions, type UseManuscriptLayoutReturn, type UseMejiroBookOptions, type UseMejiroBookReturn, type UseMultiImageOverlayOptions, type UseMultiImageOverlayReturn, type UseReadingPositionOptions, type UseReadingPositionReturn, type UseSpreadOptions, type UseSpreadReturn, type VolumeInfo, format, resolveMessages, useAnnotations, useChapterLayout, useEditableEpub, useEpub, useEpubProject, useI18n, useImageOverlay, useLibrary, useManuscriptDraft, useManuscriptLayout, useMejiroBook, useMultiImageOverlay, useReadingPosition, useSpread };
|