flipbookengine 0.6.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -3
- package/README.md +150 -11
- package/dist/components/App.d.ts +19 -0
- package/dist/components/HotspotLayer.d.ts +14 -0
- package/dist/components/NotesPanel.d.ts +14 -0
- package/dist/components/PluginPanels.d.ts +5 -0
- package/dist/components/SearchPanel.d.ts +11 -0
- package/dist/components/Toolbar.d.ts +6 -0
- package/dist/components/Viewer.d.ts +6 -0
- package/dist/core/LayoutManager.d.ts +1 -1
- package/dist/core/PdfRenderer.d.ts +23 -2
- package/dist/core-entry.d.ts +13 -0
- package/dist/core.d.ts +1 -0
- package/dist/embed.d.ts +80 -0
- package/dist/engine-Dt2Fn6O-.js +4060 -0
- package/dist/engine-Dt2Fn6O-.js.map +1 -0
- package/dist/engine.d.ts +111 -1
- package/dist/feature-Cicli9ie.js +17 -0
- package/dist/feature-Cicli9ie.js.map +1 -0
- package/dist/flipbook-engine.core.js +8 -0
- package/dist/flipbook-engine.core.js.map +1 -0
- package/dist/flipbook-engine.css +1 -1
- package/dist/flipbook-engine.iife.js +56 -47
- package/dist/flipbook-engine.iife.js.map +1 -1
- package/dist/flipbook-engine.js +9 -4
- package/dist/flipbook-engine.js.map +1 -1
- package/dist/flipbook-engine.plugins-annotations.js +14 -0
- package/dist/flipbook-engine.plugins-annotations.js.map +1 -0
- package/dist/flipbook-engine.plugins-bookmarks.js +16 -0
- package/dist/flipbook-engine.plugins-bookmarks.js.map +1 -0
- package/dist/flipbook-engine.plugins-deep-link.js +14 -0
- package/dist/flipbook-engine.plugins-deep-link.js.map +1 -0
- package/dist/flipbook-engine.plugins-hotspots.js +15 -0
- package/dist/flipbook-engine.plugins-hotspots.js.map +1 -0
- package/dist/flipbook-engine.plugins-notes.js +16 -0
- package/dist/flipbook-engine.plugins-notes.js.map +1 -0
- package/dist/flipbook-engine.plugins-search.js +15 -0
- package/dist/flipbook-engine.plugins-search.js.map +1 -0
- package/dist/flipbook-engine.plugins-share.js +13 -0
- package/dist/flipbook-engine.plugins-share.js.map +1 -0
- package/dist/flipbook-engine.plugins-toc.js +14 -0
- package/dist/flipbook-engine.plugins-toc.js.map +1 -0
- package/dist/flipbook-engine.plugins.js +5 -0
- package/dist/flipbook-engine.plugins.js.map +1 -0
- package/dist/flipbook-engine.react.js +1 -1
- package/dist/flipbook-engine.vue.js +1 -1
- package/dist/i18n/locales/en.d.ts +17 -0
- package/dist/i18n/locales/tr.d.ts +17 -0
- package/dist/i18n/service.d.ts +51 -0
- package/dist/index-BhTR2SK6.js +366 -0
- package/dist/index-BhTR2SK6.js.map +1 -0
- package/dist/index.d.ts +10 -1
- package/dist/model/annotations.d.ts +14 -0
- package/dist/model/hotspots.d.ts +40 -0
- package/dist/model/pages.d.ts +2 -0
- package/dist/model/search.d.ts +25 -0
- package/dist/plugins/annotations.d.ts +4 -0
- package/dist/plugins/bookmarks.d.ts +4 -0
- package/dist/plugins/deep-link.d.ts +4 -0
- package/dist/plugins/feature.d.ts +5 -0
- package/dist/plugins/hotspots.d.ts +4 -0
- package/dist/plugins/index.d.ts +65 -0
- package/dist/plugins/notes.d.ts +4 -0
- package/dist/plugins/search.d.ts +4 -0
- package/dist/plugins/share.d.ts +4 -0
- package/dist/plugins/toc.d.ts +4 -0
- package/dist/plugins-annotations.d.ts +1 -0
- package/dist/plugins-bookmarks.d.ts +1 -0
- package/dist/plugins-deep-link.d.ts +1 -0
- package/dist/plugins-hotspots.d.ts +1 -0
- package/dist/plugins-notes.d.ts +1 -0
- package/dist/plugins-search.d.ts +1 -0
- package/dist/plugins-share.d.ts +1 -0
- package/dist/plugins-toc.d.ts +1 -0
- package/dist/plugins.d.ts +1 -0
- package/dist/state/store.d.ts +19 -5
- package/dist/theme/theme.d.ts +16 -0
- package/dist/vue/index.d.ts +1 -1
- package/docs/api-reference.md +206 -0
- package/docs/frameworks.md +73 -0
- package/docs/getting-started.md +128 -0
- package/docs/i18n.md +47 -0
- package/docs/migration-0.4.0.md +24 -0
- package/docs/migration-0.5.0.md +25 -0
- package/docs/migration-1.0.0.md +59 -0
- package/docs/plugin-architecture.md +103 -0
- package/docs/release-checklist.md +37 -0
- package/docs/theming.md +61 -0
- package/package.json +165 -114
- package/dist/engine-MdZzt6R9.js +0 -3474
- package/dist/engine-MdZzt6R9.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 1.0.0 - 2026-09-14
|
|
4
|
+
|
|
5
|
+
- first stable open-source release of the FlipbookEngine viewer
|
|
6
|
+
- added framework-agnostic plugin contract with install/uninstall lifecycle, typed events, toolbar buttons, panels, and namespaced APIs
|
|
7
|
+
- added independent `flipbookengine/core` and `flipbookengine/plugins/*` entry points for notes, bookmarks, TOC, search, annotations, hotspots, share, and deep links
|
|
8
|
+
- added runtime `getToc()/setToc()` APIs and origin-validated iframe TOC read/update commands
|
|
9
|
+
- added interactive hotspot overlays with image/video/audio previews, selectable image galleries, and commerce/product links
|
|
10
|
+
- added plugin and embed regression coverage; full suite passes 84/84 tests
|
|
11
|
+
- documented PDF outline extraction, OCR, analytics, backend rendering, and protected downloads as commercial/backend responsibilities
|
|
12
|
+
- breaking change: 0.x releases were alpha/beta and are not compatibility guarantees; applications should validate imports and options against the 1.0 API before upgrading
|
|
13
|
+
- 0.8.0 to 1.0.0 migration: documented public entrypoint changes, explicit plugin activation/deactivation, nested TOC/embed APIs, expanded hotspot payloads, and the unchanged image-mode search limitation
|
|
14
|
+
- added an origin-validated iframe embed bridge with parent-side command and event helpers
|
|
15
|
+
- added opt-in deep links, localized share controls, host-managed bookmarks and notes, and their regression coverage
|
|
16
|
+
- added localized notes toolbar/editor; persistence remains with the host application
|
|
17
|
+
|
|
18
|
+
## 0.8.0 - 2026-09-14
|
|
19
|
+
|
|
20
|
+
- added precise PDF.js text-match rectangles and logical left/right split-page mapping
|
|
21
|
+
- replaced full-page search tint with lightweight text-position highlights
|
|
22
|
+
- hardened DOMWise search result rendering so result buttons are not stringified
|
|
23
|
+
- unified search and note focus styling with a single thin accent border and glow
|
|
24
|
+
- disabled text search in image/WebP page-list mode with localized explanation; download URL handling remains independent
|
|
25
|
+
- added localized image-mode messaging and regression coverage
|
|
26
|
+
|
|
27
|
+
## 0.6.5
|
|
28
|
+
|
|
29
|
+
- added automatic A3 landscape PDF splitting with configurable auto, single, and split modes
|
|
30
|
+
- added source-page-aware lazy rendering for split PDF pages
|
|
31
|
+
- added optional light/dark viewer backgrounds and responsive presentation gutters
|
|
32
|
+
- enlarged the opt-in thumbnail rail and moved page labels into transparent, high-contrast overlays
|
|
33
|
+
- kept thumbnail labels black in both themes and preserved a thin neon selected state
|
|
34
|
+
- enabled native mobile scrolling to avoid non-cancelable touchstart interventions
|
|
35
|
+
- fixed single-view PDF hydration after switching from spread mode
|
|
36
|
+
- added regression coverage for PDF splitting, backgrounds, presentation layout, and PDF hydration
|
|
37
|
+
|
|
38
|
+
## 0.6.0
|
|
4
39
|
|
|
5
40
|
- added a localized, theme-aware Table of Contents panel with nested host-provided page entries
|
|
6
41
|
- added TOC visibility events, page navigation, normalization, accessibility, and regression tests
|
|
@@ -58,5 +93,4 @@
|
|
|
58
93
|
- introduced dual-license documentation structure
|
|
59
94
|
- prepared package metadata for public distribution
|
|
60
95
|
- preserved legacy `BizekaFlipEngine` compatibility alias
|
|
61
|
-
- added contribution, security, and trademark policy documents
|
|
62
|
-
|
|
96
|
+
- added contribution, security, and trademark policy documents
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# FlipbookEngine
|
|
2
2
|
|
|
3
|
-
> **Release
|
|
4
|
-
> **
|
|
3
|
+
> **Release candidate:** `flipbookengine@1.0.0` is prepared as the first stable release and includes the localized Table of Contents API.
|
|
4
|
+
> **Release scope:** Version 1.0.0 adds the plugin contract, independent feature entrypoints, TOC runtime/embed APIs, and the complete open-source reader surface.
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/flipbookengine)
|
|
7
7
|
[](https://github.com/Bizeka/flipbook-engine/blob/main/LICENSE)
|
|
@@ -21,6 +21,11 @@ FlipbookEngine is a modern, lightweight, and embeddable HTML flipbook viewer for
|
|
|
21
21
|
- **Multi-Language (i18n)**: Out-of-the-box support for English (`en`) and Turkish (`tr`) with customizable overrides.
|
|
22
22
|
- **Framework Wrappers**: Direct React and Vue wrapper exports for seamless modern integration.
|
|
23
23
|
- **Progressive PDF Rendering**: PDF pages render on demand with bounded concurrency and an instance-local LRU cache, keeping large documents responsive.
|
|
24
|
+
- **Localized Sharing**: The toolbar includes a Share control that opens the native share sheet or copies the current page URL; enable `deepLink: true` for shareable page navigation.
|
|
25
|
+
- **Host-Managed Bookmarks**: The toolbar can toggle the current page bookmark; hosts can initialize and persist zero-based bookmark indexes through the public API and `bookmarkChange` event.
|
|
26
|
+
- **Host-Managed Notes**: The localized notes toolbar opens an inline editor; hosts can initialize, update, and persist page notes through the public API and `noteChange` event without coupling the viewer to a storage backend.
|
|
27
|
+
- **Client-Side PDF Search**: Extracts and searches PDF text on demand with localized snippets and normalized text-rectangle highlighting.
|
|
28
|
+
- **Interactive Hotspots**: Adds normalized page overlays with accessible plain-text popups and optional links.
|
|
24
29
|
|
|
25
30
|
## Installation
|
|
26
31
|
|
|
@@ -45,18 +50,23 @@ import pdfWorkerSrc from 'pdfjs-dist/build/pdf.worker.mjs?url';
|
|
|
45
50
|
|
|
46
51
|
const engine = new FlipbookEngine('#viewer', {
|
|
47
52
|
allowDownload: true,
|
|
48
|
-
showThumbs:
|
|
53
|
+
showThumbs: false,
|
|
49
54
|
primaryColor: '#7367f0',
|
|
50
55
|
theme: 'auto',
|
|
51
56
|
locale: 'en',
|
|
52
57
|
pdfWorkerSrc,
|
|
53
|
-
pdfRenderCacheSize: 32
|
|
58
|
+
pdfRenderCacheSize: 32,
|
|
59
|
+
pdfPageMode: 'auto',
|
|
60
|
+
background: {
|
|
61
|
+
light: { color: '#f8fafc', image: '/branding/light.webp', size: 'cover' },
|
|
62
|
+
dark: { color: '#0f172a', image: '/branding/dark.webp', size: 'cover' }
|
|
63
|
+
}
|
|
54
64
|
});
|
|
55
65
|
|
|
56
66
|
await engine.init('/files/catalog.pdf');
|
|
57
67
|
```
|
|
58
68
|
|
|
59
|
-
Passing `pages` remains optional. When omitted, FlipbookEngine creates the page structure from `pdfUrl`, renders the first page before `init` resolves, and prefetches the next page. Additional pages render as they become visible or are selected.
|
|
69
|
+
Passing `pages` remains optional. When omitted, FlipbookEngine creates the page structure from `pdfUrl`, renders the first page before `init` resolves, and prefetches the next page. Additional pages render as they become visible or are selected. In `pdfPageMode: 'auto'` (the default), ISO A3 landscape pages are normalized into two logical pages; use `'single'` to keep every PDF page intact or `'split'` to split every landscape PDF page.
|
|
60
70
|
|
|
61
71
|
`pdfRenderCacheSize` controls the per-instance LRU cache (default `32`, set to `0` to disable it).
|
|
62
72
|
|
|
@@ -65,7 +75,7 @@ Passing `pages` remains optional. When omitted, FlipbookEngine creates the page
|
|
|
65
75
|
Use the ESM build with an import map for PDF.js. The worker must be served from a URL your site permits in its Content Security Policy.
|
|
66
76
|
|
|
67
77
|
```html
|
|
68
|
-
<link rel="stylesheet" href="https://unpkg.com/flipbookengine@0.
|
|
78
|
+
<link rel="stylesheet" href="https://unpkg.com/flipbookengine@1.0.0/dist/flipbook-engine.css" />
|
|
69
79
|
<div id="viewer" style="width: 100%; height: 600px;"></div>
|
|
70
80
|
|
|
71
81
|
<script type="importmap">
|
|
@@ -76,7 +86,7 @@ Use the ESM build with an import map for PDF.js. The worker must be served from
|
|
|
76
86
|
}
|
|
77
87
|
</script>
|
|
78
88
|
<script type="module">
|
|
79
|
-
import { FlipbookEngine } from 'https://unpkg.com/flipbookengine@0.
|
|
89
|
+
import { FlipbookEngine } from 'https://unpkg.com/flipbookengine@1.0.0/dist/flipbook-engine.js';
|
|
80
90
|
|
|
81
91
|
const engine = new FlipbookEngine('#viewer', {
|
|
82
92
|
pdfWorkerSrc: 'https://unpkg.com/pdfjs-dist@5.4.530/build/pdf.worker.min.mjs'
|
|
@@ -140,6 +150,34 @@ const pages = [
|
|
|
140
150
|
</script>
|
|
141
151
|
```
|
|
142
152
|
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
## Iframe embedding
|
|
156
|
+
|
|
157
|
+
For a viewer hosted in an iframe, connect the bridge from the iframe document and allow only the parent origin:
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
const engine = new FlipbookEngine('#viewer', { showThumbs: false });
|
|
161
|
+
engine.connectEmbed({
|
|
162
|
+
allowedOrigins: ['https://catalog.example.com']
|
|
163
|
+
});
|
|
164
|
+
await engine.init('/files/catalog.pdf');
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
From the parent page, use the controller exported by the package:
|
|
168
|
+
|
|
169
|
+
```javascript
|
|
170
|
+
import { createFlipbookEmbedController } from 'flipbookengine';
|
|
171
|
+
|
|
172
|
+
const controller = createFlipbookEmbedController(
|
|
173
|
+
document.querySelector('#catalog-frame'),
|
|
174
|
+
{ targetOrigin: 'https://viewer.example.com' }
|
|
175
|
+
);
|
|
176
|
+
await controller.goToPage(2);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Always configure explicit origins for cross-origin embeds. The bridge supports page navigation, zoom, single mode, option updates, fullscreen, TOC read/update, search, state queries, and event forwarding.
|
|
180
|
+
|
|
143
181
|
## Migration Notes
|
|
144
182
|
|
|
145
183
|
Upgrading from 0.3.x to 0.4.0 keeps the public engine methods intact. The release isolates state per engine instance, makes wrapper updates lifecycle-safe, and scopes viewer markup to its container. If host CSS or automation selected the former fixed viewer IDs, migrate those selectors to the instance classes documented in the theming guide. PDF-backed consumers should configure `pdfWorkerSrc`; image-only viewers do not expose a download control.
|
|
@@ -147,6 +185,8 @@ Upgrading from 0.3.x to 0.4.0 keeps the public engine methods intact. The releas
|
|
|
147
185
|
For 0.5.0 behavior, see the [0.5.0 migration guide](./docs/migration-0.5.0.md). PDF-backed viewers now render on demand; callers should use `progress` and `error` events for rendering telemetry.
|
|
148
186
|
|
|
149
187
|
|
|
188
|
+
For the 1.0.0 migration and the 0.x compatibility boundary, see the [1.0.0 migration guide](./docs/migration-1.0.0.md).
|
|
189
|
+
|
|
150
190
|
## Public API Reference
|
|
151
191
|
|
|
152
192
|
The `FlipbookEngine` class exposes the following public methods:
|
|
@@ -161,6 +201,13 @@ The `FlipbookEngine` class exposes the following public methods:
|
|
|
161
201
|
- **`toggleFullscreen()`**: Programmatically toggles fullscreen mode.
|
|
162
202
|
- **`updateOptions(options: Partial<FlipbookEngineOptions>)`**: Updates instance options at runtime.
|
|
163
203
|
- **`setLocale(locale: string, messages?: PartialFlipbookMessages | Record<string, PartialFlipbookMessages>)`**: Updates the locale programmatically and optionally overrides messages for that locale.
|
|
204
|
+
- **`getPageUrl(pageIndex = getCurrentPage())`**: Returns a shareable URL for a 0-based page index.
|
|
205
|
+
- **`sharePage(pageIndex = getCurrentPage())`**: Opens the native share dialog or copies the page URL to the clipboard. The toolbar exposes this behavior through a localized Share button.
|
|
206
|
+
- **`getBookmarkedPages()`**: Returns the sorted zero-based bookmark indexes.
|
|
207
|
+
- **`isBookmarked(pageIndex = getCurrentPage())`**: Checks whether a page is bookmarked.
|
|
208
|
+
- **`setBookmark(pageIndex, bookmarked)`** / **`toggleBookmark(pageIndex)`**: Updates bookmark state and emits `bookmarkChange`; hosts can persist the event payload.
|
|
209
|
+
- **`getNotes()`** / **`getNote(pageIndex)`**: Reads host-managed page notes.
|
|
210
|
+
- **`setNote(pageIndex, note)`** / **`clearNote(pageIndex)`**: Updates notes and emits `noteChange`; empty notes are removed. The toolbar editor is intentionally host-storage agnostic, so a backend can persist each event later.
|
|
164
211
|
- **`destroy(keepContainer = false)`**: Tears down the instance and listeners; when `true`, keeps the container markup for an immediate reinitialization.
|
|
165
212
|
|
|
166
213
|
### Subscribing to Events
|
|
@@ -176,7 +223,7 @@ const unsubscribe = engine.on('pageChange', ({ currentPage, totalPages, isSingle
|
|
|
176
223
|
unsubscribe();
|
|
177
224
|
```
|
|
178
225
|
|
|
179
|
-
Supported events: `init`, `progress`, `pageChange`, `zoomChange`, `singlePageModeChange`, `thumbsToggle`, `tocToggle`, `orientationChange`, `error`, `destroy`.
|
|
226
|
+
Supported events: `init`, `progress`, `pageChange`, `zoomChange`, `singlePageModeChange`, `thumbsToggle`, `tocToggle`, `orientationChange`, `deepLinkChange`, `bookmarkChange`, `noteChange`, `searchChange`, `hotspotActivate`, `annotationActivate`, `error`, `destroy`.
|
|
180
227
|
|
|
181
228
|
| Option | Type | Default | Description |
|
|
182
229
|
| :--- | :--- | :--- | :--- |
|
|
@@ -192,6 +239,19 @@ Supported events: `init`, `progress`, `pageChange`, `zoomChange`, `singlePageMod
|
|
|
192
239
|
| `pdfWorkerSrc` | `string` | - | URL of the PDF.js worker emitted or hosted by the consuming application. |
|
|
193
240
|
| `pdfRenderConcurrency` | `number` | `3` | Maximum number of PDF pages rendered concurrently when on-demand pages are requested. |
|
|
194
241
|
| `pdfRenderCacheSize` | `number` | `32` | Maximum number of rendered PDF page images retained per engine instance (LRU); `0` disables caching. |
|
|
242
|
+
| `pdfPageMode` | `'auto' \| 'single' \| 'split'` | `'auto'` | Controls PDF page splitting: A3 landscape pages are split automatically, all landscape pages can be split explicitly, or splitting can be disabled. |
|
|
243
|
+
| `background` | `FlipbookBackgrounds \| null` | `null` | Optional light/dark viewer backgrounds with color, image, size, position, and repeat settings. |
|
|
244
|
+
| `deepLink` | `boolean` | `false` | Keeps the active page synchronized with a `?page=` URL parameter. The localized toolbar Share control uses this URL format. |
|
|
245
|
+
| `bookmarks` | `number[]` | `[]` | Initial zero-based bookmarked page indexes; the host owns persistence. |
|
|
246
|
+
| `notes` | `Record<number, string>` | `{}` | Initial page notes keyed by zero-based page index; the notes toolbar edits them while the host owns persistence. |
|
|
247
|
+
| `hotspots` | `FlipbookHotspot[]` | `[]` | Normalized (0..1) page overlays with info/media/gallery/commerce popup content and optional links. |
|
|
248
|
+
| `annotations` | `FlipbookAnnotation[]` | `[]` | Host-managed page note markers with normalized coordinates and plain-text popup content. |
|
|
249
|
+
| `onShare` | `(url: string) => void` | `null` | Optional callback invoked after the toolbar shares or copies the generated page URL. |
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
## PDF page formats
|
|
253
|
+
|
|
254
|
+
PDF.js page dimensions are detected at runtime, so portrait A4, landscape A4, and other page ratios are supported without a fixed size preset. A3 landscape pages are split into left/right logical pages when `pdfPageMode` is `'auto'` or `'split'`; the halves are presented as an A4-like spread in double-page mode.
|
|
195
255
|
|
|
196
256
|
## Styling and Theming
|
|
197
257
|
|
|
@@ -242,13 +302,13 @@ When choosing a flipbook library, here is how we compare to other solutions:
|
|
|
242
302
|
A special thanks to the incredible team behind **[Serenity](https://github.com/serenity-is/serenity)**. FlipbookEngine's reactive UI layer is powered by **[domwise](https://github.com/serenity-is/serenity/tree/master/packages/domwise)**. Coupled with `@preact/signals-core`, this keeps the UI update path small without requiring a traditional Virtual DOM runtime.
|
|
243
303
|
|
|
244
304
|
---
|
|
245
|
-
##
|
|
305
|
+
## Release scope
|
|
246
306
|
|
|
247
|
-
FlipbookEngine
|
|
307
|
+
FlipbookEngine ships an AGPL open-source viewer package and maintains a separate closed-source commercial backend roadmap.
|
|
248
308
|
|
|
249
309
|
### Open-source v1.0.0 (AGPL viewer)
|
|
250
310
|
|
|
251
|
-
The npm package
|
|
311
|
+
The npm package is an embeddable, framework-agnostic PDF viewer. The following client-side reader capabilities are included in the open-source v1.0.0 release:
|
|
252
312
|
|
|
253
313
|
- **Table of Contents (Index):** Interactive navigation to chapters or product categories.
|
|
254
314
|
- **Page Notes & Annotations:** Reader notes and bookmarks stored by the host application.
|
|
@@ -258,6 +318,47 @@ The npm package remains an embeddable, framework-agnostic PDF viewer. The open-s
|
|
|
258
318
|
|
|
259
319
|
The open-source viewer continues to use PDF.js as an external npm dependency and does not require a backend renderer.
|
|
260
320
|
|
|
321
|
+
The v1.0.0 release also defines the framework-agnostic plugin contract. The rendering core stays small while TOC, notes, bookmarks, annotations, search, hotspots, and sharing can be installed as optional plugins. Analytics is not shipped as an official open-source plugin; hosts can consume the documented events or use a private commercial adapter. See [Plugin architecture](./docs/plugin-architecture.md).
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
### Plugin usage and activation
|
|
325
|
+
|
|
326
|
+
Version 1.0.0 keeps the all-in-one entry point for existing applications and adds optional, tree-shakeable feature adapters. A plugin is active only when it is supplied in the constructor or installed at runtime. Omitting an adapter keeps it inactive.
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
import { FlipbookEngine } from 'flipbookengine/core';
|
|
330
|
+
import { notesPlugin } from 'flipbookengine/plugins/notes';
|
|
331
|
+
import { bookmarksPlugin } from 'flipbookengine/plugins/bookmarks';
|
|
332
|
+
|
|
333
|
+
const engine = new FlipbookEngine('#viewer', {
|
|
334
|
+
plugins: [notesPlugin, bookmarksPlugin]
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
await engine.callPluginApi('notes', 'set', 0, 'Review this page');
|
|
338
|
+
console.log(engine.getPluginNames());
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Disable or remove a feature at runtime with `uninstallPlugin(name)`. This removes the plugin APIs, toolbar/panel contributions, event subscriptions, and cleanup callbacks. Re-enable it with `installPlugin(plugin)`:
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
engine.uninstallPlugin('notes');
|
|
345
|
+
engine.installPlugin(notesPlugin);
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
The official notes, bookmarks, TOC, search, annotations, hotspots, share, and deep-link adapters expose namespaced APIs. Their UI is still controlled by the host/all-in-one viewer options; custom plugins may additionally register toolbar buttons and panels through the plugin contract. Analytics is not included as an official open-source adapter.
|
|
349
|
+
|
|
350
|
+
### 0.8.0 to 1.0.0 compatibility boundary
|
|
351
|
+
|
|
352
|
+
Version 1.0.0 is the first stable compatibility boundary. The 0.8.0 line was alpha/beta and does not provide a rollback or compatibility guarantee.
|
|
353
|
+
|
|
354
|
+
- The documented all-in-one import and engine options remain available.
|
|
355
|
+
- Imports from undocumented internal `src/*` or generated `dist/*` files are not supported; move to `flipbookengine/core`, `flipbookengine/plugins`, or the documented feature subpaths.
|
|
356
|
+
- Optional adapters are explicit: pass them through `plugins`, call `installPlugin()` to enable, and `uninstallPlugin()` to disable and clean up their APIs, UI contributions, and event listeners.
|
|
357
|
+
- TOC runtime/embed APIs and expanded hotspot media/gallery/commerce fields are new 1.0 APIs; existing host-managed data remains the source of truth.
|
|
358
|
+
- Image/WebP text search remains unsupported; PDF mode is required unless the host supplies server-generated text metadata.
|
|
359
|
+
|
|
360
|
+
See the complete [1.0.0 migration guide](./docs/migration-1.0.0.md) before upgrading from 0.8.0.
|
|
361
|
+
|
|
261
362
|
### Commercial edition (closed-source backend)
|
|
262
363
|
|
|
263
364
|
The commercial roadmap is separate from the AGPL package and is intended for a separate backend project. It will provide licensed server-side capabilities, including:
|
|
@@ -282,3 +383,41 @@ For commercial licenses and inquiries, contact: **murat.dogan@hotmail.com.tr**
|
|
|
282
383
|
|
|
283
384
|
|
|
284
385
|
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
### Client-side PDF search
|
|
389
|
+
|
|
390
|
+
When initialized with a PDF URL, `search(query)` extracts text through PDF.js without rendering every page. It returns page-level matches and snippets, updates the search toolbar panel, and overlays precise normalized rectangles over matching text when PDF.js exposes text geometry. Search results use a zero-based `pageIndex` for API navigation and a one-based `pageNumber` for display.
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
const results = await engine.search('catalog', { caseSensitive: false, maxResults: 50 });
|
|
394
|
+
engine.goToPage(results[0]?.pageIndex ?? 0);
|
|
395
|
+
engine.clearSearch();
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Search is unavailable for image-only page lists because those assets do not contain extractable PDF text or text geometry. For image mode, applications that need search/highlights should generate page text and normalized coordinates on the server and pass the resulting page metadata as a host-side feature; the open-source viewer does not OCR raster images. The iframe controller exposes the same operation with `search`, `clearSearch`, and `getSearchResults`.
|
|
399
|
+
|
|
400
|
+
### Interactive hotspots
|
|
401
|
+
|
|
402
|
+
Hosts can provide normalized (0..1) page coordinates for lightweight links and pop-ups:
|
|
403
|
+
|
|
404
|
+
```ts
|
|
405
|
+
const engine = new FlipbookEngine('#viewer', {
|
|
406
|
+
hotspots: [{ id: 'product-42', pageIndex: 3, x: 0.60, y: 0.25, width: 0.25, height: 0.18, label: 'Product details', content: 'Open the product details page.', href: '/products/42' }]
|
|
407
|
+
});
|
|
408
|
+
engine.on('hotspotActivate', ({ hotspot }) => console.log(hotspot.id));
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Hotspots support `kind: 'info' | 'media' | 'gallery' | 'commerce'`. A hotspot can render a single image/video/audio preview through `media`, a selectable image gallery through `gallery`, and a safe external/product destination through `href`. Content remains plain text; applications should sanitize server-provided URLs before passing them to the viewer. Use `activateHotspot(id)` and `closeHotspot()` for programmatic control.
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
### Page annotations
|
|
415
|
+
|
|
416
|
+
Host uygulamaları, kullanıcı notunu sayfa üzerindeki normalize koordinata bağlamak için `annotations` seçeneğini kullanabilir. Marker tıklaması popup açar ve `annotationActivate` olayı yayınlanır. Bu sözleşme şimdilik host-managed'dir; annotation kayıtlarının backend koordinatlarına taşınması tüketici uygulamanın sorumluluğundadır.
|
|
417
|
+
|
|
418
|
+
```ts
|
|
419
|
+
const engine = new FlipbookEngine('#viewer', {
|
|
420
|
+
annotations: [{ id: 'note-1', pageIndex: 4, x: .42, y: .36, text: 'Review pricing' }]
|
|
421
|
+
});
|
|
422
|
+
```
|
|
423
|
+
|
package/dist/components/App.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { FlipbookSearchOptions } from '../model/search';
|
|
2
|
+
import { FlipbookHotspot } from '../model/hotspots';
|
|
3
|
+
import { FlipbookAnnotation } from '../model/annotations';
|
|
1
4
|
import { FlipbookStore } from '../state/store';
|
|
2
5
|
import { PageFlipAdapter } from '../adapters/PageFlipAdapter';
|
|
3
6
|
import { InteractionManager } from '../core/InteractionManager';
|
|
7
|
+
import { FlipbookPluginRegistry } from '../plugins';
|
|
4
8
|
|
|
5
9
|
interface AppProps {
|
|
6
10
|
pageFlipAdapterRef: {
|
|
@@ -14,8 +18,23 @@ interface AppProps {
|
|
|
14
18
|
bookContainerRef: (el: HTMLElement) => void;
|
|
15
19
|
className?: string;
|
|
16
20
|
onDownload: () => void;
|
|
21
|
+
onShare: () => void;
|
|
22
|
+
onToggleBookmark: () => void;
|
|
23
|
+
onToggleNotes: () => void;
|
|
24
|
+
onSaveNote: (note: string) => void;
|
|
25
|
+
onClearNote: () => void;
|
|
26
|
+
onCloseNotes: () => void;
|
|
27
|
+
onSearch: (query: string, options?: FlipbookSearchOptions) => void;
|
|
28
|
+
onClearSearch: () => void;
|
|
29
|
+
onCloseSearch: () => void;
|
|
30
|
+
onSelectSearchResult: (pageIndex: number) => void;
|
|
31
|
+
onHotspotActivate: (hotspot: FlipbookHotspot) => void;
|
|
32
|
+
onHotspotClose: () => void;
|
|
33
|
+
onAnnotationActivate: (annotation: FlipbookAnnotation) => void;
|
|
34
|
+
onAnnotationClose: () => void;
|
|
17
35
|
onToggleFullscreen: () => void;
|
|
18
36
|
store: FlipbookStore;
|
|
37
|
+
pluginRegistry?: FlipbookPluginRegistry;
|
|
19
38
|
}
|
|
20
39
|
export declare function App(props: AppProps): import('@serenity-is/domwise').JSXElement;
|
|
21
40
|
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FlipbookHotspot } from '../model/hotspots';
|
|
2
|
+
import { FlipbookAnnotation } from '../model/annotations';
|
|
3
|
+
import { FlipbookStore } from '../state/store';
|
|
4
|
+
|
|
5
|
+
interface HotspotLayerProps {
|
|
6
|
+
store: FlipbookStore;
|
|
7
|
+
pageIndex: number;
|
|
8
|
+
onActivate: (hotspot: FlipbookHotspot) => void;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
onAnnotationActivate: (annotation: FlipbookAnnotation) => void;
|
|
11
|
+
onAnnotationClose: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function HotspotLayer(props: HotspotLayerProps): import('@serenity-is/domwise').JSXElement;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FlipbookStore } from '../state/store';
|
|
2
|
+
|
|
3
|
+
interface NotesPanelProps {
|
|
4
|
+
store: FlipbookStore;
|
|
5
|
+
onSave: (note: string) => void;
|
|
6
|
+
onClear: () => void;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Page-level note UI. Persistence remains host-owned through the engine API and
|
|
11
|
+
* noteChange event; the panel intentionally does not know about a backend.
|
|
12
|
+
*/
|
|
13
|
+
export declare function NotesPanel(props: NotesPanelProps): import('@serenity-is/domwise').JSXElement;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FlipbookStore } from '../state/store';
|
|
2
|
+
|
|
3
|
+
interface SearchPanelProps {
|
|
4
|
+
store: FlipbookStore;
|
|
5
|
+
onSearch: (query: string) => void;
|
|
6
|
+
onClear: () => void;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
onSelect: (pageIndex: number) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function SearchPanel(props: SearchPanelProps): import('@serenity-is/domwise').JSXElement;
|
|
11
|
+
export {};
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { FlipbookStore } from '../state/store';
|
|
2
|
+
import { FlipbookPluginRegistry } from '../plugins';
|
|
2
3
|
|
|
3
4
|
interface ToolbarProps {
|
|
4
5
|
store: FlipbookStore;
|
|
5
6
|
onToggleThumbs: () => void;
|
|
6
7
|
onToggleToc: () => void;
|
|
8
|
+
onToggleSearch: () => void;
|
|
7
9
|
onToggleSingleMode: () => void;
|
|
8
10
|
onZoomIn: () => void;
|
|
9
11
|
onZoomOut: () => void;
|
|
10
12
|
onDownload?: () => void;
|
|
13
|
+
onShare: () => void;
|
|
14
|
+
onToggleBookmark: () => void;
|
|
15
|
+
onToggleNotes: () => void;
|
|
11
16
|
onSoundToggle: () => void;
|
|
12
17
|
onNextPage: () => void;
|
|
13
18
|
onPrevPage: () => void;
|
|
14
19
|
onToggleAutoPlay: () => void;
|
|
15
20
|
onToggleFullscreen: () => void;
|
|
21
|
+
pluginRegistry?: FlipbookPluginRegistry;
|
|
16
22
|
}
|
|
17
23
|
export declare function Toolbar(props: ToolbarProps): import('@serenity-is/domwise').JSXElement;
|
|
18
24
|
export {};
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { FlipbookStore } from '../state/store';
|
|
2
|
+
import { FlipbookHotspot } from '../model/hotspots';
|
|
3
|
+
import { FlipbookAnnotation } from '../model/annotations';
|
|
2
4
|
|
|
3
5
|
interface ViewerProps {
|
|
4
6
|
store: FlipbookStore;
|
|
5
7
|
bookWrapperRef: (el: HTMLElement) => void;
|
|
6
8
|
bookSizerRef: (el: HTMLElement) => void;
|
|
7
9
|
bookContainerRef: (el: HTMLElement) => void;
|
|
10
|
+
onHotspotActivate: (hotspot: FlipbookHotspot) => void;
|
|
11
|
+
onHotspotClose: () => void;
|
|
12
|
+
onAnnotationActivate: (annotation: FlipbookAnnotation) => void;
|
|
13
|
+
onAnnotationClose: () => void;
|
|
8
14
|
}
|
|
9
15
|
export declare function Viewer(props: ViewerProps): import('@serenity-is/domwise').JSXElement;
|
|
10
16
|
export {};
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { NormalizedFlipbookPage } from '../model/pages';
|
|
2
|
+
import { FlipbookSearchOptions, FlipbookSearchHighlight } from '../model/search';
|
|
2
3
|
|
|
3
4
|
export interface PdfRenderProgress {
|
|
4
5
|
completed: number;
|
|
5
6
|
total: number;
|
|
6
7
|
}
|
|
8
|
+
export type PdfPageMode = 'auto' | 'single' | 'split';
|
|
9
|
+
export interface PdfPageLayout {
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
split: boolean;
|
|
13
|
+
}
|
|
14
|
+
/** Detects ISO A3 landscape pages while allowing PDF metadata rounding and bleed. */
|
|
15
|
+
export declare function isA3Landscape(width: number, height: number): boolean;
|
|
7
16
|
export interface PdfRenderOptions {
|
|
8
17
|
scale?: number;
|
|
9
18
|
quality?: number;
|
|
@@ -17,13 +26,25 @@ export declare class PdfRenderer {
|
|
|
17
26
|
private loadingTask;
|
|
18
27
|
private options;
|
|
19
28
|
private readonly cache;
|
|
29
|
+
private readonly textCache;
|
|
20
30
|
constructor(options?: PdfRenderOptions);
|
|
21
31
|
/** Loads a PDF document and cancels PDF.js loading when the signal aborts. */
|
|
22
32
|
loadDocument(pdfUrl: string, signal?: AbortSignal): Promise<number>;
|
|
23
33
|
/** Renders a specific page to a Data URL. The page index is 1-based. */
|
|
24
34
|
renderPageToDataUrl(pageIndex: number, signal?: AbortSignal): Promise<string>;
|
|
25
|
-
/**
|
|
26
|
-
|
|
35
|
+
/** Extracts text from a 1-based PDF source page using PDF.js text content. */
|
|
36
|
+
extractPageText(pageNumber: number): Promise<string>;
|
|
37
|
+
/** Searches all PDF source pages and returns normalized rectangles for matched text. */
|
|
38
|
+
searchText(query: string, options?: FlipbookSearchOptions): Promise<Array<{
|
|
39
|
+
sourcePageNumber: number;
|
|
40
|
+
matches: number;
|
|
41
|
+
snippet: string;
|
|
42
|
+
highlights?: FlipbookSearchHighlight[];
|
|
43
|
+
}>>;
|
|
44
|
+
/** Returns source page dimensions and whether the page should be split. */
|
|
45
|
+
getPageLayouts(mode?: PdfPageMode): Promise<PdfPageLayout[]>;
|
|
46
|
+
/** Calculates the best viewport dimensions based on the first logical page. */
|
|
47
|
+
calculateViewportDimensions(baseShortSide?: number, firstPageLayout?: PdfPageLayout): Promise<{
|
|
27
48
|
width: number;
|
|
28
49
|
height: number;
|
|
29
50
|
}>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license FlipbookEngine v1.0.0
|
|
3
|
+
* Copyright (c) 2026 Murat Dogan
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
*/
|
|
6
|
+
export { FlipbookEngine, type FlipbookEngineOptions, type FlipbookLocaleMessages, type PageImages, type FlipbookEngineEventMap, type FlipbookEngineEventName } from './engine';
|
|
7
|
+
export type { FlipbookPageAsset, FlipbookPageKind, FlipbookCropMode, FlipbookSplitDirection, NormalizedFlipbookPage } from './model/pages';
|
|
8
|
+
export { normalizeFlipbookPages, isFlipbookPageAsset } from './model/pages';
|
|
9
|
+
export type { FlipbookLocale, FlipbookMessages, PartialFlipbookMessages } from './i18n/service';
|
|
10
|
+
export type { FlipbookThemeMode, FlipbookBackgroundStyle, FlipbookBackgrounds } from './theme/theme';
|
|
11
|
+
export type { PdfPageMode, PdfPageLayout } from './core/PdfRenderer';
|
|
12
|
+
export { isA3Landscape } from './core/PdfRenderer';
|
|
13
|
+
export type { FlipbookHotspot, FlipbookHotspotKind, FlipbookHotspotMedia, FlipbookHotspotMediaType, FlipbookHotspotGalleryItem } from './model/hotspots';
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './core-entry'
|
package/dist/embed.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { FlipbookEngine, FlipbookEngineEventMap, FlipbookEngineEventName, FlipbookEngineOptions } from './engine';
|
|
2
|
+
import { FlipbookSearchOptions, FlipbookSearchResult } from './model/search';
|
|
3
|
+
import { FlipbookTocEntry } from './model/toc';
|
|
4
|
+
|
|
5
|
+
export type FlipbookEmbedCommandName = 'goToPage' | 'nextPage' | 'prevPage' | 'setZoom' | 'setSingleMode' | 'updateOptions' | 'toggleFullscreen' | 'search' | 'clearSearch' | 'getSearchResults' | 'getToc' | 'setToc' | 'getState';
|
|
6
|
+
export interface FlipbookEmbedOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Origins allowed to send commands. Defaults to the current origin.
|
|
9
|
+
* Use an explicit origin for cross-origin iframe integrations.
|
|
10
|
+
*/
|
|
11
|
+
allowedOrigins?: string[];
|
|
12
|
+
/** Origin used for messages sent to the embedding parent. */
|
|
13
|
+
targetOrigin?: string;
|
|
14
|
+
/** Response timeout for the parent-side controller. */
|
|
15
|
+
responseTimeout?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface FlipbookEmbedCommand {
|
|
18
|
+
type: 'flipbook:command';
|
|
19
|
+
command: FlipbookEmbedCommandName;
|
|
20
|
+
requestId?: string;
|
|
21
|
+
payload?: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface FlipbookEmbedEvent<T extends FlipbookEngineEventName = FlipbookEngineEventName> {
|
|
24
|
+
type: 'flipbook:event';
|
|
25
|
+
event: T;
|
|
26
|
+
payload: FlipbookEngineEventMap[T];
|
|
27
|
+
}
|
|
28
|
+
export interface FlipbookEmbedResponse {
|
|
29
|
+
type: 'flipbook:response';
|
|
30
|
+
requestId?: string;
|
|
31
|
+
ok: boolean;
|
|
32
|
+
result?: unknown;
|
|
33
|
+
error?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface FlipbookEmbedState {
|
|
36
|
+
currentPage: number;
|
|
37
|
+
totalPages: number;
|
|
38
|
+
zoom: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Runs inside an iframe and exposes a restricted postMessage command bridge.
|
|
42
|
+
* Commands are accepted only from window.parent and configured origins.
|
|
43
|
+
*/
|
|
44
|
+
export declare class FlipbookEmbedBridge {
|
|
45
|
+
private readonly engine;
|
|
46
|
+
private readonly options;
|
|
47
|
+
private readonly listener;
|
|
48
|
+
private readonly unsubs;
|
|
49
|
+
private connected;
|
|
50
|
+
private parentOrigin;
|
|
51
|
+
constructor(engine: FlipbookEngine, options?: FlipbookEmbedOptions);
|
|
52
|
+
connect(): this;
|
|
53
|
+
disconnect(): void;
|
|
54
|
+
private readonly engineEventNames;
|
|
55
|
+
private isAllowedOrigin;
|
|
56
|
+
private post;
|
|
57
|
+
private postEvent;
|
|
58
|
+
private respond;
|
|
59
|
+
private handleMessage;
|
|
60
|
+
private getState;
|
|
61
|
+
}
|
|
62
|
+
export interface FlipbookEmbedController {
|
|
63
|
+
send(command: FlipbookEmbedCommandName, payload?: unknown): Promise<unknown>;
|
|
64
|
+
goToPage(pageIndex: number): Promise<FlipbookEmbedState>;
|
|
65
|
+
nextPage(): Promise<FlipbookEmbedState>;
|
|
66
|
+
prevPage(): Promise<FlipbookEmbedState>;
|
|
67
|
+
setZoom(zoom: number): Promise<FlipbookEmbedState>;
|
|
68
|
+
setSingleMode(isSingle: boolean): Promise<FlipbookEmbedState>;
|
|
69
|
+
updateOptions(options: Partial<FlipbookEngineOptions>): Promise<FlipbookEmbedState>;
|
|
70
|
+
toggleFullscreen(): Promise<FlipbookEmbedState>;
|
|
71
|
+
search(query: string, options?: FlipbookSearchOptions): Promise<FlipbookSearchResult[]>;
|
|
72
|
+
clearSearch(): Promise<FlipbookEmbedState>;
|
|
73
|
+
getSearchResults(): Promise<FlipbookSearchResult[]>;
|
|
74
|
+
getToc(): Promise<FlipbookTocEntry[]>;
|
|
75
|
+
setToc(entries: FlipbookTocEntry[], show?: boolean): Promise<FlipbookEmbedState>;
|
|
76
|
+
getState(): Promise<FlipbookEmbedState>;
|
|
77
|
+
on<T extends FlipbookEngineEventName>(event: T, handler: (payload: FlipbookEngineEventMap[T]) => void): () => void;
|
|
78
|
+
destroy(): void;
|
|
79
|
+
}
|
|
80
|
+
export declare function createFlipbookEmbedController(iframe: HTMLIFrameElement, options?: FlipbookEmbedOptions): FlipbookEmbedController;
|