@embedpdf/plugin-render 1.4.1 → 2.0.0-next.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/vue/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { defineComponent, computed, ref, watchEffect, onBeforeUnmount, createElementBlock, createCommentVNode, openBlock } from "vue";
1
+ import { defineComponent, ref, computed, watch, createElementBlock, createCommentVNode, openBlock, mergeProps } from "vue";
2
2
  import { ignore, PdfErrorCode } from "@embedpdf/models";
3
- import { useCapability, usePlugin } from "@embedpdf/core/vue";
3
+ import { useCapability, usePlugin, useDocumentState } from "@embedpdf/core/vue";
4
4
  import { RenderPlugin } from "@embedpdf/plugin-render";
5
5
  export * from "@embedpdf/plugin-render";
6
6
  const useRenderPlugin = () => usePlugin(RenderPlugin.id);
@@ -9,86 +9,98 @@ const _hoisted_1 = ["src"];
9
9
  const _sfc_main = /* @__PURE__ */ defineComponent({
10
10
  __name: "render-layer",
11
11
  props: {
12
+ documentId: {},
12
13
  pageIndex: {},
13
14
  scale: {},
14
- scaleFactor: {},
15
15
  dpr: {}
16
16
  },
17
17
  setup(__props) {
18
18
  const props = __props;
19
- const actualScale = computed(() => props.scale ?? props.scaleFactor ?? 1);
20
- const actualDpr = computed(() => props.dpr ?? window.devicePixelRatio);
21
19
  const { provides: renderProvides } = useRenderCapability();
22
- const { plugin: renderPlugin } = useRenderPlugin();
20
+ const documentState = useDocumentState(() => props.documentId);
23
21
  const imageUrl = ref(null);
24
- const refreshTick = ref(0);
25
22
  let urlRef = null;
26
23
  let hasLoaded = false;
27
- watchEffect((onCleanup) => {
28
- if (!renderPlugin.value) return;
29
- const unsubscribe = renderPlugin.value.onRefreshPages((pages) => {
30
- if (pages.includes(props.pageIndex)) {
31
- refreshTick.value++;
32
- }
33
- });
34
- onCleanup(unsubscribe);
24
+ const refreshVersion = computed(() => {
25
+ if (!documentState.value) return 0;
26
+ return documentState.value.pageRefreshVersions[props.pageIndex] || 0;
27
+ });
28
+ const actualScale = computed(() => {
29
+ var _a;
30
+ if (props.scale !== void 0) return props.scale;
31
+ return ((_a = documentState.value) == null ? void 0 : _a.scale) ?? 1;
35
32
  });
36
- watchEffect((onCleanup) => {
37
- const pageIndex = props.pageIndex;
38
- const scale = actualScale.value;
39
- const dpr = actualDpr.value;
40
- refreshTick.value;
41
- const capability = renderProvides.value;
42
- if (!capability) return;
43
- if (urlRef && hasLoaded) {
44
- URL.revokeObjectURL(urlRef);
45
- urlRef = null;
46
- hasLoaded = false;
47
- }
48
- const task = capability.renderPage({
49
- pageIndex,
50
- options: {
51
- scaleFactor: scale,
52
- dpr
33
+ const actualDpr = computed(() => {
34
+ if (props.dpr !== void 0) return props.dpr;
35
+ return window.devicePixelRatio;
36
+ });
37
+ watch(
38
+ [
39
+ () => props.documentId,
40
+ () => props.pageIndex,
41
+ actualScale,
42
+ actualDpr,
43
+ renderProvides,
44
+ refreshVersion
45
+ ],
46
+ ([docId, pageIdx, scale, dpr, capability], [prevDocId], onCleanup) => {
47
+ if (!capability) {
48
+ imageUrl.value = null;
49
+ return;
53
50
  }
54
- });
55
- task.wait((blob) => {
56
- const objectUrl = URL.createObjectURL(blob);
57
- urlRef = objectUrl;
58
- imageUrl.value = objectUrl;
59
- hasLoaded = false;
60
- }, ignore);
61
- onCleanup(() => {
62
- if (urlRef) {
63
- if (hasLoaded) {
51
+ if (prevDocId !== void 0 && prevDocId !== docId) {
52
+ imageUrl.value = null;
53
+ if (urlRef && hasLoaded) {
64
54
  URL.revokeObjectURL(urlRef);
65
55
  urlRef = null;
66
56
  hasLoaded = false;
67
57
  }
68
- } else {
69
- task.abort({
70
- code: PdfErrorCode.Cancelled,
71
- message: "canceled render task"
72
- });
73
58
  }
74
- });
75
- });
76
- onBeforeUnmount(() => {
77
- if (urlRef) {
78
- URL.revokeObjectURL(urlRef);
79
- urlRef = null;
80
- }
81
- });
59
+ if (urlRef && hasLoaded && prevDocId === docId) {
60
+ URL.revokeObjectURL(urlRef);
61
+ urlRef = null;
62
+ hasLoaded = false;
63
+ }
64
+ const task = capability.forDocument(docId).renderPage({
65
+ pageIndex: pageIdx,
66
+ options: {
67
+ scaleFactor: scale,
68
+ dpr
69
+ }
70
+ });
71
+ task.wait((blob) => {
72
+ const objectUrl = URL.createObjectURL(blob);
73
+ urlRef = objectUrl;
74
+ imageUrl.value = objectUrl;
75
+ hasLoaded = false;
76
+ }, ignore);
77
+ onCleanup(() => {
78
+ if (urlRef) {
79
+ if (hasLoaded) {
80
+ URL.revokeObjectURL(urlRef);
81
+ urlRef = null;
82
+ hasLoaded = false;
83
+ }
84
+ } else {
85
+ task.abort({
86
+ code: PdfErrorCode.Cancelled,
87
+ message: "canceled render task"
88
+ });
89
+ }
90
+ });
91
+ },
92
+ { immediate: true }
93
+ );
82
94
  function handleImageLoad() {
83
95
  hasLoaded = true;
84
96
  }
85
97
  return (_ctx, _cache) => {
86
- return imageUrl.value ? (openBlock(), createElementBlock("img", {
98
+ return imageUrl.value ? (openBlock(), createElementBlock("img", mergeProps({
87
99
  key: 0,
88
100
  src: imageUrl.value,
89
101
  style: { width: "100%", height: "100%" },
90
102
  onLoad: handleImageLoad
91
- }, null, 40, _hoisted_1)) : createCommentVNode("", true);
103
+ }, _ctx.$attrs), null, 16, _hoisted_1)) : createCommentVNode("", true);
92
104
  };
93
105
  }
94
106
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-render.ts","../../src/vue/components/render-layer.vue"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { RenderPlugin } from '@embedpdf/plugin-render';\n\nexport const useRenderPlugin = () => usePlugin<RenderPlugin>(RenderPlugin.id);\nexport const useRenderCapability = () => useCapability<RenderPlugin>(RenderPlugin.id);\n","<script setup lang=\"ts\">\nimport { ref, onBeforeUnmount, computed, watchEffect } from 'vue';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\n\nimport { useRenderCapability, useRenderPlugin } from '../hooks';\n\ninterface Props {\n pageIndex: number;\n /**\n * The scale factor for rendering the page.\n */\n scale?: number;\n /**\n * @deprecated Use `scale` instead. Will be removed in the next major release.\n */\n scaleFactor?: number;\n dpr?: number;\n}\n\nconst props = defineProps<Props>();\n\n// Handle deprecation: prefer scale over scaleFactor, but fall back to scaleFactor if scale is not provided\nconst actualScale = computed(() => props.scale ?? props.scaleFactor ?? 1);\nconst actualDpr = computed(() => props.dpr ?? window.devicePixelRatio);\n\nconst { provides: renderProvides } = useRenderCapability();\nconst { plugin: renderPlugin } = useRenderPlugin();\n\nconst imageUrl = ref<string | null>(null);\nconst refreshTick = ref(0);\n\nlet urlRef: string | null = null;\nlet hasLoaded = false;\n\n// Listen for external page refresh events\nwatchEffect((onCleanup) => {\n if (!renderPlugin.value) return;\n\n const unsubscribe = renderPlugin.value.onRefreshPages((pages: number[]) => {\n if (pages.includes(props.pageIndex)) {\n refreshTick.value++;\n }\n });\n\n onCleanup(unsubscribe);\n});\n\n// Render page when dependencies change\nwatchEffect((onCleanup) => {\n // Capture reactive dependencies\n const pageIndex = props.pageIndex;\n const scale = actualScale.value;\n const dpr = actualDpr.value;\n const tick = refreshTick.value;\n const capability = renderProvides.value;\n\n if (!capability) return;\n\n // Revoke old URL before creating new one (if it's been loaded)\n if (urlRef && hasLoaded) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n hasLoaded = false;\n }\n\n const task = capability.renderPage({\n pageIndex,\n options: {\n scaleFactor: scale,\n dpr,\n },\n });\n\n task.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef = objectUrl;\n imageUrl.value = objectUrl;\n hasLoaded = false;\n }, ignore);\n\n onCleanup(() => {\n if (urlRef) {\n // Only revoke if image has loaded\n if (hasLoaded) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n hasLoaded = false;\n }\n } else {\n // Task still in progress, abort it\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n });\n});\n\nonBeforeUnmount(() => {\n if (urlRef) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n }\n});\n\nfunction handleImageLoad() {\n hasLoaded = true;\n}\n</script>\n\n<template>\n <img\n v-if=\"imageUrl\"\n :src=\"imageUrl\"\n :style=\"{ width: '100%', height: '100%' }\"\n @load=\"handleImageLoad\"\n />\n</template>\n"],"names":["_createElementBlock"],"mappings":";;;;;AAGO,MAAM,kBAAkB,MAAM,UAAwB,aAAa,EAAE;AACrE,MAAM,sBAAsB,MAAM,cAA4B,aAAa,EAAE;;;;;;;;;;;ACepF,UAAM,QAAQ;AAGd,UAAM,cAAc,SAAS,MAAM,MAAM,SAAS,MAAM,eAAe,CAAC;AACxE,UAAM,YAAY,SAAS,MAAM,MAAM,OAAO,OAAO,gBAAgB;AAErE,UAAM,EAAE,UAAU,eAAe,IAAI,oBAAoB;AACzD,UAAM,EAAE,QAAQ,aAAa,IAAI,gBAAgB;AAE3C,UAAA,WAAW,IAAmB,IAAI;AAClC,UAAA,cAAc,IAAI,CAAC;AAEzB,QAAI,SAAwB;AAC5B,QAAI,YAAY;AAGhB,gBAAY,CAAC,cAAc;AACrB,UAAA,CAAC,aAAa,MAAO;AAEzB,YAAM,cAAc,aAAa,MAAM,eAAe,CAAC,UAAoB;AACzE,YAAI,MAAM,SAAS,MAAM,SAAS,GAAG;AACvB,sBAAA;AAAA,QAAA;AAAA,MACd,CACD;AAED,gBAAU,WAAW;AAAA,IAAA,CACtB;AAGD,gBAAY,CAAC,cAAc;AAEzB,YAAM,YAAY,MAAM;AACxB,YAAM,QAAQ,YAAY;AAC1B,YAAM,MAAM,UAAU;AACT,kBAAY;AACzB,YAAM,aAAa,eAAe;AAElC,UAAI,CAAC,WAAY;AAGjB,UAAI,UAAU,WAAW;AACvB,YAAI,gBAAgB,MAAM;AACjB,iBAAA;AACG,oBAAA;AAAA,MAAA;AAGR,YAAA,OAAO,WAAW,WAAW;AAAA,QACjC;AAAA,QACA,SAAS;AAAA,UACP,aAAa;AAAA,UACb;AAAA,QAAA;AAAA,MACF,CACD;AAEI,WAAA,KAAK,CAAC,SAAS;AACZ,cAAA,YAAY,IAAI,gBAAgB,IAAI;AACjC,iBAAA;AACT,iBAAS,QAAQ;AACL,oBAAA;AAAA,SACX,MAAM;AAET,gBAAU,MAAM;AACd,YAAI,QAAQ;AAEV,cAAI,WAAW;AACb,gBAAI,gBAAgB,MAAM;AACjB,qBAAA;AACG,wBAAA;AAAA,UAAA;AAAA,QACd,OACK;AAEL,eAAK,MAAM;AAAA,YACT,MAAM,aAAa;AAAA,YACnB,SAAS;AAAA,UAAA,CACV;AAAA,QAAA;AAAA,MACH,CACD;AAAA,IAAA,CACF;AAED,oBAAgB,MAAM;AACpB,UAAI,QAAQ;AACV,YAAI,gBAAgB,MAAM;AACjB,iBAAA;AAAA,MAAA;AAAA,IACX,CACD;AAED,aAAS,kBAAkB;AACb,kBAAA;AAAA,IAAA;;aAMJ,SAAQ,sBADhBA,mBAKE,OAAA;AAAA;QAHC,KAAK,SAAQ;AAAA,QACb,OAAO,EAAiC,OAAA,QAAA,QAAA,OAAA;AAAA,QACxC,QAAM;AAAA,MAAA;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-render.ts","../../src/vue/components/render-layer.vue"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { RenderPlugin } from '@embedpdf/plugin-render';\n\nexport const useRenderPlugin = () => usePlugin<RenderPlugin>(RenderPlugin.id);\nexport const useRenderCapability = () => useCapability<RenderPlugin>(RenderPlugin.id);\n","<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue';\nimport { ignore, PdfErrorCode } from '@embedpdf/models';\nimport { useDocumentState } from '@embedpdf/core/vue';\nimport { useRenderCapability } from '../hooks';\n\ninterface RenderLayerProps {\n /**\n * The ID of the document to render from\n */\n documentId: string;\n /**\n * The page index to render (0-based)\n */\n pageIndex: number;\n /**\n * Optional scale override. If not provided, uses document's current scale.\n */\n scale?: number;\n /**\n * Optional device pixel ratio override. If not provided, uses window.devicePixelRatio.\n */\n dpr?: number;\n}\n\nconst props = defineProps<RenderLayerProps>();\n\nconst { provides: renderProvides } = useRenderCapability();\nconst documentState = useDocumentState(() => props.documentId);\n\nconst imageUrl = ref<string | null>(null);\nlet urlRef: string | null = null;\nlet hasLoaded = false;\n\n// Get refresh version from core state\nconst refreshVersion = computed(() => {\n if (!documentState.value) return 0;\n return documentState.value.pageRefreshVersions[props.pageIndex] || 0;\n});\n\n// Determine actual render options: use overrides if provided, otherwise fall back to document state\nconst actualScale = computed(() => {\n if (props.scale !== undefined) return props.scale;\n return documentState.value?.scale ?? 1;\n});\n\nconst actualDpr = computed(() => {\n if (props.dpr !== undefined) return props.dpr;\n return window.devicePixelRatio;\n});\n\n// Render page when dependencies change\nwatch(\n [\n () => props.documentId,\n () => props.pageIndex,\n actualScale,\n actualDpr,\n renderProvides,\n refreshVersion,\n ],\n ([docId, pageIdx, scale, dpr, capability], [prevDocId], onCleanup) => {\n if (!capability) {\n imageUrl.value = null;\n return;\n }\n\n // CRITICAL: Clear image immediately when documentId changes (not for zoom/scale)\n if (prevDocId !== undefined && prevDocId !== docId) {\n imageUrl.value = null;\n if (urlRef && hasLoaded) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n hasLoaded = false;\n }\n }\n\n // Revoke old URL before creating new one (if it's been loaded)\n if (urlRef && hasLoaded && prevDocId === docId) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n hasLoaded = false;\n }\n\n const task = capability.forDocument(docId).renderPage({\n pageIndex: pageIdx,\n options: {\n scaleFactor: scale,\n dpr,\n },\n });\n\n task.wait((blob) => {\n const objectUrl = URL.createObjectURL(blob);\n urlRef = objectUrl;\n imageUrl.value = objectUrl;\n hasLoaded = false;\n }, ignore);\n\n onCleanup(() => {\n if (urlRef) {\n // Only revoke if image has loaded\n if (hasLoaded) {\n URL.revokeObjectURL(urlRef);\n urlRef = null;\n hasLoaded = false;\n }\n } else {\n // Task still in progress, abort it\n task.abort({\n code: PdfErrorCode.Cancelled,\n message: 'canceled render task',\n });\n }\n });\n },\n { immediate: true },\n);\n\nfunction handleImageLoad() {\n hasLoaded = true;\n}\n</script>\n\n<template>\n <img\n v-if=\"imageUrl\"\n :src=\"imageUrl\"\n :style=\"{ width: '100%', height: '100%' }\"\n @load=\"handleImageLoad\"\n v-bind=\"$attrs\"\n />\n</template>\n"],"names":["_openBlock","_createElementBlock","_mergeProps","$attrs"],"mappings":";;;;;AAGO,MAAM,kBAAkB,MAAM,UAAwB,aAAa,EAAE;AACrE,MAAM,sBAAsB,MAAM,cAA4B,aAAa,EAAE;;;;;;;;;;;ACqBpF,UAAM,QAAQ;AAEd,UAAM,EAAE,UAAU,eAAA,IAAmB,oBAAA;AACrC,UAAM,gBAAgB,iBAAiB,MAAM,MAAM,UAAU;AAE7D,UAAM,WAAW,IAAmB,IAAI;AACxC,QAAI,SAAwB;AAC5B,QAAI,YAAY;AAGhB,UAAM,iBAAiB,SAAS,MAAM;AACpC,UAAI,CAAC,cAAc,MAAO,QAAO;AACjC,aAAO,cAAc,MAAM,oBAAoB,MAAM,SAAS,KAAK;AAAA,IACrE,CAAC;AAGD,UAAM,cAAc,SAAS,MAAM;;AACjC,UAAI,MAAM,UAAU,OAAW,QAAO,MAAM;AAC5C,eAAO,mBAAc,UAAd,mBAAqB,UAAS;AAAA,IACvC,CAAC;AAED,UAAM,YAAY,SAAS,MAAM;AAC/B,UAAI,MAAM,QAAQ,OAAW,QAAO,MAAM;AAC1C,aAAO,OAAO;AAAA,IAChB,CAAC;AAGD;AAAA,MACE;AAAA,QACE,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,QACZ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,CAAC,CAAC,OAAO,SAAS,OAAO,KAAK,UAAU,GAAG,CAAC,SAAS,GAAG,cAAc;AACpE,YAAI,CAAC,YAAY;AACf,mBAAS,QAAQ;AACjB;AAAA,QACF;AAGA,YAAI,cAAc,UAAa,cAAc,OAAO;AAClD,mBAAS,QAAQ;AACjB,cAAI,UAAU,WAAW;AACvB,gBAAI,gBAAgB,MAAM;AAC1B,qBAAS;AACT,wBAAY;AAAA,UACd;AAAA,QACF;AAGA,YAAI,UAAU,aAAa,cAAc,OAAO;AAC9C,cAAI,gBAAgB,MAAM;AAC1B,mBAAS;AACT,sBAAY;AAAA,QACd;AAEA,cAAM,OAAO,WAAW,YAAY,KAAK,EAAE,WAAW;AAAA,UACpD,WAAW;AAAA,UACX,SAAS;AAAA,YACP,aAAa;AAAA,YACb;AAAA,UAAA;AAAA,QACF,CACD;AAED,aAAK,KAAK,CAAC,SAAS;AAClB,gBAAM,YAAY,IAAI,gBAAgB,IAAI;AAC1C,mBAAS;AACT,mBAAS,QAAQ;AACjB,sBAAY;AAAA,QACd,GAAG,MAAM;AAET,kBAAU,MAAM;AACd,cAAI,QAAQ;AAEV,gBAAI,WAAW;AACb,kBAAI,gBAAgB,MAAM;AAC1B,uBAAS;AACT,0BAAY;AAAA,YACd;AAAA,UACF,OAAO;AAEL,iBAAK,MAAM;AAAA,cACT,MAAM,aAAa;AAAA,cACnB,SAAS;AAAA,YAAA,CACV;AAAA,UACH;AAAA,QACF,CAAC;AAAA,MACH;AAAA,MACA,EAAE,WAAW,KAAA;AAAA,IAAK;AAGpB,aAAS,kBAAkB;AACzB,kBAAY;AAAA,IACd;;aAKU,SAAA,SADRA,UAAA,GAAAC,mBAME,OANFC,WAME;AAAA;QAJC,KAAK,SAAA;AAAA,QACL,OAAO,EAAA,OAAA,QAAA,QAAA,OAAA;AAAA,QACP,QAAM;AAAA,MAAA,GACCC,KAAAA,MAAM,GAAA,MAAA,IAAA,UAAA;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-render",
3
- "version": "1.4.1",
3
+ "version": "2.0.0-next.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -35,13 +35,13 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@embedpdf/models": "1.4.1"
38
+ "@embedpdf/models": "2.0.0-next.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/react": "^18.2.0",
42
42
  "typescript": "^5.0.0",
43
- "@embedpdf/build": "1.1.0",
44
- "@embedpdf/core": "1.4.1"
43
+ "@embedpdf/core": "2.0.0-next.0",
44
+ "@embedpdf/build": "1.1.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "preact": "^10.26.4",
@@ -49,7 +49,7 @@
49
49
  "react-dom": ">=16.8.0",
50
50
  "vue": ">=3.2.0",
51
51
  "svelte": ">=5 <6",
52
- "@embedpdf/core": "1.4.1"
52
+ "@embedpdf/core": "2.0.0-next.0"
53
53
  },
54
54
  "files": [
55
55
  "dist",