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.
Files changed (91) hide show
  1. package/CHANGELOG.md +37 -3
  2. package/README.md +150 -11
  3. package/dist/components/App.d.ts +19 -0
  4. package/dist/components/HotspotLayer.d.ts +14 -0
  5. package/dist/components/NotesPanel.d.ts +14 -0
  6. package/dist/components/PluginPanels.d.ts +5 -0
  7. package/dist/components/SearchPanel.d.ts +11 -0
  8. package/dist/components/Toolbar.d.ts +6 -0
  9. package/dist/components/Viewer.d.ts +6 -0
  10. package/dist/core/LayoutManager.d.ts +1 -1
  11. package/dist/core/PdfRenderer.d.ts +23 -2
  12. package/dist/core-entry.d.ts +13 -0
  13. package/dist/core.d.ts +1 -0
  14. package/dist/embed.d.ts +80 -0
  15. package/dist/engine-Dt2Fn6O-.js +4060 -0
  16. package/dist/engine-Dt2Fn6O-.js.map +1 -0
  17. package/dist/engine.d.ts +111 -1
  18. package/dist/feature-Cicli9ie.js +17 -0
  19. package/dist/feature-Cicli9ie.js.map +1 -0
  20. package/dist/flipbook-engine.core.js +8 -0
  21. package/dist/flipbook-engine.core.js.map +1 -0
  22. package/dist/flipbook-engine.css +1 -1
  23. package/dist/flipbook-engine.iife.js +56 -47
  24. package/dist/flipbook-engine.iife.js.map +1 -1
  25. package/dist/flipbook-engine.js +9 -4
  26. package/dist/flipbook-engine.js.map +1 -1
  27. package/dist/flipbook-engine.plugins-annotations.js +14 -0
  28. package/dist/flipbook-engine.plugins-annotations.js.map +1 -0
  29. package/dist/flipbook-engine.plugins-bookmarks.js +16 -0
  30. package/dist/flipbook-engine.plugins-bookmarks.js.map +1 -0
  31. package/dist/flipbook-engine.plugins-deep-link.js +14 -0
  32. package/dist/flipbook-engine.plugins-deep-link.js.map +1 -0
  33. package/dist/flipbook-engine.plugins-hotspots.js +15 -0
  34. package/dist/flipbook-engine.plugins-hotspots.js.map +1 -0
  35. package/dist/flipbook-engine.plugins-notes.js +16 -0
  36. package/dist/flipbook-engine.plugins-notes.js.map +1 -0
  37. package/dist/flipbook-engine.plugins-search.js +15 -0
  38. package/dist/flipbook-engine.plugins-search.js.map +1 -0
  39. package/dist/flipbook-engine.plugins-share.js +13 -0
  40. package/dist/flipbook-engine.plugins-share.js.map +1 -0
  41. package/dist/flipbook-engine.plugins-toc.js +14 -0
  42. package/dist/flipbook-engine.plugins-toc.js.map +1 -0
  43. package/dist/flipbook-engine.plugins.js +5 -0
  44. package/dist/flipbook-engine.plugins.js.map +1 -0
  45. package/dist/flipbook-engine.react.js +1 -1
  46. package/dist/flipbook-engine.vue.js +1 -1
  47. package/dist/i18n/locales/en.d.ts +17 -0
  48. package/dist/i18n/locales/tr.d.ts +17 -0
  49. package/dist/i18n/service.d.ts +51 -0
  50. package/dist/index-BhTR2SK6.js +366 -0
  51. package/dist/index-BhTR2SK6.js.map +1 -0
  52. package/dist/index.d.ts +10 -1
  53. package/dist/model/annotations.d.ts +14 -0
  54. package/dist/model/hotspots.d.ts +40 -0
  55. package/dist/model/pages.d.ts +2 -0
  56. package/dist/model/search.d.ts +25 -0
  57. package/dist/plugins/annotations.d.ts +4 -0
  58. package/dist/plugins/bookmarks.d.ts +4 -0
  59. package/dist/plugins/deep-link.d.ts +4 -0
  60. package/dist/plugins/feature.d.ts +5 -0
  61. package/dist/plugins/hotspots.d.ts +4 -0
  62. package/dist/plugins/index.d.ts +65 -0
  63. package/dist/plugins/notes.d.ts +4 -0
  64. package/dist/plugins/search.d.ts +4 -0
  65. package/dist/plugins/share.d.ts +4 -0
  66. package/dist/plugins/toc.d.ts +4 -0
  67. package/dist/plugins-annotations.d.ts +1 -0
  68. package/dist/plugins-bookmarks.d.ts +1 -0
  69. package/dist/plugins-deep-link.d.ts +1 -0
  70. package/dist/plugins-hotspots.d.ts +1 -0
  71. package/dist/plugins-notes.d.ts +1 -0
  72. package/dist/plugins-search.d.ts +1 -0
  73. package/dist/plugins-share.d.ts +1 -0
  74. package/dist/plugins-toc.d.ts +1 -0
  75. package/dist/plugins.d.ts +1 -0
  76. package/dist/state/store.d.ts +19 -5
  77. package/dist/theme/theme.d.ts +16 -0
  78. package/dist/vue/index.d.ts +1 -1
  79. package/docs/api-reference.md +206 -0
  80. package/docs/frameworks.md +73 -0
  81. package/docs/getting-started.md +128 -0
  82. package/docs/i18n.md +47 -0
  83. package/docs/migration-0.4.0.md +24 -0
  84. package/docs/migration-0.5.0.md +25 -0
  85. package/docs/migration-1.0.0.md +59 -0
  86. package/docs/plugin-architecture.md +103 -0
  87. package/docs/release-checklist.md +37 -0
  88. package/docs/theming.md +61 -0
  89. package/package.json +165 -114
  90. package/dist/engine-MdZzt6R9.js +0 -3474
  91. package/dist/engine-MdZzt6R9.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,6 +1,41 @@
