@embedpdf-editor/vue3-chapter-viewer 0.1.0 → 0.2.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/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { AnnotationCapability } from '@embedpdf/plugin-annotation';
2
+ import { BasePlugin } from '@embedpdf/core';
2
3
  import { BasePluginConfig } from '@embedpdf/core';
3
4
  import { ChapterTreeNode } from '../vue/chapter-tree';
4
5
  import { default as ChapterTreePanel } from '../components/ChapterTreePanel.vue';
@@ -8,9 +9,11 @@ import { ComponentOptionsMixin } from 'vue';
8
9
  import { ComponentProvideOptions } from 'vue';
9
10
  import { DefineComponent } from 'vue';
10
11
  import { EmbedPDF } from '@embedpdf/core/vue';
12
+ import { EventHook } from '@embedpdf/core';
11
13
  import { default as PdfChapterViewport } from '../components/PdfChapterViewport.vue';
12
14
  import { PdfEngine } from '@embedpdf/models';
13
15
  import { PluginBatchRegistration } from '@embedpdf/core';
16
+ import { PluginRegistry } from '@embedpdf/core';
14
17
  import { PublicProps } from 'vue';
15
18
  import { ReactNode } from 'react';
16
19
  import { Rect } from '@embedpdf/models';
@@ -20,28 +23,24 @@ import { UISchema } from '@embedpdf/plugin-ui';
20
23
  import { useCapability } from '@embedpdf/core/vue';
21
24
  import { usePdfiumEngine } from '@embedpdf/engines/vue';
22
25
 
23
- declare const __VLS_export: DefineComponent<__VLS_Props, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
24
-
25
- declare type __VLS_Props = {
26
- viewerProps: ChapterPdfViewerProps;
27
- };
26
+ declare const __VLS_export: DefineComponent<ChapterPdfViewerProps, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<ChapterPdfViewerProps> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
28
27
 
29
28
  /** 对当前选区应用 PDF 划线/高亮,支持按类型自定义颜色、粗细与偏移 */
30
29
  export declare function applySelectionMarkup(documentId: string, kind: SelectionMarkupKind, annotation: AnnotationCapability, selection: SelectionCapability, styles?: MarkupStylesConfig): boolean;
31
30
 
32
31
  declare interface BookmarkMarkerUiConfig {
33
- /** 自定义图标;提供时仅渲染图标,无默认蓝色背景按钮 */
32
+ /** 自定义图标;提供时仅渲染图标,无默认蓝色圆角背景 */
34
33
  renderIcon?: (ctx: {
35
34
  bookmark: ParagraphBookmark;
36
- }) => ReactNode;
35
+ }) => unknown;
37
36
  iconSize?: number;
38
37
  }
39
38
 
40
39
  declare interface BookmarkMarkerUiConfig_2 {
41
- /** 自定义图标;提供时仅渲染图标,无默认蓝色圆角背景 */
40
+ /** 自定义图标;提供时仅渲染图标,无默认蓝色背景按钮 */
42
41
  renderIcon?: (ctx: {
43
42
  bookmark: ParagraphBookmark;
44
- }) => unknown;
43
+ }) => ReactNode;
45
44
  iconSize?: number;
46
45
  }
47
46
 
