@aphrody/m3-reader 3.3.3

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 ADDED
@@ -0,0 +1,12 @@
1
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
2
+ # @aphrody/m3-reader
3
+
4
+ Material 3 React readers for paged and vertical manga and illustrated books. This package owns the reader UI, paging, virtual scrolling, zoom, fullscreen, thumbnails, keyboard controls, and lightbox focus. It does not own an asset server, editorial API, persistence, or OCR policy.
5
+
6
+ Import `@aphrody/m3-reader/styles.css` once in the host stylesheet. The host must load Tailwind 4 and scan the package's `dist` directory with `@source`, as with other Aphrody M3 component packages. CSS colors use Material 3 `--md-sys-color-*` roles, with readable fallbacks. The reader can also be themed through `--reader-surface`, `--reader-on-surface`, `--reader-accent`, `--reader-on-accent`, and `--reader-outline`.
7
+
8
+ For Shenron's Dragon Ball appearance, also import `@aphrody/m3-reader/dragon-ball.css` and wrap readers in `class="m3-reader--dragon-ball"`. All 12 editable `--dbz-*` palette values and the corner radius remain live, including `/admin/design` overrides. The reader theme also carries the measured slanted badge, ink border, tactile controls, and orange scrollbar conventions. The fallback colors follow Shenron's documented cover measurements in `docs/couverture-analyse-visuelle.md`; this package does not add new artwork. Shenron still owns the global site theme editor and the measured full palette used outside readers.
9
+
10
+ `MangaReader` accepts page URLs, direction, adjacent chapter links, an asset resolver, an optional mirror resolver, and callbacks for page addressing. `DatabookReader` accepts numbered pages, an abortable transcription loader, a transcription renderer, image optimization callbacks, and a preload count. `CollectionReader` owns edition and chapter controls; the host supplies its edition grouping and chapter renderer. The host supplies domain-specific loading and rendering.
11
+
12
+ Shenron uses the `/source` export through thin adapters in its manga and databook components, so a fresh local clone does not require a prebuilt `dist`. Next transpiles the package and Tailwind scans its `src`. The root export points to compiled `dist` for regular package consumers. Shenron remains responsible for asset routing, API links, reading history, on-demand transcription retrieval, OCR warnings, correction links, and Markdown rendering. The local `file:` dependency requires both repositories in the same parent directory until this package is published and Shenron switches to a registry version.
@@ -0,0 +1,26 @@
1
+ import { type ReactNode } from "react";
2
+ export interface ReaderCollectionChapter {
3
+ id: string | number;
4
+ label: string;
5
+ pageCount: number;
6
+ }
7
+ export interface ReaderCollectionEdition {
8
+ id: string;
9
+ label: string;
10
+ chapters: ReaderCollectionChapter[];
11
+ }
12
+ export interface CollectionReaderProps {
13
+ title: string;
14
+ editions: ReaderCollectionEdition[];
15
+ initialEdition?: string;
16
+ initialChapter?: string | number;
17
+ emptyLabel: string;
18
+ contentsLabel: string;
19
+ previousLabel: string;
20
+ nextLabel: string;
21
+ onSelectionChange?: (edition: ReaderCollectionEdition, chapter: ReaderCollectionChapter) => void;
22
+ renderChapter: (edition: ReaderCollectionEdition, chapter: ReaderCollectionChapter, index: number) => ReactNode;
23
+ }
24
+ /** Edition and chapter navigation shared by manga volumes and illustrated collections. */
25
+ export declare function CollectionReader({ title, editions, initialEdition, initialChapter, emptyLabel, contentsLabel, previousLabel, nextLabel, onSelectionChange, renderChapter }: CollectionReaderProps): import("react").JSX.Element;
26
+ //# sourceMappingURL=CollectionReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectionReader.d.ts","sourceRoot":"","sources":["../src/CollectionReader.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAuC,MAAM,OAAO,CAAC;AAE5E,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,uBAAuB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,uBAAuB,EAAE,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACjG,aAAa,EAAE,CAAC,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,uBAAuB,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;CACjH;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,EAAE,qBAAqB,+BAmDjM"}
@@ -0,0 +1,39 @@
1
+ import type { ReactNode } from "react";
2
+ import { type ReactElement } from "react";
3
+ import "swiper/css";
4
+ import "swiper/css/zoom";
5
+ import "swiper/css/virtual";
6
+ export type DatabookReaderPage = {
7
+ /** Numéro affiché (auto 1…N, modifiable côté admin). */
8
+ number?: number | null;
9
+ image?: string | null;
10
+ /**
11
+ * Transcription — présente pour les premières planches seulement.
12
+ * Au-delà, la fiche envoie `text: null` et `aDuTexte: true`, et le lecteur
13
+ * demande le texte au fournisseur de transcriptions au fil du défilement :
14
+ * embarquer les 313 transcriptions d'un Daizenshuu pesait 412 Ko de charge
15
+ * RSC pour une planche lue.
16
+ */
17
+ text?: string | null;
18
+ /** La planche PORTE une transcription, même si elle n'est pas encore chargée. */
19
+ aDuTexte?: boolean;
20
+ /** Transcription relue à l'image : pas d'avertissement de lecture douteuse. */
21
+ verifiee?: boolean;
22
+ };
23
+ export type ReaderTranscription = {
24
+ text: string;
25
+ page: number;
26
+ verified: boolean;
27
+ };
28
+ export type DatabookReaderProps = {
29
+ pages: DatabookReaderPage[];
30
+ title: string;
31
+ resolveAssetUrl?: (path: string) => string;
32
+ imageSrc?: (url: string, width: number) => string;
33
+ imageSrcSet?: (url: string, widths: number[]) => string | null;
34
+ loadTranscriptions?: (pages: number[], signal: AbortSignal) => Promise<Record<string, string>>;
35
+ renderTranscription?: (transcription: ReaderTranscription) => ReactNode;
36
+ preloadCount?: number;
37
+ };
38
+ export declare function DatabookReader({ pages, title, resolveAssetUrl, imageSrc, imageSrcSet, loadTranscriptions, renderTranscription, preloadCount, }: DatabookReaderProps): ReactElement;
39
+ //# sourceMappingURL=DatabookReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DatabookReader.d.ts","sourceRoot":"","sources":["../src/DatabookReader.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,KAAK,YAAY,EAA4D,MAAM,OAAO,CAAC;AAiBpG,OAAO,YAAY,CAAC;AAEpB,OAAO,iBAAiB,CAAC;AAEzB,OAAO,oBAAoB,CAAC;AAW5B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,MAAM,GAAG,IAAI,CAAC;IAC/D,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/F,mBAAmB,CAAC,EAAE,CAAC,aAAa,EAAE,mBAAmB,KAAK,SAAS,CAAC;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AA0GF,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,eAAgC,EAChC,QAAuB,EACvB,WAAwB,EACxB,kBAAkB,EAClB,mBAAmB,EACnB,YAAgB,GACjB,EAAE,mBAAmB,GAAG,YAAY,CAkmBpC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Lecteur de scan manga complet, 100 % client.
3
+ *
4
+ * Deux modes togglables :
5
+ * - Paginé : Swiper (Keyboard, Zoom, Virtual, Mousewheel), RTL réel,
6
+ * double-page optionnelle sur grand écran.
7
+ * - Vertical : défilement webtoon virtualisé via `@tanstack/react-virtual`
8
+ * (mesure dynamique des planches, overscan raisonnable).
9
+ *
10
+ * URL resolution and chapter persistence are supplied by the host.
11
+ */
12
+ import { type ReactElement, type ReactNode } from "react";
13
+ import "swiper/css";
14
+ import "swiper/css/zoom";
15
+ export type MangaReaderProps = {
16
+ pages: string[];
17
+ title: string;
18
+ direction?: "rtl" | "ltr";
19
+ prevHref?: string | null;
20
+ nextHref?: string | null;
21
+ prevPages?: string[] | null;
22
+ nextPages?: string[] | null;
23
+ initialPage?: number;
24
+ onPageChange?: (page: number) => void;
25
+ apiPageHref?: (page: number) => string | null;
26
+ resolveAssetUrl?: (path: string) => string;
27
+ resolveMirrorUrl?: (url: string) => string | null;
28
+ renderChapterLink?: (props: {
29
+ href: string;
30
+ children: ReactNode;
31
+ className: string;
32
+ ariaLabel: string;
33
+ }) => ReactNode;
34
+ };
35
+ export declare function MangaReader({ pages, title, direction, prevHref, nextHref, prevPages, nextPages, initialPage, onPageChange, apiPageHref, resolveAssetUrl, resolveMirrorUrl, renderChapterLink, }: MangaReaderProps): ReactElement;
36
+ //# sourceMappingURL=MangaReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MangaReader.d.ts","sourceRoot":"","sources":["../src/MangaReader.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,SAAS,EAOf,MAAM,OAAO,CAAC;AAkBf,OAAO,YAAY,CAAC;AAEpB,OAAO,iBAAiB,CAAC;AAWzB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC9C,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3C,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAClD,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,SAAS,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,KAAK,SAAS,CAAC;CACjB,CAAC;AAiBF,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAK,EACL,SAAiB,EACjB,QAAe,EACf,QAAe,EACf,SAAgB,EAChB,SAAgB,EAChB,WAAe,EACf,YAAY,EACZ,WAAW,EACX,eAAgC,EAChC,gBAAgB,EAChB,iBAAiB,GAClB,EAAE,gBAAgB,GAAG,YAAY,CAucjC"}
@@ -0,0 +1,7 @@
1
+ export { MangaReader } from "./MangaReader";
2
+ export type { MangaReaderProps } from "./MangaReader";
3
+ export { DatabookReader } from "./DatabookReader";
4
+ export type { DatabookReaderPage, DatabookReaderProps, ReaderTranscription } from "./DatabookReader";
5
+ export { CollectionReader } from "./CollectionReader";
6
+ export type { CollectionReaderProps, ReaderCollectionChapter, ReaderCollectionEdition } from "./CollectionReader";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC"}