@embedpdf/plugin-thumbnail 1.0.11 → 1.0.12
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.cjs +2 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -54
- package/dist/index.js +9 -17
- package/dist/index.js.map +1 -1
- package/dist/lib/index.d.ts +7 -0
- package/dist/lib/manifest.d.ts +4 -0
- package/dist/lib/thumbnail-plugin.d.ts +17 -0
- package/dist/lib/types.d.ts +30 -0
- package/dist/preact/adapter.d.ts +5 -0
- package/dist/preact/core.d.ts +1 -0
- package/dist/preact/index.cjs +2 -124
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.ts +1 -34
- package/dist/preact/index.js +18 -24
- package/dist/preact/index.js.map +1 -1
- package/dist/react/adapter.d.ts +2 -0
- package/dist/react/core.d.ts +1 -0
- package/dist/react/index.cjs +2 -124
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.ts +1 -30
- package/dist/react/index.js +17 -24
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/components/index.d.ts +2 -0
- package/dist/shared-preact/components/thumbnail-img.d.ts +8 -0
- package/dist/shared-preact/components/thumbnails-pane.d.ts +10 -0
- package/dist/shared-preact/hooks/index.d.ts +1 -0
- package/dist/shared-preact/hooks/use-thumbnail.d.ts +11 -0
- package/dist/shared-preact/index.d.ts +2 -0
- package/dist/shared-react/components/index.d.ts +2 -0
- package/dist/shared-react/components/thumbnail-img.d.ts +8 -0
- package/dist/shared-react/components/thumbnails-pane.d.ts +10 -0
- package/dist/shared-react/hooks/index.d.ts +1 -0
- package/dist/shared-react/hooks/use-thumbnail.d.ts +11 -0
- package/dist/shared-react/index.d.ts +2 -0
- package/package.json +14 -11
- package/dist/index.d.cts +0 -54
- package/dist/preact/index.d.cts +0 -34
- package/dist/react/index.d.cts +0 -30
package/dist/index.cjs
CHANGED
|
@@ -1,170 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
THUMBNAIL_PLUGIN_ID: () => THUMBNAIL_PLUGIN_ID,
|
|
24
|
-
ThumbnailPlugin: () => ThumbnailPlugin,
|
|
25
|
-
ThumbnailPluginPackage: () => ThumbnailPluginPackage,
|
|
26
|
-
manifest: () => manifest
|
|
27
|
-
});
|
|
28
|
-
module.exports = __toCommonJS(index_exports);
|
|
29
|
-
|
|
30
|
-
// src/lib/manifest.ts
|
|
31
|
-
var THUMBNAIL_PLUGIN_ID = "thumbnail";
|
|
32
|
-
var manifest = {
|
|
33
|
-
id: THUMBNAIL_PLUGIN_ID,
|
|
34
|
-
name: "Thumbnail Plugin",
|
|
35
|
-
version: "1.0.0",
|
|
36
|
-
provides: ["thumbnail"],
|
|
37
|
-
requires: ["render"],
|
|
38
|
-
optional: [],
|
|
39
|
-
defaultConfig: {
|
|
40
|
-
enabled: true,
|
|
41
|
-
width: 150,
|
|
42
|
-
gap: 10,
|
|
43
|
-
buffer: 3,
|
|
44
|
-
labelHeight: 16
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
// src/lib/thumbnail-plugin.ts
|
|
49
|
-
var import_core = require("@embedpdf/core");
|
|
50
|
-
var import_models = require("@embedpdf/models");
|
|
51
|
-
var ThumbnailPlugin = class extends import_core.BasePlugin {
|
|
52
|
-
constructor(id, registry, cfg) {
|
|
53
|
-
super(id, registry);
|
|
54
|
-
this.cfg = cfg;
|
|
55
|
-
this.thumbs = [];
|
|
56
|
-
this.window = null;
|
|
57
|
-
this.emitWindow = (0, import_core.createBehaviorEmitter)();
|
|
58
|
-
this.taskCache = /* @__PURE__ */ new Map();
|
|
59
|
-
this.renderCapability = this.registry.getPlugin("render").provides();
|
|
60
|
-
this.coreStore.onAction(import_core.SET_DOCUMENT, (_action, state) => {
|
|
61
|
-
this.taskCache.clear();
|
|
62
|
-
this.setWindowState(state);
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
/* ------------ init ------------------------------------------------ */
|
|
66
|
-
async initialize() {
|
|
67
|
-
}
|
|
68
|
-
setWindowState(state) {
|
|
69
|
-
const core = state.core;
|
|
70
|
-
if (!core.document) return;
|
|
71
|
-
const W = this.cfg.width ?? 120;
|
|
72
|
-
const L = this.cfg.labelHeight ?? 16;
|
|
73
|
-
const GAP = this.cfg.gap ?? 8;
|
|
74
|
-
let offset = 0;
|
|
75
|
-
this.thumbs = core.document.pages.map((p) => {
|
|
76
|
-
const ratio = p.size.height / p.size.width;
|
|
77
|
-
const thumbH = Math.round(W * ratio);
|
|
78
|
-
const wrapH = thumbH + L;
|
|
79
|
-
const meta = {
|
|
80
|
-
pageIndex: p.index,
|
|
81
|
-
width: W,
|
|
82
|
-
height: thumbH,
|
|
83
|
-
wrapperHeight: wrapH,
|
|
84
|
-
top: offset,
|
|
85
|
-
labelHeight: L
|
|
86
|
-
};
|
|
87
|
-
offset += wrapH + GAP;
|
|
88
|
-
return meta;
|
|
89
|
-
});
|
|
90
|
-
this.window = {
|
|
91
|
-
start: -1,
|
|
92
|
-
end: -1,
|
|
93
|
-
items: [],
|
|
94
|
-
totalHeight: offset - GAP
|
|
95
|
-
// last item has no gap below
|
|
96
|
-
};
|
|
97
|
-
this.emitWindow.emit(this.window);
|
|
98
|
-
}
|
|
99
|
-
/* ------------ capability ----------------------------------------- */
|
|
100
|
-
buildCapability() {
|
|
101
|
-
return {
|
|
102
|
-
onWindow: this.emitWindow.on,
|
|
103
|
-
setViewport: (y, h) => this.updateWindow(y, h),
|
|
104
|
-
renderThumb: (idx, dpr) => this.renderThumb(idx, dpr)
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
/* ------------ windowing math ------------------------------------- */
|
|
108
|
-
updateWindow(scrollY, viewportH) {
|
|
109
|
-
const BUF = this.cfg.buffer ?? 3;
|
|
110
|
-
let low = 0, high = this.thumbs.length - 1, first = 0;
|
|
111
|
-
while (low <= high) {
|
|
112
|
-
const mid = low + high >> 1;
|
|
113
|
-
const m = this.thumbs[mid];
|
|
114
|
-
if (m.top + m.wrapperHeight < scrollY) low = mid + 1;
|
|
115
|
-
else {
|
|
116
|
-
first = mid;
|
|
117
|
-
high = mid - 1;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
let last = first;
|
|
121
|
-
const limit = scrollY + viewportH;
|
|
122
|
-
while (last + 1 < this.thumbs.length && this.thumbs[last].top < limit) last++;
|
|
123
|
-
last = Math.min(this.thumbs.length - 1, last + BUF);
|
|
124
|
-
const start = Math.max(0, first - BUF);
|
|
125
|
-
if (this.window && start === this.window.start && last === this.window.end) return;
|
|
126
|
-
this.window = {
|
|
127
|
-
start,
|
|
128
|
-
end: last,
|
|
129
|
-
items: this.thumbs.slice(start, last + 1),
|
|
130
|
-
totalHeight: this.window.totalHeight
|
|
131
|
-
};
|
|
132
|
-
this.emitWindow.emit(this.window);
|
|
133
|
-
}
|
|
134
|
-
/* ------------ thumbnail raster ----------------------------------- */
|
|
135
|
-
renderThumb(idx, dpr) {
|
|
136
|
-
if (this.taskCache.has(idx)) return this.taskCache.get(idx);
|
|
137
|
-
const core = this.coreState.core;
|
|
138
|
-
const page = core.document.pages[idx];
|
|
139
|
-
const scale = (this.cfg.width ?? 120) / page.size.width;
|
|
140
|
-
const task = this.renderCapability.renderPageRect({
|
|
141
|
-
pageIndex: idx,
|
|
142
|
-
rect: { origin: { x: 0, y: 0 }, size: page.size },
|
|
143
|
-
scaleFactor: scale,
|
|
144
|
-
dpr
|
|
145
|
-
});
|
|
146
|
-
this.taskCache.set(idx, task);
|
|
147
|
-
task.wait(import_models.ignore, () => {
|
|
148
|
-
this.taskCache.delete(idx);
|
|
149
|
-
});
|
|
150
|
-
return task;
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
ThumbnailPlugin.id = "thumbnail";
|
|
154
|
-
|
|
155
|
-
// src/lib/index.ts
|
|
156
|
-
var ThumbnailPluginPackage = {
|
|
157
|
-
manifest,
|
|
158
|
-
create: (registry, _engine, config) => new ThumbnailPlugin(THUMBNAIL_PLUGIN_ID, registry, config),
|
|
159
|
-
reducer: () => {
|
|
160
|
-
},
|
|
161
|
-
initialState: {}
|
|
162
|
-
};
|
|
163
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
164
|
-
0 && (module.exports = {
|
|
165
|
-
THUMBNAIL_PLUGIN_ID,
|
|
166
|
-
ThumbnailPlugin,
|
|
167
|
-
ThumbnailPluginPackage,
|
|
168
|
-
manifest
|
|
169
|
-
});
|
|
170
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core"),e=require("@embedpdf/models"),i="thumbnail",s={id:i,name:"Thumbnail Plugin",version:"1.0.0",provides:["thumbnail"],requires:["render"],optional:[],defaultConfig:{enabled:!0,width:150,gap:10,buffer:3,labelHeight:16}},h=class extends t.BasePlugin{constructor(e,i,s){super(e,i),this.cfg=s,this.thumbs=[],this.window=null,this.emitWindow=t.createBehaviorEmitter(),this.taskCache=new Map,this.renderCapability=this.registry.getPlugin("render").provides(),this.coreStore.onAction(t.SET_DOCUMENT,((t,e)=>{this.taskCache.clear(),this.setWindowState(e)}))}async initialize(){}setWindowState(t){const e=t.core;if(!e.document)return;const i=this.cfg.width??120,s=this.cfg.labelHeight??16,h=this.cfg.gap??8;let n=0;this.thumbs=e.document.pages.map((t=>{const e=t.size.height/t.size.width,r=Math.round(i*e),a=r+s,o={pageIndex:t.index,width:i,height:r,wrapperHeight:a,top:n,labelHeight:s};return n+=a+h,o})),this.window={start:-1,end:-1,items:[],totalHeight:n-h},this.emitWindow.emit(this.window)}buildCapability(){return{onWindow:this.emitWindow.on,setViewport:(t,e)=>this.updateWindow(t,e),renderThumb:(t,e)=>this.renderThumb(t,e)}}updateWindow(t,e){const i=this.cfg.buffer??3;let s=0,h=this.thumbs.length-1,n=0;for(;s<=h;){const e=s+h>>1,i=this.thumbs[e];i.top+i.wrapperHeight<t?s=e+1:(n=e,h=e-1)}let r=n;const a=t+e;for(;r+1<this.thumbs.length&&this.thumbs[r].top<a;)r++;r=Math.min(this.thumbs.length-1,r+i);const o=Math.max(0,n-i);this.window&&o===this.window.start&&r===this.window.end||(this.window={start:o,end:r,items:this.thumbs.slice(o,r+1),totalHeight:this.window.totalHeight},this.emitWindow.emit(this.window))}renderThumb(t,i){if(this.taskCache.has(t))return this.taskCache.get(t);const s=this.coreState.core.document.pages[t],h=(this.cfg.width??120)/s.size.width,n=this.renderCapability.renderPageRect({pageIndex:t,rect:{origin:{x:0,y:0},size:s.size},scaleFactor:h,dpr:i});return this.taskCache.set(t,n),n.wait(e.ignore,(()=>{this.taskCache.delete(t)})),n}};h.id="thumbnail";let n=h;const r={manifest:s,create:(t,e,s)=>new n(i,t,s),reducer:()=>{},initialState:{}};exports.THUMBNAIL_PLUGIN_ID=i,exports.ThumbnailPlugin=n,exports.ThumbnailPluginPackage=r,exports.manifest=s;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/thumbnail-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { ThumbnailPluginConfig } from './types';\n\nexport const THUMBNAIL_PLUGIN_ID = 'thumbnail';\n\nexport const manifest: PluginManifest<ThumbnailPluginConfig> = {\n id: THUMBNAIL_PLUGIN_ID,\n name: 'Thumbnail Plugin',\n version: '1.0.0',\n provides: ['thumbnail'],\n requires: ['render'],\n optional: [],\n defaultConfig: {\n enabled: true,\n width: 150,\n gap: 10,\n buffer: 3,\n labelHeight: 16,\n },\n};\n","import {\n BasePlugin,\n CoreState,\n createBehaviorEmitter,\n PluginRegistry,\n SET_DOCUMENT,\n StoreState,\n} from '@embedpdf/core';\nimport { ThumbMeta, ThumbnailPluginConfig, WindowState } from './types';\nimport { ThumbnailCapability } from './types';\nimport { ignore, PdfErrorReason, Task } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\n\nexport class ThumbnailPlugin extends BasePlugin<ThumbnailPluginConfig, ThumbnailCapability> {\n static readonly id = 'thumbnail' as const;\n\n private renderCapability: RenderCapability;\n private thumbs: ThumbMeta[] = [];\n private window: WindowState | null = null;\n private readonly emitWindow = createBehaviorEmitter<WindowState>();\n private readonly taskCache = new Map<number, Task<Blob, PdfErrorReason>>();\n\n constructor(\n id: string,\n registry: PluginRegistry,\n private cfg: ThumbnailPluginConfig,\n ) {\n super(id, registry);\n\n this.renderCapability = this.registry.getPlugin<RenderPlugin>('render')!.provides();\n\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n this.taskCache.clear();\n this.setWindowState(state);\n });\n }\n\n /* ------------ init ------------------------------------------------ */\n async initialize(): Promise<void> {}\n\n private setWindowState(state: StoreState<CoreState>) {\n const core = state.core;\n\n if (!core.document) return;\n\n const W = this.cfg.width ?? 120;\n const L = this.cfg.labelHeight ?? 16; // label\n const GAP = this.cfg.gap ?? 8;\n\n let offset = 0;\n this.thumbs = core.document.pages.map((p) => {\n const ratio = p.size.height / p.size.width;\n const thumbH = Math.round(W * ratio);\n const wrapH = thumbH + L; // no GAP here\n\n const meta: ThumbMeta = {\n pageIndex: p.index,\n width: W,\n height: thumbH,\n wrapperHeight: wrapH,\n top: offset,\n labelHeight: L,\n };\n offset += wrapH + GAP; // GAP added *after* wrapper\n return meta;\n });\n\n this.window = {\n start: -1,\n end: -1,\n items: [],\n totalHeight: offset - GAP, // last item has no gap below\n };\n this.emitWindow.emit(this.window);\n }\n\n /* ------------ capability ----------------------------------------- */\n protected buildCapability(): ThumbnailCapability {\n return {\n onWindow: this.emitWindow.on,\n setViewport: (y, h) => this.updateWindow(y, h),\n renderThumb: (idx, dpr) => this.renderThumb(idx, dpr),\n };\n }\n\n /* ------------ windowing math ------------------------------------- */\n private updateWindow(scrollY: number, viewportH: number) {\n const BUF = this.cfg.buffer ?? 3;\n\n /* -------- find first visible wrapper ---------- */\n let low = 0,\n high = this.thumbs.length - 1,\n first = 0;\n while (low <= high) {\n const mid = (low + high) >> 1;\n const m = this.thumbs[mid];\n if (m.top + m.wrapperHeight < scrollY) low = mid + 1;\n else {\n first = mid;\n high = mid - 1;\n }\n }\n\n /* -------- find last visible + buffer ---------- */\n let last = first;\n const limit = scrollY + viewportH;\n while (last + 1 < this.thumbs.length && this.thumbs[last].top < limit) last++;\n last = Math.min(this.thumbs.length - 1, last + BUF);\n\n const start = Math.max(0, first - BUF);\n if (this.window && start === this.window.start && last === this.window.end) return;\n\n this.window = {\n start,\n end: last,\n items: this.thumbs.slice(start, last + 1),\n totalHeight: this.window!.totalHeight,\n };\n this.emitWindow.emit(this.window);\n }\n\n /* ------------ thumbnail raster ----------------------------------- */\n private renderThumb(idx: number, dpr: number) {\n if (this.taskCache.has(idx)) return this.taskCache.get(idx)!;\n\n const core = this.coreState.core;\n const page = core.document!.pages[idx];\n const scale = (this.cfg.width ?? 120) / page.size.width;\n\n const task = this.renderCapability.renderPageRect({\n pageIndex: idx,\n rect: { origin: { x: 0, y: 0 }, size: page.size },\n scaleFactor: scale,\n dpr,\n });\n\n this.taskCache.set(idx, task);\n\n task.wait(ignore, () => {\n this.taskCache.delete(idx);\n });\n\n return task;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, THUMBNAIL_PLUGIN_ID } from './manifest';\nimport { ThumbnailPluginConfig } from './types';\nimport { ThumbnailPlugin } from './thumbnail-plugin';\n\nexport const ThumbnailPluginPackage: PluginPackage<ThumbnailPlugin, ThumbnailPluginConfig> = {\n manifest,\n create: (registry, _engine, config) => new ThumbnailPlugin(THUMBNAIL_PLUGIN_ID, registry, config),\n reducer: () => {},\n initialState: {},\n};\n\nexport * from './thumbnail-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["THUMBNAIL_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","enabled","width","gap","buffer","labelHeight","_ThumbnailPlugin","BasePlugin","constructor","registry","cfg","super","this","thumbs","window","emitWindow","createBehaviorEmitter","taskCache","Map","renderCapability","getPlugin","coreStore","onAction","SET_DOCUMENT","_action","state","clear","setWindowState","initialize","core","document","W","L","GAP","offset","pages","map","p","ratio","size","height","thumbH","Math","round","wrapH","meta","pageIndex","index","wrapperHeight","top","start","end","items","totalHeight","emit","buildCapability","onWindow","on","setViewport","y","h","updateWindow","renderThumb","idx","dpr","scrollY","viewportH","BUF","low","high","length","first","mid","m","last","limit","min","max","slice","has","get","page","coreState","scale","task","renderPageRect","rect","origin","x","scaleFactor","set","wait","ignore","delete","ThumbnailPlugin","ThumbnailPluginPackage","create","_engine","config","reducer","initialState"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,54 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { Task, PdfErrorReason } from '@embedpdf/models';
|
|
3
|
-
|
|
4
|
-
interface ThumbnailPluginConfig extends BasePluginConfig {
|
|
5
|
-
width?: number;
|
|
6
|
-
gap?: number;
|
|
7
|
-
buffer?: number;
|
|
8
|
-
labelHeight?: number;
|
|
9
|
-
}
|
|
10
|
-
interface ThumbMeta {
|
|
11
|
-
pageIndex: number;
|
|
12
|
-
width: number;
|
|
13
|
-
height: number;
|
|
14
|
-
wrapperHeight: number;
|
|
15
|
-
top: number;
|
|
16
|
-
labelHeight: number;
|
|
17
|
-
}
|
|
18
|
-
interface WindowState {
|
|
19
|
-
start: number;
|
|
20
|
-
end: number;
|
|
21
|
-
items: ThumbMeta[];
|
|
22
|
-
totalHeight: number;
|
|
23
|
-
}
|
|
24
|
-
interface ThumbnailCapability {
|
|
25
|
-
/** called from UI on every scroll */
|
|
26
|
-
setViewport(offsetY: number, viewportH: number): void;
|
|
27
|
-
/** listen to window changes */
|
|
28
|
-
onWindow(cb: (w: WindowState) => void): () => void;
|
|
29
|
-
/** lazily render one thumb */
|
|
30
|
-
renderThumb(pageIdx: number, dpr: number): Task<Blob, PdfErrorReason>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
declare class ThumbnailPlugin extends BasePlugin<ThumbnailPluginConfig, ThumbnailCapability> {
|
|
34
|
-
private cfg;
|
|
35
|
-
static readonly id: "thumbnail";
|
|
36
|
-
private renderCapability;
|
|
37
|
-
private thumbs;
|
|
38
|
-
private window;
|
|
39
|
-
private readonly emitWindow;
|
|
40
|
-
private readonly taskCache;
|
|
41
|
-
constructor(id: string, registry: PluginRegistry, cfg: ThumbnailPluginConfig);
|
|
42
|
-
initialize(): Promise<void>;
|
|
43
|
-
private setWindowState;
|
|
44
|
-
protected buildCapability(): ThumbnailCapability;
|
|
45
|
-
private updateWindow;
|
|
46
|
-
private renderThumb;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
declare const THUMBNAIL_PLUGIN_ID = "thumbnail";
|
|
50
|
-
declare const manifest: PluginManifest<ThumbnailPluginConfig>;
|
|
51
|
-
|
|
52
|
-
declare const ThumbnailPluginPackage: PluginPackage<ThumbnailPlugin, ThumbnailPluginConfig>;
|
|
53
|
-
|
|
54
|
-
export { THUMBNAIL_PLUGIN_ID, type ThumbMeta, type ThumbnailCapability, ThumbnailPlugin, type ThumbnailPluginConfig, ThumbnailPluginPackage, type WindowState, manifest };
|
|
1
|
+
export * from './lib';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { BasePlugin, createBehaviorEmitter, SET_DOCUMENT } from "@embedpdf/core";
|
|
2
|
+
import { ignore } from "@embedpdf/models";
|
|
3
|
+
const THUMBNAIL_PLUGIN_ID = "thumbnail";
|
|
4
|
+
const manifest = {
|
|
4
5
|
id: THUMBNAIL_PLUGIN_ID,
|
|
5
6
|
name: "Thumbnail Plugin",
|
|
6
7
|
version: "1.0.0",
|
|
@@ -15,15 +16,7 @@ var manifest = {
|
|
|
15
16
|
labelHeight: 16
|
|
16
17
|
}
|
|
17
18
|
};
|
|
18
|
-
|
|
19
|
-
// src/lib/thumbnail-plugin.ts
|
|
20
|
-
import {
|
|
21
|
-
BasePlugin,
|
|
22
|
-
createBehaviorEmitter,
|
|
23
|
-
SET_DOCUMENT
|
|
24
|
-
} from "@embedpdf/core";
|
|
25
|
-
import { ignore } from "@embedpdf/models";
|
|
26
|
-
var ThumbnailPlugin = class extends BasePlugin {
|
|
19
|
+
const _ThumbnailPlugin = class _ThumbnailPlugin extends BasePlugin {
|
|
27
20
|
constructor(id, registry, cfg) {
|
|
28
21
|
super(id, registry);
|
|
29
22
|
this.cfg = cfg;
|
|
@@ -125,10 +118,9 @@ var ThumbnailPlugin = class extends BasePlugin {
|
|
|
125
118
|
return task;
|
|
126
119
|
}
|
|
127
120
|
};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
var ThumbnailPluginPackage = {
|
|
121
|
+
_ThumbnailPlugin.id = "thumbnail";
|
|
122
|
+
let ThumbnailPlugin = _ThumbnailPlugin;
|
|
123
|
+
const ThumbnailPluginPackage = {
|
|
132
124
|
manifest,
|
|
133
125
|
create: (registry, _engine, config) => new ThumbnailPlugin(THUMBNAIL_PLUGIN_ID, registry, config),
|
|
134
126
|
reducer: () => {
|
|
@@ -141,4 +133,4 @@ export {
|
|
|
141
133
|
ThumbnailPluginPackage,
|
|
142
134
|
manifest
|
|
143
135
|
};
|
|
144
|
-
//# sourceMappingURL=index.js.map
|
|
136
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/manifest.ts","../src/lib/thumbnail-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { ThumbnailPluginConfig } from './types';\n\nexport const THUMBNAIL_PLUGIN_ID = 'thumbnail';\n\nexport const manifest: PluginManifest<ThumbnailPluginConfig> = {\n id: THUMBNAIL_PLUGIN_ID,\n name: 'Thumbnail Plugin',\n version: '1.0.0',\n provides: ['thumbnail'],\n requires: ['render'],\n optional: [],\n defaultConfig: {\n enabled: true,\n width: 150,\n gap: 10,\n buffer: 3,\n labelHeight: 16,\n },\n};\n","import {\n BasePlugin,\n CoreState,\n createBehaviorEmitter,\n PluginRegistry,\n SET_DOCUMENT,\n StoreState,\n} from '@embedpdf/core';\nimport { ThumbMeta, ThumbnailPluginConfig, WindowState } from './types';\nimport { ThumbnailCapability } from './types';\nimport { ignore, PdfErrorReason, Task } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\n\nexport class ThumbnailPlugin extends BasePlugin<ThumbnailPluginConfig, ThumbnailCapability> {\n static readonly id = 'thumbnail' as const;\n\n private renderCapability: RenderCapability;\n private thumbs: ThumbMeta[] = [];\n private window: WindowState | null = null;\n private readonly emitWindow = createBehaviorEmitter<WindowState>();\n private readonly taskCache = new Map<number, Task<Blob, PdfErrorReason>>();\n\n constructor(\n id: string,\n registry: PluginRegistry,\n private cfg: ThumbnailPluginConfig,\n ) {\n super(id, registry);\n\n this.renderCapability = this.registry.getPlugin<RenderPlugin>('render')!.provides();\n\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n this.taskCache.clear();\n this.setWindowState(state);\n });\n }\n\n /* ------------ init ------------------------------------------------ */\n async initialize(): Promise<void> {}\n\n private setWindowState(state: StoreState<CoreState>) {\n const core = state.core;\n\n if (!core.document) return;\n\n const W = this.cfg.width ?? 120;\n const L = this.cfg.labelHeight ?? 16; // label\n const GAP = this.cfg.gap ?? 8;\n\n let offset = 0;\n this.thumbs = core.document.pages.map((p) => {\n const ratio = p.size.height / p.size.width;\n const thumbH = Math.round(W * ratio);\n const wrapH = thumbH + L; // no GAP here\n\n const meta: ThumbMeta = {\n pageIndex: p.index,\n width: W,\n height: thumbH,\n wrapperHeight: wrapH,\n top: offset,\n labelHeight: L,\n };\n offset += wrapH + GAP; // GAP added *after* wrapper\n return meta;\n });\n\n this.window = {\n start: -1,\n end: -1,\n items: [],\n totalHeight: offset - GAP, // last item has no gap below\n };\n this.emitWindow.emit(this.window);\n }\n\n /* ------------ capability ----------------------------------------- */\n protected buildCapability(): ThumbnailCapability {\n return {\n onWindow: this.emitWindow.on,\n setViewport: (y, h) => this.updateWindow(y, h),\n renderThumb: (idx, dpr) => this.renderThumb(idx, dpr),\n };\n }\n\n /* ------------ windowing math ------------------------------------- */\n private updateWindow(scrollY: number, viewportH: number) {\n const BUF = this.cfg.buffer ?? 3;\n\n /* -------- find first visible wrapper ---------- */\n let low = 0,\n high = this.thumbs.length - 1,\n first = 0;\n while (low <= high) {\n const mid = (low + high) >> 1;\n const m = this.thumbs[mid];\n if (m.top + m.wrapperHeight < scrollY) low = mid + 1;\n else {\n first = mid;\n high = mid - 1;\n }\n }\n\n /* -------- find last visible + buffer ---------- */\n let last = first;\n const limit = scrollY + viewportH;\n while (last + 1 < this.thumbs.length && this.thumbs[last].top < limit) last++;\n last = Math.min(this.thumbs.length - 1, last + BUF);\n\n const start = Math.max(0, first - BUF);\n if (this.window && start === this.window.start && last === this.window.end) return;\n\n this.window = {\n start,\n end: last,\n items: this.thumbs.slice(start, last + 1),\n totalHeight: this.window!.totalHeight,\n };\n this.emitWindow.emit(this.window);\n }\n\n /* ------------ thumbnail raster ----------------------------------- */\n private renderThumb(idx: number, dpr: number) {\n if (this.taskCache.has(idx)) return this.taskCache.get(idx)!;\n\n const core = this.coreState.core;\n const page = core.document!.pages[idx];\n const scale = (this.cfg.width ?? 120) / page.size.width;\n\n const task = this.renderCapability.renderPageRect({\n pageIndex: idx,\n rect: { origin: { x: 0, y: 0 }, size: page.size },\n scaleFactor: scale,\n dpr,\n });\n\n this.taskCache.set(idx, task);\n\n task.wait(ignore, () => {\n this.taskCache.delete(idx);\n });\n\n return task;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, THUMBNAIL_PLUGIN_ID } from './manifest';\nimport { ThumbnailPluginConfig } from './types';\nimport { ThumbnailPlugin } from './thumbnail-plugin';\n\nexport const ThumbnailPluginPackage: PluginPackage<ThumbnailPlugin, ThumbnailPluginConfig> = {\n manifest,\n create: (registry, _engine, config) => new ThumbnailPlugin(THUMBNAIL_PLUGIN_ID, registry, config),\n reducer: () => {},\n initialState: {},\n};\n\nexport * from './thumbnail-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/lib/manifest.ts","../src/lib/thumbnail-plugin.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { ThumbnailPluginConfig } from './types';\n\nexport const THUMBNAIL_PLUGIN_ID = 'thumbnail';\n\nexport const manifest: PluginManifest<ThumbnailPluginConfig> = {\n id: THUMBNAIL_PLUGIN_ID,\n name: 'Thumbnail Plugin',\n version: '1.0.0',\n provides: ['thumbnail'],\n requires: ['render'],\n optional: [],\n defaultConfig: {\n enabled: true,\n width: 150,\n gap: 10,\n buffer: 3,\n labelHeight: 16,\n },\n};\n","import {\n BasePlugin,\n CoreState,\n createBehaviorEmitter,\n PluginRegistry,\n SET_DOCUMENT,\n StoreState,\n} from '@embedpdf/core';\nimport { ThumbMeta, ThumbnailPluginConfig, WindowState } from './types';\nimport { ThumbnailCapability } from './types';\nimport { ignore, PdfErrorReason, Task } from '@embedpdf/models';\nimport { RenderCapability, RenderPlugin } from '@embedpdf/plugin-render';\n\nexport class ThumbnailPlugin extends BasePlugin<ThumbnailPluginConfig, ThumbnailCapability> {\n static readonly id = 'thumbnail' as const;\n\n private renderCapability: RenderCapability;\n private thumbs: ThumbMeta[] = [];\n private window: WindowState | null = null;\n private readonly emitWindow = createBehaviorEmitter<WindowState>();\n private readonly taskCache = new Map<number, Task<Blob, PdfErrorReason>>();\n\n constructor(\n id: string,\n registry: PluginRegistry,\n private cfg: ThumbnailPluginConfig,\n ) {\n super(id, registry);\n\n this.renderCapability = this.registry.getPlugin<RenderPlugin>('render')!.provides();\n\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n this.taskCache.clear();\n this.setWindowState(state);\n });\n }\n\n /* ------------ init ------------------------------------------------ */\n async initialize(): Promise<void> {}\n\n private setWindowState(state: StoreState<CoreState>) {\n const core = state.core;\n\n if (!core.document) return;\n\n const W = this.cfg.width ?? 120;\n const L = this.cfg.labelHeight ?? 16; // label\n const GAP = this.cfg.gap ?? 8;\n\n let offset = 0;\n this.thumbs = core.document.pages.map((p) => {\n const ratio = p.size.height / p.size.width;\n const thumbH = Math.round(W * ratio);\n const wrapH = thumbH + L; // no GAP here\n\n const meta: ThumbMeta = {\n pageIndex: p.index,\n width: W,\n height: thumbH,\n wrapperHeight: wrapH,\n top: offset,\n labelHeight: L,\n };\n offset += wrapH + GAP; // GAP added *after* wrapper\n return meta;\n });\n\n this.window = {\n start: -1,\n end: -1,\n items: [],\n totalHeight: offset - GAP, // last item has no gap below\n };\n this.emitWindow.emit(this.window);\n }\n\n /* ------------ capability ----------------------------------------- */\n protected buildCapability(): ThumbnailCapability {\n return {\n onWindow: this.emitWindow.on,\n setViewport: (y, h) => this.updateWindow(y, h),\n renderThumb: (idx, dpr) => this.renderThumb(idx, dpr),\n };\n }\n\n /* ------------ windowing math ------------------------------------- */\n private updateWindow(scrollY: number, viewportH: number) {\n const BUF = this.cfg.buffer ?? 3;\n\n /* -------- find first visible wrapper ---------- */\n let low = 0,\n high = this.thumbs.length - 1,\n first = 0;\n while (low <= high) {\n const mid = (low + high) >> 1;\n const m = this.thumbs[mid];\n if (m.top + m.wrapperHeight < scrollY) low = mid + 1;\n else {\n first = mid;\n high = mid - 1;\n }\n }\n\n /* -------- find last visible + buffer ---------- */\n let last = first;\n const limit = scrollY + viewportH;\n while (last + 1 < this.thumbs.length && this.thumbs[last].top < limit) last++;\n last = Math.min(this.thumbs.length - 1, last + BUF);\n\n const start = Math.max(0, first - BUF);\n if (this.window && start === this.window.start && last === this.window.end) return;\n\n this.window = {\n start,\n end: last,\n items: this.thumbs.slice(start, last + 1),\n totalHeight: this.window!.totalHeight,\n };\n this.emitWindow.emit(this.window);\n }\n\n /* ------------ thumbnail raster ----------------------------------- */\n private renderThumb(idx: number, dpr: number) {\n if (this.taskCache.has(idx)) return this.taskCache.get(idx)!;\n\n const core = this.coreState.core;\n const page = core.document!.pages[idx];\n const scale = (this.cfg.width ?? 120) / page.size.width;\n\n const task = this.renderCapability.renderPageRect({\n pageIndex: idx,\n rect: { origin: { x: 0, y: 0 }, size: page.size },\n scaleFactor: scale,\n dpr,\n });\n\n this.taskCache.set(idx, task);\n\n task.wait(ignore, () => {\n this.taskCache.delete(idx);\n });\n\n return task;\n }\n}\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, THUMBNAIL_PLUGIN_ID } from './manifest';\nimport { ThumbnailPluginConfig } from './types';\nimport { ThumbnailPlugin } from './thumbnail-plugin';\n\nexport const ThumbnailPluginPackage: PluginPackage<ThumbnailPlugin, ThumbnailPluginConfig> = {\n manifest,\n create: (registry, _engine, config) => new ThumbnailPlugin(THUMBNAIL_PLUGIN_ID, registry, config),\n reducer: () => {},\n initialState: {},\n};\n\nexport * from './thumbnail-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { PluginPackage } from '@embedpdf/core';
|
|
2
|
+
import { ThumbnailPluginConfig } from './types';
|
|
3
|
+
import { ThumbnailPlugin } from './thumbnail-plugin';
|
|
4
|
+
export declare const ThumbnailPluginPackage: PluginPackage<ThumbnailPlugin, ThumbnailPluginConfig>;
|
|
5
|
+
export * from './thumbnail-plugin';
|
|
6
|
+
export * from './types';
|
|
7
|
+
export * from './manifest';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BasePlugin, PluginRegistry } from '@embedpdf/core';
|
|
2
|
+
import { ThumbnailPluginConfig, ThumbnailCapability } from './types';
|
|
3
|
+
export declare class ThumbnailPlugin extends BasePlugin<ThumbnailPluginConfig, ThumbnailCapability> {
|
|
4
|
+
private cfg;
|
|
5
|
+
static readonly id: "thumbnail";
|
|
6
|
+
private renderCapability;
|
|
7
|
+
private thumbs;
|
|
8
|
+
private window;
|
|
9
|
+
private readonly emitWindow;
|
|
10
|
+
private readonly taskCache;
|
|
11
|
+
constructor(id: string, registry: PluginRegistry, cfg: ThumbnailPluginConfig);
|
|
12
|
+
initialize(): Promise<void>;
|
|
13
|
+
private setWindowState;
|
|
14
|
+
protected buildCapability(): ThumbnailCapability;
|
|
15
|
+
private updateWindow;
|
|
16
|
+
private renderThumb;
|
|
17
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { BasePluginConfig } from '@embedpdf/core';
|
|
2
|
+
import { PdfErrorReason, Task } from '@embedpdf/models';
|
|
3
|
+
export interface ThumbnailPluginConfig extends BasePluginConfig {
|
|
4
|
+
width?: number;
|
|
5
|
+
gap?: number;
|
|
6
|
+
buffer?: number;
|
|
7
|
+
labelHeight?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface ThumbMeta {
|
|
10
|
+
pageIndex: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
wrapperHeight: number;
|
|
14
|
+
top: number;
|
|
15
|
+
labelHeight: number;
|
|
16
|
+
}
|
|
17
|
+
export interface WindowState {
|
|
18
|
+
start: number;
|
|
19
|
+
end: number;
|
|
20
|
+
items: ThumbMeta[];
|
|
21
|
+
totalHeight: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ThumbnailCapability {
|
|
24
|
+
/** called from UI on every scroll */
|
|
25
|
+
setViewport(offsetY: number, viewportH: number): void;
|
|
26
|
+
/** listen to window changes */
|
|
27
|
+
onWindow(cb: (w: WindowState) => void): () => void;
|
|
28
|
+
/** lazily render one thumb */
|
|
29
|
+
renderThumb(pageIdx: number, dpr: number): Task<Blob, PdfErrorReason>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Fragment } from 'preact';
|
|
2
|
+
export { useEffect, useRef, useState, useCallback, useMemo } from 'preact/hooks';
|
|
3
|
+
export type { ComponentChildren as ReactNode } from 'preact';
|
|
4
|
+
export type CSSProperties = import('preact').JSX.CSSProperties;
|
|
5
|
+
export type HTMLAttributes<T = any> = import('preact').JSX.HTMLAttributes<T extends EventTarget ? T : never>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '@embedpdf/core/preact';
|
package/dist/preact/index.cjs
CHANGED
|
@@ -1,124 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/preact/index.ts
|
|
21
|
-
var preact_exports = {};
|
|
22
|
-
__export(preact_exports, {
|
|
23
|
-
ThumbImg: () => ThumbImg,
|
|
24
|
-
ThumbnailsPane: () => ThumbnailsPane,
|
|
25
|
-
useThumbnailCapability: () => useThumbnailCapability,
|
|
26
|
-
useThumbnailPlugin: () => useThumbnailPlugin
|
|
27
|
-
});
|
|
28
|
-
module.exports = __toCommonJS(preact_exports);
|
|
29
|
-
|
|
30
|
-
// src/preact/hooks/use-thumbnail.ts
|
|
31
|
-
var import_preact = require("@embedpdf/core/preact");
|
|
32
|
-
var import_plugin_thumbnail = require("@embedpdf/plugin-thumbnail");
|
|
33
|
-
var useThumbnailPlugin = () => (0, import_preact.usePlugin)(import_plugin_thumbnail.ThumbnailPlugin.id);
|
|
34
|
-
var useThumbnailCapability = () => (0, import_preact.useCapability)(import_plugin_thumbnail.ThumbnailPlugin.id);
|
|
35
|
-
|
|
36
|
-
// src/preact/components/thumbnails-pane.tsx
|
|
37
|
-
var import_hooks = require("preact/hooks");
|
|
38
|
-
var import_jsx_runtime = require("preact/jsx-runtime");
|
|
39
|
-
function ThumbnailsPane({
|
|
40
|
-
style,
|
|
41
|
-
selectedPage,
|
|
42
|
-
scrollOptions = { behavior: "smooth", block: "nearest", inline: "nearest" },
|
|
43
|
-
...props
|
|
44
|
-
}) {
|
|
45
|
-
const { provides: thumbs } = useThumbnailCapability();
|
|
46
|
-
const viewportRef = (0, import_hooks.useRef)(null);
|
|
47
|
-
const [window2, setWindow] = (0, import_hooks.useState)(null);
|
|
48
|
-
(0, import_hooks.useEffect)(() => thumbs?.onWindow(setWindow), [thumbs]);
|
|
49
|
-
(0, import_hooks.useEffect)(() => {
|
|
50
|
-
const vp = viewportRef.current;
|
|
51
|
-
if (!vp) return;
|
|
52
|
-
const onScroll = () => thumbs?.setViewport(vp.scrollTop, vp.clientHeight);
|
|
53
|
-
vp.addEventListener("scroll", onScroll);
|
|
54
|
-
return () => vp.removeEventListener("scroll", onScroll);
|
|
55
|
-
}, [thumbs]);
|
|
56
|
-
(0, import_hooks.useEffect)(() => {
|
|
57
|
-
const vp = viewportRef.current;
|
|
58
|
-
if (!vp || !thumbs) return;
|
|
59
|
-
if (window2?.items.length === 0) {
|
|
60
|
-
thumbs.setViewport(vp.scrollTop, vp.clientHeight);
|
|
61
|
-
}
|
|
62
|
-
}, [window2, thumbs]);
|
|
63
|
-
(0, import_hooks.useEffect)(() => {
|
|
64
|
-
if (!selectedPage || !window2) return;
|
|
65
|
-
const item = window2.items.find((it) => it.pageIndex + 1 === selectedPage);
|
|
66
|
-
if (!item) return;
|
|
67
|
-
const vp = viewportRef.current;
|
|
68
|
-
if (!vp) return;
|
|
69
|
-
const margin = 8;
|
|
70
|
-
if (item.top < vp.scrollTop + margin) {
|
|
71
|
-
vp.scrollTo({ top: item.top, ...scrollOptions });
|
|
72
|
-
} else if (item.top + item.wrapperHeight + item.labelHeight > vp.scrollTop + vp.clientHeight - margin) {
|
|
73
|
-
vp.scrollTo({
|
|
74
|
-
top: item.top + item.wrapperHeight + item.labelHeight - vp.clientHeight,
|
|
75
|
-
...scrollOptions
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}, [selectedPage, window2, scrollOptions]);
|
|
79
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: viewportRef, style: { overflowY: "auto", position: "relative", ...style }, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { height: window2?.totalHeight ?? 0, position: "relative" }, children: window2?.items.map((m) => props.children(m)) }) });
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// src/preact/components/thumbnail-img.tsx
|
|
83
|
-
var import_hooks3 = require("preact/hooks");
|
|
84
|
-
var import_models = require("@embedpdf/models");
|
|
85
|
-
var import_jsx_runtime2 = require("preact/jsx-runtime");
|
|
86
|
-
function ThumbImg({ meta, style, ...props }) {
|
|
87
|
-
const { provides: thumbs } = useThumbnailCapability();
|
|
88
|
-
const [url, setUrl] = (0, import_hooks3.useState)();
|
|
89
|
-
const urlRef = (0, import_hooks3.useRef)(null);
|
|
90
|
-
(0, import_hooks3.useEffect)(() => {
|
|
91
|
-
const task = thumbs?.renderThumb(meta.pageIndex, window.devicePixelRatio);
|
|
92
|
-
task?.wait((blob) => {
|
|
93
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
94
|
-
urlRef.current = objectUrl;
|
|
95
|
-
setUrl(objectUrl);
|
|
96
|
-
}, import_models.ignore);
|
|
97
|
-
return () => {
|
|
98
|
-
if (urlRef.current) {
|
|
99
|
-
URL.revokeObjectURL(urlRef.current);
|
|
100
|
-
urlRef.current = null;
|
|
101
|
-
} else {
|
|
102
|
-
task?.abort({
|
|
103
|
-
code: import_models.PdfErrorCode.Cancelled,
|
|
104
|
-
message: "canceled render task"
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
}, [meta.pageIndex]);
|
|
109
|
-
const handleImageLoad = () => {
|
|
110
|
-
if (urlRef.current) {
|
|
111
|
-
URL.revokeObjectURL(urlRef.current);
|
|
112
|
-
urlRef.current = null;
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
return url ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src: url, onLoad: handleImageLoad, style, ...props }) : null;
|
|
116
|
-
}
|
|
117
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
118
|
-
0 && (module.exports = {
|
|
119
|
-
ThumbImg,
|
|
120
|
-
ThumbnailsPane,
|
|
121
|
-
useThumbnailCapability,
|
|
122
|
-
useThumbnailPlugin
|
|
123
|
-
});
|
|
124
|
-
//# sourceMappingURL=index.cjs.map
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/preact"),t=require("@embedpdf/plugin-thumbnail"),r=require("preact/jsx-runtime");require("preact");const n=require("preact/hooks"),l=require("@embedpdf/models"),i=()=>e.useCapability(t.ThumbnailPlugin.id);exports.ThumbImg=function({meta:e,style:t,...o}){const{provides:s}=i(),[u,c]=n.useState(),a=n.useRef(null);return n.useEffect((()=>{const t=null==s?void 0:s.renderThumb(e.pageIndex,window.devicePixelRatio);return null==t||t.wait((e=>{const t=URL.createObjectURL(e);a.current=t,c(t)}),l.ignore),()=>{a.current?(URL.revokeObjectURL(a.current),a.current=null):null==t||t.abort({code:l.PdfErrorCode.Cancelled,message:"canceled render task"})}}),[e.pageIndex]),u?r.jsx("img",{src:u,onLoad:()=>{a.current&&(URL.revokeObjectURL(a.current),a.current=null)},style:t,...o}):null},exports.ThumbnailsPane=function({style:e,selectedPage:t,scrollOptions:l={behavior:"smooth",block:"nearest",inline:"nearest"},...o}){const{provides:s}=i(),u=n.useRef(null),[c,a]=n.useState(null);return n.useEffect((()=>null==s?void 0:s.onWindow(a)),[s]),n.useEffect((()=>{const e=u.current;if(!e)return;const t=()=>null==s?void 0:s.setViewport(e.scrollTop,e.clientHeight);return e.addEventListener("scroll",t),()=>e.removeEventListener("scroll",t)}),[s]),n.useEffect((()=>{const e=u.current;e&&s&&0===(null==c?void 0:c.items.length)&&s.setViewport(e.scrollTop,e.clientHeight)}),[c,s]),n.useEffect((()=>{if(!t||!c)return;const e=c.items.find((e=>e.pageIndex+1===t));if(!e)return;const r=u.current;if(!r)return;e.top<r.scrollTop+8?r.scrollTo({top:e.top,...l}):e.top+e.wrapperHeight+e.labelHeight>r.scrollTop+r.clientHeight-8&&r.scrollTo({top:e.top+e.wrapperHeight+e.labelHeight-r.clientHeight,...l})}),[t,c,l]),r.jsx("div",{ref:u,style:{overflowY:"auto",position:"relative",...e},...o,children:r.jsx("div",{style:{height:(null==c?void 0:c.totalHeight)??0,position:"relative"},children:null==c?void 0:c.items.map((e=>o.children(e)))})})},exports.useThumbnailCapability=i,exports.useThumbnailPlugin=()=>e.usePlugin(t.ThumbnailPlugin.id);
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|