1
1
  # Changelog
2
2
 
3
- ## 0.6.0 (unreleased)
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 notice:** `flipbookengine@0.5.3` is a valid published release. Upgrade to `0.5.4` or later for lifecycle, locale, and PDF render error-handling fixes. The post-tag source regression was corrected before the 0.5.4 release.
4
- > **Development notice:** `0.6.0` is the next unreleased feature candidate and adds the localized Table of Contents API. `0.5.4` remains the latest published version until the 0.6.0 release.
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
  [![NPM Version](https://img.shields.io/npm/v/flipbookengine?style=flat-square&color=blue)](https://www.npmjs.com/package/flipbookengine)
7
7
  [![License](https://img.shields.io/npm/l/flipbookengine?style=flat-square)](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: true,
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.5.4/dist/flipbook-engine.css" />
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.5.4/dist/flipbook-engine.js';
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
- ## Roadmap
305
+ ## Release scope
246
306
 
247
- FlipbookEngine has two complementary targets: an AGPL open-source viewer package and a separate closed-source commercial backend edition.
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 remains an embeddable, framework-agnostic PDF viewer. The open-source v1.0.0 target focuses on client-side reader capabilities:
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
+
@@ -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,5 @@
1
+ import { FlipbookPluginRegistry } from '../plugins';
2
+
3
+ export declare function PluginPanels(props: {
4
+ registry: FlipbookPluginRegistry;
5
+ }): import('@serenity-is/domwise').JSXElement;
@@ -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,7 +1,7 @@
1
1
  import { FlipbookStore } from '../state/store';
2
2
 
3
3
  /**
4
- * @license FlipbookEngine v0.6.0
4
+ * @license FlipbookEngine v1.0.0
5
5
  * Copyright (c) 2026 Murat Dogan
6
6
  *
7
7
  * This source code is dual-licensed under the AGPLv3 and a Commercial License.
@@ -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
- /** Calculates the best viewport dimensions based on the first page. */
26
- calculateViewportDimensions(baseShortSide?: number): Promise<{
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'
@@ -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;