@@ -95,6 +94,90 @@ export declare interface ChapterDescriptor {
95
94
  */
96
95
  export declare type ChapterLoadStatus = 'idle' | 'loading' | 'loaded' | 'error' | 'password-required' | 'closed';
97
96
 
97
+ declare interface ChapterManagerCapability {
98
+ /** 替换 manifest(会触发已不存在章节的卸载) */
99
+ setManifest(manifest: ChapterManifest, strategy?: OverlapOwnerStrategy): void;
100
+ getManifest(): ChapterManifest;
101
+ getVirtualPageMap(): VirtualPageMap;
102
+ /** ChapterScrollPlugin 在可见页位变化时调用,用以驱动按需加载 */
103
+ setVisibleGlobalPages(visiblePageIndices: number[]): void;
104
+ /** 显式触发某章节加载(如点击章节标题跳转时) */
105
+ ensureChapterLoaded(chapterId: string): Promise<ChapterLoadStatus>;
106
+ /** 状态查询 */
107
+ getChapterStatus(chapterId: string): ChapterLoadStatus;
108
+ getChapter(chapterId: string): ChapterDescriptor | null;
109
+ /** 事件 */
110
+ onChapterStatusChange: EventHook<ChapterStatusEvent>;
111
+ onManifestChange: EventHook<{
112
+ manifest: ChapterManifest;
113
+ map: VirtualPageMap;
114
+ }>;
115
+ }
116
+
117
+ /**
118
+ * 章节生命周期管理:以章节为粒度懒加载/预取/卸载 PDF 文件,并屏蔽密码协议细节。
119
+ *
120
+ * 关键不变量:
121
+ * - 每个章节对 DocumentManager 用 `documentId === chapterId`,从而保持 1:1 缓存。
122
+ * - 视觉上的「activeDocumentId」由本插件根据当前可见页位维护;上层无须感知。
123
+ * - 渲染层最终始终通过 `(chapterId, localPageIndex)` 索引到 owner 章节的 PDF 文档。
124
+ */
125
+ export declare class ChapterManagerPlugin extends BasePlugin<ChapterManagerPluginConfig, ChapterManagerCapability> {
126
+ static readonly id: "chapter-manager";
127
+ private readonly statusChange$;
128
+ private readonly manifestChange$;
129
+ private config;
130
+ private documentManager;
131
+ private passwordProvider?;
132
+ private manifest;
133
+ private overlapStrategy;
134
+ private virtualPageMap;
135
+ /** 每个章节当前状态(in-memory;不需要 redux 同步) */
136
+ private readonly chapterStatus;
137
+ /** 章节最近一次进入视口或被显式请求的时间戳,用于卸载判断 */
138
+ private readonly chapterLastUsed;
139
+ /** 章节密码累计尝试次数 */
140
+ private readonly passwordAttempts;
141
+ /** 等待 ensureChapterLoaded 完成的 Promise 列表(按章节去重) */
142
+ private readonly pendingLoadPromises;
143
+ /** unload tick 句柄 */
144
+ private unloadTimer;
145
+ private documentManagerUnsubs;
146
+ constructor(id: string, registry: PluginRegistry);
147
+ initialize(config: ChapterManagerPluginConfig): Promise<void>;
148
+ protected buildCapability(): ChapterManagerCapability;
149
+ destroy(): void;
150
+ private setManifestInternal;
151
+ /** manifest 就绪后预取前 N 章(不依赖滚动视口是否已算出可见页) */
152
+ private eagerPrefetchFromManifest;
153
+ private findChapter;
154
+ private isOwnedChapter;
155
+ private handleVisibleChange;
156
+ private collectIdleChapters;
157
+ ensureChapterLoaded(chapterId: string): Promise<ChapterLoadStatus>;
158
+ private resolvePdfPayload;
159
+ private startLoad;
160
+ /** 阻塞等待该章节状态进入 loaded / error / password-required / closed */
161
+ private waitForTerminalStatus;
162
+ private handleDocumentError;
163
+ private closeChapter;
164
+ private updateStatus;
165
+ }
166
+
167
+ declare interface ChapterManagerPluginConfig extends BasePluginConfig {
168
+ manifest: ChapterManifest;
169
+ overlapStrategy?: OverlapOwnerStrategy;
170
+ passwordProvider?: IPasswordProvider;
171
+ /** 未在 descriptor.source 中指定 PDF 时,由此统一加载 */
172
+ chapterPdfLoader?: IChapterPdfLoader;
173
+ /** 视口前后预取多少章节,默认 1 */
174
+ prefetchChapters?: number;
175
+ /** 章节空闲多久后卸载(毫秒),默认 60s。设为 0 关闭卸载 */
176
+ unloadTimeoutMs?: number;
177
+ /** 第一个加载的章节是否自动设为 active,默认 true */
178
+ autoActivateOnLoad?: boolean;
179
+ }
180
+
98
181
  export declare interface ChapterManifest {
99
182
  chapters: ChapterDescriptor[];
100
183
  /**
@@ -121,14 +204,21 @@ export declare type ChapterPdfPayload = {
121
204
 
122
205
  export declare const ChapterPdfViewer: typeof __VLS_export;
123
206
 
124
- /** React / Vue 共用的章节阅读器顶层 props(框架专属字段在各自入口扩展) */
207
+ /** React / Vue 共用的章节阅读器顶层 props */
125
208
  export declare interface ChapterPdfViewerProps {
126
209
  engine: PdfEngine;
127
- editorOptions: Omit<CreatePdfChapterEditorOptions, 'features'> & {
128
- notes?: PdfChapterEditorNotesConfig;
129
- bookmarks?: PdfChapterEditorBookmarksConfig;
130
- };
131
- features?: ChapterViewerFeaturesConfig;
210
+ /**
211
+ * 推荐:统一配置(manifest + 笔记/书签回调 + 可选 features)
212
+ */
213
+ options?: ChapterViewerOptions;
214
+ /**
215
+ * @deprecated 请改用 `options`
216
+ */
217
+ editorOptions?: Omit<CreatePdfChapterEditorOptions, 'features'>;
218
+ /**
219
+ * @deprecated 请并入 `options.features`
220
+ */
221
+ features?: ChapterViewerConfig;
132
222
  className?: string;
133
223
  viewportClassName?: string;
134
224
  }
@@ -147,13 +237,45 @@ export declare type ChapterSource = {
147
237
  load: () => Promise<ChapterPdfPayload>;
148
238
  };
149
239
 
240
+ declare interface ChapterStatusEvent {
241
+ chapterId: string;
242
+ status: ChapterLoadStatus;
243
+ /** 仅在 status === 'error' 时有意义 */
244
+ error?: {
245
+ message: string;
246
+ code?: number;
247
+ };
248
+ }
249
+
150
250
  export { ChapterTreeNode }
151
251
 
152
252
  export { ChapterTreePanel }
153
253
 
154
254
  export { ChapterViewerCatalog }
155
255
 
156
- /** 章节渲染器集成功能开关(与 demo 默认样式对齐) */
256
+ /**
257
+ * 用户侧功能配置(简化写法):
258
+ * - 省略或 `true`:开启并使用默认样式
259
+ * - `false`:关闭
260
+ * - 对象:开启并覆盖对应字段
261
+ */
262
+ export declare type ChapterViewerConfig = {
263
+ markup?: boolean | {
264
+ styles?: MarkupStylesConfig;
265
+ };
266
+ bookmarks?: boolean | {
267
+ marker?: BookmarkMarkerUiConfig;
268
+ hover?: HoverBookmarkUiConfig;
269
+ };
270
+ notes?: boolean | {
271
+ marker?: NoteMarkerUiConfig;
272
+ };
273
+ zoom?: boolean | ChapterViewerZoomConfig;
274
+ /** 默认随划线/笔记开启;仅在有扩展按钮或需隐藏内置按钮时配置 */
275
+ selectionToolbar?: boolean | SelectionToolbarConfig;
276
+ };
277
+
278
+ /** 渲染器内部使用的规范化功能配置 */
157
279
  export declare interface ChapterViewerFeaturesConfig {
158
280
  /** 划线/高亮 */
159
281
  markup?: {
@@ -163,8 +285,8 @@ export declare interface ChapterViewerFeaturesConfig {
163
285
  /** 段落书签(含悬停添加) */
164
286
  bookmarks?: {
165
287
  enabled?: boolean;
166
- marker?: BookmarkMarkerUiConfig_2;
167
- hover?: HoverBookmarkUiConfig_2;
288
+ marker?: BookmarkMarkerUiConfig;
289
+ hover?: HoverBookmarkUiConfig;
168
290
  };
169
291
  /** 笔记 */
170
292
  notes?: {
@@ -177,27 +299,57 @@ export declare interface ChapterViewerFeaturesConfig {
177
299
  zoom?: ChapterViewerZoomConfig;
178
300
  }
179
301
 
302
+ /** 章节阅读器统一配置(推荐入口) */
303
+ export declare interface ChapterViewerOptions {
304
+ manifest: ChapterManifest;
305
+ /** 笔记持久化与弹窗回调 */
306
+ notes: NoteCallbacks;
307
+ /** 书签持久化与删除回调 */
308
+ bookmarks: ParagraphBookmarkCallbacks;
309
+ chapterPdfLoader?: IChapterPdfLoader;
310
+ /** 功能开关与样式;省略则全开 */
311
+ features?: ChapterViewerConfig;
312
+ }
313
+
180
314
  declare interface ChapterViewerZoomConfig {
181
315
  /** 是否启用 pinch/滑块缩放容器,默认 true */
182
316
  enabled?: boolean;
183
317
  min?: number;
184
318
  max?: number;
319
+ /** 文档 scale 初始值;未设置且配置了 pageWidth 时由 pageWidth 按首页宽度推导 */
185
320
  initial?: number;
321
+ /**
322
+ * 页面布局目标宽度(CSS px)。
323
+ * 章节 PDF 加载后按 `pageWidth / pdfPageWidth` 设置 document scale,与 RenderLayer / 滚动占位一致。
324
+ */
325
+ pageWidth?: number;
186
326
  }
187
327
 
328
+ /** 生成插件列表 + 规范化后的 features(供 EmbedPDF / PdfChapterViewport 使用) */
329
+ export declare function createChapterViewerBundle(input: ChapterViewerOptions | CreateChapterViewerEditorOptionsInput): {
330
+ plugins: PluginBatchRegistration<any, any, any, any>[];
331
+ features: ChapterViewerFeaturesConfig;
332
+ editorOptions: CreatePdfChapterEditorOptions;
333
+ };
334
+
188
335
  /**
189
336
  * 创建带默认划线/笔记/书签/选区 card 的章节编辑器插件包。
190
- * 传入的 `features` 与默认值浅合并。
191
337
  */
192
338
  export declare function createChapterViewerEditor(options: CreatePdfChapterEditorOptions): PdfChapterEditorBundle;
193
339
 
194
- export declare function createChapterViewerEditorOptions(input: CreateChapterViewerEditorOptionsInput): Omit<CreatePdfChapterEditorOptions, 'features'>;
340
+ /** 进阶用法:仅生成 editor 配置(不含 features,需自行传给 PdfChapterViewport) */
341
+ export declare function createChapterViewerEditorOptions(input: ChapterViewerOptions | CreateChapterViewerEditorOptionsInput): Omit<CreatePdfChapterEditorOptions, 'features'>;
195
342
 
343
+ /** @deprecated 旧版嵌套 `callbacks` 写法,仍兼容 */
196
344
  export declare type CreateChapterViewerEditorOptionsInput = {
197
345
  manifest: ChapterManifest;
198
346
  chapterPdfLoader?: IChapterPdfLoader;
199
- bookmarks: PdfChapterEditorBookmarksConfig;
200
- notes: PdfChapterEditorNotesConfig;
347
+ bookmarks: {
348
+ callbacks: ParagraphBookmarkCallbacks;
349
+ };
350
+ notes: {
351
+ callbacks: NoteCallbacks;
352
+ };
201
353
  };
202
354
 
203
355
  declare interface CreateEditorUiSchemaOptions {
@@ -240,7 +392,10 @@ export declare interface CreatePdfChapterEditorOptions {
240
392
  features?: ChapterViewerFeaturesConfig;
241
393
  }
242
394
 
243
- /** demo 对齐的默认集成功能 */
395
+ /** 用户侧默认:省略 `options.features` 即等价于此空对象(全部功能开启) */
396
+ export declare const DEFAULT_CHAPTER_VIEWER_CONFIG: ChapterViewerConfig;
397
+
398
+ /** 默认全开的功能配置(内部规范化结果) */
244
399
  export declare const DEFAULT_CHAPTER_VIEWER_FEATURES: ChapterViewerFeaturesConfig;
245
400
 
246
401
  /** 与 snippet 主工具栏 mode tabs 对齐的编辑模式 */
@@ -252,13 +407,13 @@ declare const editorSecondaryToolbars: Record<string, ToolbarSchema>;
252
407
  export { EmbedPDF }
253
408
 
254
409
  declare interface HoverBookmarkUiConfig {
255
- renderAddIcon?: () => ReactNode;
410
+ /** 悬停行末「添加书签」自定义图标;无背景 */
411
+ renderAddIcon?: () => unknown;
256
412
  iconSize?: number;
257
413
  }
258
414
 
259
415
  declare interface HoverBookmarkUiConfig_2 {
260
- /** 悬停行末「添加书签」自定义图标;无背景 */
261
- renderAddIcon?: () => unknown;
416
+ renderAddIcon?: () => ReactNode;
262
417
  iconSize?: number;
263
418
  }
264
419
 
@@ -469,8 +624,8 @@ declare interface ParagraphBookmarkCallbacks {
469
624
 
470
625
  declare interface ParagraphBookmarkPluginConfig extends BasePluginConfig {
471
626
  callbacks?: ParagraphBookmarkCallbacks;
472
- ui?: BookmarkMarkerUiConfig;
473
- hover?: HoverBookmarkUiConfig;
627
+ ui?: BookmarkMarkerUiConfig_2;
628
+ hover?: HoverBookmarkUiConfig_2;
474
629
  }
475
630
 
476
631
  export declare interface PdfChapterEditorBookmarksConfig {
@@ -516,4 +671,42 @@ export { useCapability }
516
671
 
517
672
  export { usePdfiumEngine }
518
673
 
674
+ /**
675
+ * 一个虚拟页位的解析结果。`localPageIndex` 是 owner 章节 PDF 内的 0-based 索引。
676
+ */
677
+ declare interface VirtualPageLocation {
678
+ globalPageIndex: number;
679
+ globalPageNumber: number;
680
+ chapterId: string;
681
+ localPageIndex: number;
682
+ }
683
+
684
+ /**
685
+ * 跨章节 PDF 的「全局页 ↔ (章节, 本地页)」映射。
686
+ *
687
+ * 设计要点:
688
+ * - 「globalPageNumber」是后端 manifest 里的业务页号,可能不连续(极端情况)。
689
+ * - 「globalPageIndex」是去重后排序的 0-based 紧凑索引,是滚动/虚拟列表使用的页位。
690
+ * 这样上层 `ChapterScroll` 不必关心业务页号是否连续。
691
+ */
692
+ declare class VirtualPageMap {
693
+ private readonly _pages;
694
+ private readonly _byChapter;
695
+ private readonly _byGlobalNumber;
696
+ constructor(pages: VirtualPageLocation[]);
697
+ get totalPages(): number;
698
+ /** 顺序返回所有去重后的页位 */
699
+ list(): readonly VirtualPageLocation[];
700
+ /** 由 0-based 紧凑索引取页位 */
701
+ atIndex(globalPageIndex: number): VirtualPageLocation | null;
702
+ /** 由后端业务页号取页位 */
703
+ byGlobalNumber(globalPageNumber: number): VirtualPageLocation | null;
704
+ /** 由 (章节, 本地页) 反查到 owner 视图下的全局位置;非 owner 章节会返回 null */
705
+ toGlobal(chapterId: string, localPageIndex: number): VirtualPageLocation | null;
706
+ /** 该章节在虚拟视图中实际「被采用」的页(owner 命中的) */
707
+ pagesOfChapter(chapterId: string): readonly VirtualPageLocation[];
708
+ /** 拿一个章节首次出现的虚拟索引(用于 scrollToChapter) */
709
+ firstIndexOfChapter(chapterId: string): number;
710
+ }
711
+
519
712
  export { }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,sBAAsB,EACtB,gCAAgC,EAChC,+BAA+B,EAC/B,oBAAoB,EACpB,4BAA4B,EAC5B,wBAAwB,EACxB,QAAQ,EACR,aAAa,GACd,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,qBAAqB,EACrB,2BAA2B,EAC3B,qCAAqC,EACrC,6BAA6B,EAC7B,2BAA2B,EAC3B,+BAA+B,EAC/B,aAAa,EACb,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,yBAAyB,EACzB,sBAAsB,EACtB,gCAAgC,EAChC,+BAA+B,EAC/B,6BAA6B,EAC7B,oBAAoB,EACpB,4BAA4B,EAC5B,wBAAwB,EACxB,QAAQ,EACR,aAAa,GACd,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,qCAAqC,EACrC,6BAA6B,EAC7B,2BAA2B,EAC3B,+BAA+B,EAC/B,aAAa,EACb,UAAU,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,oCAAoC,CAAC"}