web-annotation-renderer 0.6.0 → 0.6.2

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 (87) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +52 -51
  4. package/dist/index.js.map +1 -1
  5. package/dist/index10.cjs +1 -1
  6. package/dist/index10.cjs.map +1 -1
  7. package/dist/index10.js +13 -210
  8. package/dist/index10.js.map +1 -1
  9. package/dist/index11.cjs +1 -1
  10. package/dist/index11.cjs.map +1 -1
  11. package/dist/index11.js +50 -13
  12. package/dist/index11.js.map +1 -1
  13. package/dist/index12.cjs +1 -1
  14. package/dist/index12.cjs.map +1 -1
  15. package/dist/index12.js +155 -48
  16. package/dist/index12.js.map +1 -1
  17. package/dist/index13.cjs +1 -1
  18. package/dist/index13.cjs.map +1 -1
  19. package/dist/index13.js +34 -169
  20. package/dist/index13.js.map +1 -1
  21. package/dist/index14.cjs +1 -1
  22. package/dist/index14.cjs.map +1 -1
  23. package/dist/index14.js +65 -28
  24. package/dist/index14.js.map +1 -1
  25. package/dist/index15.cjs +1 -1
  26. package/dist/index15.cjs.map +1 -1
  27. package/dist/index15.js +33 -71
  28. package/dist/index15.js.map +1 -1
  29. package/dist/index16.cjs +1 -1
  30. package/dist/index16.cjs.map +1 -1
  31. package/dist/index16.js +77 -22
  32. package/dist/index16.js.map +1 -1
  33. package/dist/index17.cjs +1 -1
  34. package/dist/index17.cjs.map +1 -1
  35. package/dist/index17.js +31 -52
  36. package/dist/index17.js.map +1 -1
  37. package/dist/index18.cjs +1 -1
  38. package/dist/index18.cjs.map +1 -1
  39. package/dist/index18.js +22 -23
  40. package/dist/index18.js.map +1 -1
  41. package/dist/index2.cjs +1 -1
  42. package/dist/index2.cjs.map +1 -1
  43. package/dist/index2.js +5 -6
  44. package/dist/index2.js.map +1 -1
  45. package/dist/index21.cjs +1 -1
  46. package/dist/index21.cjs.map +1 -1
  47. package/dist/index21.js +48 -27
  48. package/dist/index21.js.map +1 -1
  49. package/dist/index24.cjs +1 -1
  50. package/dist/index24.js +1 -1
  51. package/dist/index25.cjs +1 -1
  52. package/dist/index25.js +1 -1
  53. package/dist/index29.cjs +1 -1
  54. package/dist/index29.cjs.map +1 -1
  55. package/dist/index29.js +70 -4
  56. package/dist/index29.js.map +1 -1
  57. package/dist/index3.cjs +1 -1
  58. package/dist/index3.js +1 -1
  59. package/dist/index30.cjs +2 -0
  60. package/dist/index30.cjs.map +1 -0
  61. package/dist/index30.js +8 -0
  62. package/dist/index30.js.map +1 -0
  63. package/dist/index31.cjs +2 -0
  64. package/dist/index31.cjs.map +1 -0
  65. package/dist/index31.js +995 -0
  66. package/dist/index31.js.map +1 -0
  67. package/dist/index5.cjs +1 -1
  68. package/dist/index5.cjs.map +1 -1
  69. package/dist/index5.js +189 -80
  70. package/dist/index5.js.map +1 -1
  71. package/dist/index6.cjs +1 -1
  72. package/dist/index6.cjs.map +1 -1
  73. package/dist/index6.js +18 -60
  74. package/dist/index6.js.map +1 -1
  75. package/dist/index7.cjs +1 -1
  76. package/dist/index7.cjs.map +1 -1
  77. package/dist/index7.js +17 -17
  78. package/dist/index7.js.map +1 -1
  79. package/dist/index8.cjs +1 -1
  80. package/dist/index8.cjs.map +1 -1
  81. package/dist/index8.js +125 -16
  82. package/dist/index8.js.map +1 -1
  83. package/dist/index9.cjs +1 -1
  84. package/dist/index9.cjs.map +1 -1
  85. package/dist/index9.js +201 -118
  86. package/dist/index9.js.map +1 -1
  87. package/package.json +4 -2
package/dist/index18.js CHANGED
@@ -1,27 +1,26 @@
1
- function h(s, t) {
2
- const { id: p, start: f, end: d, cx: o, cy: r, rx: e, ry: c } = s;
3
- if (typeof o != "number" || typeof r != "number" || typeof e != "number" || typeof c != "number")
4
- return [];
5
- const i = 36, u = [];
6
- for (let n = 0; n <= i; n++) {
7
- const a = n / i * Math.PI * 2;
8
- u.push([
9
- o + e * Math.cos(a),
10
- r + c * Math.sin(a)
11
- ]);
12
- }
13
- return [{
14
- id: p,
15
- points: u,
16
- start: f,
17
- end: d,
18
- color: t.color || "rgba(255, 165, 0, 0.8)",
19
- width: t.width || 3,
20
- lineCap: t.lineCap || "round"
21
- }];
1
+ function l(d, i) {
2
+ const { id: c, start: e, end: r, strokes: n } = d;
3
+ if (!n || n.length === 0) return [];
4
+ const a = r - e;
5
+ if (a <= 0) return [];
6
+ const f = n.reduce(
7
+ (t, o) => Math.max(t, (o.timeOffset || 0) + (o.duration || 0.5)),
8
+ 0
9
+ ) || 1, s = a / f;
10
+ return n.filter((t) => t.points && t.points.length >= 2).map((t, o) => ({
11
+ id: `${c}-${o}`,
12
+ points: t.points,
13
+ start: e + (t.timeOffset || 0) * s,
14
+ end: Math.min(
15
+ e + ((t.timeOffset || 0) + (t.duration || 0.5)) * s,
16
+ r
17
+ ),
18
+ color: t.color || i.color || "#DC143C",
19
+ width: t.width || i.width || 2,
20
+ lineCap: i.lineCap || "round"
21
+ }));
22
22
  }
23
23
  export {
24
- h as circleToStrokes,
25
- h as default
24
+ l as inkToStrokes
26
25
  };
27
26
  //# sourceMappingURL=index18.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index18.js","sources":["../src/converters/circle.js"],"sourcesContent":["/**\n * Circle Converter - Converts circle annotations to stroke commands\n *\n * Transforms circle/ellipse data into stroke paths that can be\n * rendered progressively on canvas.\n *\n * @module converters/circle\n */\n\n/**\n * Converts a circle annotation to stroke commands\n *\n * Generates an ellipse path from to 360° that renders\n * progressively around the perimeter.\n *\n * @param {Object} annotation - Circle annotation object\n * @param {string} annotation.id - Unique identifier\n * @param {number} annotation.start - Start time in seconds\n * @param {number} annotation.end - End time in seconds\n * @param {number} annotation.cx - Center x position (0-1 normalized)\n * @param {number} annotation.cy - Center y position (0-1 normalized)\n * @param {number} annotation.rx - Horizontal radius (0-1 normalized)\n * @param {number} annotation.ry - Vertical radius (0-1 normalized)\n * @param {Object} [annotation.style] - Optional style overrides\n * @param {Object} style - Resolved style configuration\n * @param {string} style.color - Stroke color\n * @param {number} style.width - Stroke width in pixels\n * @param {string} [style.lineCap='round'] - Line cap style\n * @returns {Array<Object>} Array of stroke commands\n */\nexport function circleToStrokes(annotation, style) {\n const { id, start, end, cx, cy, rx, ry } = annotation;\n\n if (typeof cx !== 'number' || typeof cy !== 'number' ||\n typeof rx !== 'number' || typeof ry !== 'number') {\n return [];\n }\n\n // Generate ellipse points (36 segments + closing point)\n const numPoints = 36;\n const points = [];\n\n for (let i = 0; i <= numPoints; i++) {\n const angle = (i / numPoints) * Math.PI * 2;\n points.push([\n cx + rx * Math.cos(angle),\n cy + ry * Math.sin(angle)\n ]);\n }\n\n return [{\n id,\n points,\n start,\n end,\n color: style.color || 'rgba(255, 165, 0, 0.8)',\n width: style.width || 3,\n lineCap: style.lineCap || 'round'\n }];\n}\n\nexport default circleToStrokes;\n"],"names":["circleToStrokes","annotation","style","id","start","end","cx","cy","rx","ry","numPoints","points","i","angle"],"mappings":"AA8BO,SAASA,EAAgBC,GAAYC,GAAO;AACjD,QAAM,EAAE,IAAAC,GAAI,OAAAC,GAAO,KAAAC,GAAK,IAAAC,GAAI,IAAAC,GAAI,IAAAC,GAAI,IAAAC,EAAE,IAAKR;AAE3C,MAAI,OAAOK,KAAO,YAAY,OAAOC,KAAO,YACxC,OAAOC,KAAO,YAAY,OAAOC,KAAO;AAC1C,WAAO,CAAA;AAIT,QAAMC,IAAY,IACZC,IAAS,CAAA;AAEf,WAASC,IAAI,GAAGA,KAAKF,GAAWE,KAAK;AACnC,UAAMC,IAASD,IAAIF,IAAa,KAAK,KAAK;AAC1C,IAAAC,EAAO,KAAK;AAAA,MACVL,IAAKE,IAAK,KAAK,IAAIK,CAAK;AAAA,MACxBN,IAAKE,IAAK,KAAK,IAAII,CAAK;AAAA,IAC9B,CAAK;AAAA,EACH;AAEA,SAAO,CAAC;AAAA,IACN,IAAAV;AAAA,IACA,QAAAQ;AAAA,IACA,OAAAP;AAAA,IACA,KAAAC;AAAA,IACA,OAAOH,EAAM,SAAS;AAAA,IACtB,OAAOA,EAAM,SAAS;AAAA,IACtB,SAASA,EAAM,WAAW;AAAA,EAC9B,CAAG;AACH;"}
1
+ {"version":3,"file":"index18.js","sources":["../src/converters/ink.js"],"sourcesContent":["/**\n * Ink Annotation Converter\n *\n * Converts freehand ink annotations to renderer stroke commands.\n * Unlike other converters, ink does NOT use RoughJS — strokes are\n * already hand-drawn and only need timing mapped to the annotation window.\n *\n * @module converters/ink\n */\n\n/**\n * Convert ink annotation to renderer strokes\n *\n * Maps each sub-stroke's recorded timing (timeOffset + duration) to the\n * annotation's playback window [start, end] using a proportional timeScale.\n *\n * @param {Object} annotation - Ink annotation object\n * @param {string} annotation.id - Annotation ID\n * @param {number} annotation.start - Playback start time (seconds)\n * @param {number} annotation.end - Playback end time (seconds)\n * @param {Array} annotation.strokes - Sub-strokes with points and timing\n * @param {Object} style - Resolved style from StrokeRenderer config\n * @returns {Array} Renderer stroke commands\n */\nexport function inkToStrokes(annotation, style) {\n const { id, start, end, strokes: subStrokes } = annotation;\n if (!subStrokes || subStrokes.length === 0) return [];\n\n const totalDuration = end - start;\n if (totalDuration <= 0) return [];\n\n // Calculate recorded session length from stroke timing\n const sessionDuration = subStrokes.reduce(\n (max, s) => Math.max(max, (s.timeOffset || 0) + (s.duration || 0.5)),\n 0\n ) || 1;\n const timeScale = totalDuration / sessionDuration;\n\n return subStrokes\n .filter((sub) => sub.points && sub.points.length >= 2)\n .map((sub, i) => ({\n id: `${id}-${i}`,\n points: sub.points,\n start: start + (sub.timeOffset || 0) * timeScale,\n end: Math.min(\n start + ((sub.timeOffset || 0) + (sub.duration || 0.5)) * timeScale,\n end\n ),\n color: sub.color || style.color || '#DC143C',\n width: sub.width || style.width || 2,\n lineCap: style.lineCap || 'round',\n }));\n}\n"],"names":["inkToStrokes","annotation","style","id","start","end","subStrokes","totalDuration","sessionDuration","max","s","timeScale","sub","i"],"mappings":"AAwBO,SAASA,EAAaC,GAAYC,GAAO;AAC9C,QAAM,EAAE,IAAAC,GAAI,OAAAC,GAAO,KAAAC,GAAK,SAASC,EAAU,IAAKL;AAChD,MAAI,CAACK,KAAcA,EAAW,WAAW,EAAG,QAAO,CAAA;AAEnD,QAAMC,IAAgBF,IAAMD;AAC5B,MAAIG,KAAiB,EAAG,QAAO,CAAA;AAG/B,QAAMC,IAAkBF,EAAW;AAAA,IACjC,CAACG,GAAKC,MAAM,KAAK,IAAID,IAAMC,EAAE,cAAc,MAAMA,EAAE,YAAY,IAAI;AAAA,IACnE;AAAA,EACJ,KAAO,GACCC,IAAYJ,IAAgBC;AAElC,SAAOF,EACJ,OAAO,CAACM,MAAQA,EAAI,UAAUA,EAAI,OAAO,UAAU,CAAC,EACpD,IAAI,CAACA,GAAKC,OAAO;AAAA,IAChB,IAAI,GAAGV,CAAE,IAAIU,CAAC;AAAA,IACd,QAAQD,EAAI;AAAA,IACZ,OAAOR,KAASQ,EAAI,cAAc,KAAKD;AAAA,IACvC,KAAK,KAAK;AAAA,MACRP,MAAUQ,EAAI,cAAc,MAAMA,EAAI,YAAY,QAAQD;AAAA,MAC1DN;AAAA,IACR;AAAA,IACM,OAAOO,EAAI,SAASV,EAAM,SAAS;AAAA,IACnC,OAAOU,EAAI,SAASV,EAAM,SAAS;AAAA,IACnC,SAASA,EAAM,WAAW;AAAA,EAChC,EAAM;AACN;"}
package/dist/index2.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./index3.cjs"),s=require("./index4.cjs"),i=require("./index5.cjs"),o=require("./index6.cjs");class a{constructor(e){if(!e||typeof e!="object")throw new Error("AnnotationRenderer: config object is required");if(!e.container||!(e.container instanceof HTMLElement))throw new Error("AnnotationRenderer: config.container must be a valid DOM element");if(!e.canvasElement||!(e.canvasElement instanceof HTMLCanvasElement))throw new Error("AnnotationRenderer: config.canvasElement must be a valid canvas element");this.config=e,this.canvasElement=e.canvasElement,this.container=e.container,this.pdfRenderer=new n.PDFRenderer,this.strokeCanvas=this._createStrokeCanvas(),this.strokeRenderer=new i.StrokeRenderer(this.strokeCanvas,e.strokeConfig||{}),this.timelineSync=new s.TimelineSync,this.currentPage=e.initialPage||1,this.currentScale=e.initialScale||1,this.annotations=e.annotations||[],this.pageCount=0,this.currentViewport=null,this.pdfUrl=null,this.timelineSync.subscribe(t=>{this.strokeRenderer.render(t)}),e.pdfUrl&&this.loadPDF(e.pdfUrl).catch(t=>{console.error("AnnotationRenderer: Failed to auto-load PDF:",t)})}_createStrokeCanvas(){const e=document.createElement("canvas");return e.className="stroke-canvas",e.style.position="absolute",e.style.top="0",e.style.left="0",e.style.pointerEvents="none",e.style.zIndex="10",this.container.appendChild(e),e}async loadPDF(e){try{if(!e||typeof e!="string")return{success:!1,error:"Invalid PDF URL provided"};const t=await this.pdfRenderer.loadDocument(e);return t.success?(this.pdfUrl=e,this.pageCount=t.pageCount,{success:!0,pageCount:t.pageCount}):t}catch(t){return console.error("AnnotationRenderer.loadPDF: Error loading PDF:",t),{success:!1,error:`Failed to load PDF: ${t.message}`}}}async setPage(e){try{if(typeof e!="number"||e<1)return{success:!1,error:"Invalid page number"};if(this.pageCount>0&&e>this.pageCount)return{success:!1,error:`Page ${e} exceeds document page count (${this.pageCount})`};this.pdfRenderer.cancelRender();const t=await this.pdfRenderer.renderPage(e,this.canvasElement,this.currentScale);if(t.success){this.currentPage=e,this.currentViewport=t.viewport,this.strokeRenderer.setViewport(t.viewport.width,t.viewport.height),this.strokeRenderer.setAnnotations(this.annotations,e);const r=this.timelineSync.getCurrentTime();return this.strokeRenderer.render(r),{success:!0,viewport:t.viewport}}return t}catch(t){return console.error("AnnotationRenderer.setPage: Error rendering page:",t),{success:!1,error:`Failed to render page: ${t.message}`}}}async setScale(e){try{return typeof e!="number"||e<=0?{success:!1,error:"Invalid scale value (must be positive number)"}:(this.currentScale=e,await this.setPage(this.currentPage))}catch(t){return console.error("AnnotationRenderer.setScale: Error changing scale:",t),{success:!1,error:`Failed to change scale: ${t.message}`}}}setAnnotations(e){Array.isArray(e)||(console.warn("AnnotationRenderer.setAnnotations: annotations must be an array"),e=[]),this.annotations=e,this.strokeRenderer.setAnnotations(e,this.currentPage);const t=this.timelineSync.getCurrentTime();this.strokeRenderer.render(t)}setStrokes(e){this.strokeRenderer.setStrokes(e);const t=this.timelineSync.getCurrentTime();this.strokeRenderer.render(t)}setTime(e){if(typeof e!="number"){console.warn("AnnotationRenderer.setTime: timestamp must be a number");return}this.timelineSync.setTime(e)}startContinuousSync(e){this.timelineSync.startContinuousSync(e)}stopContinuousSync(){this.timelineSync.stopContinuousSync()}isContinuousSyncActive(){return this.timelineSync.isRunning}updateStrokeConfig(e){if(!e||typeof e!="object")return;this.strokeRenderer.config=o.deepMerge(this.strokeRenderer.config,e),this.strokeRenderer.setAnnotations(this.annotations,this.currentPage);const t=this.timelineSync.getCurrentTime();this.strokeRenderer.render(t)}getState(){return{page:this.currentPage,scale:this.currentScale,annotations:this.annotations,pageCount:this.pageCount,time:this.timelineSync.getCurrentTime(),viewport:this.currentViewport,pdfUrl:this.pdfUrl}}destroy(){this.pdfRenderer&&this.pdfRenderer.destroy(),this.strokeRenderer&&this.strokeRenderer.destroy(),this.timelineSync&&this.timelineSync.destroy(),this.strokeCanvas&&this.strokeCanvas.parentNode&&this.strokeCanvas.parentNode.removeChild(this.strokeCanvas),this.pdfRenderer=null,this.strokeRenderer=null,this.timelineSync=null,this.strokeCanvas=null,this.config=null,this.canvasElement=null,this.container=null,this.annotations=[],this.currentPage=0,this.currentScale=1,this.pageCount=0,this.currentViewport=null,this.pdfUrl=null}}exports.AnnotationRenderer=a;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./index3.cjs"),s=require("./index4.cjs"),i=require("./index5.cjs");class o{constructor(e){if(!e||typeof e!="object")throw new Error("AnnotationRenderer: config object is required");if(!e.container||!(e.container instanceof HTMLElement))throw new Error("AnnotationRenderer: config.container must be a valid DOM element");if(!e.canvasElement||!(e.canvasElement instanceof HTMLCanvasElement))throw new Error("AnnotationRenderer: config.canvasElement must be a valid canvas element");this.config=e,this.canvasElement=e.canvasElement,this.container=e.container,this.pdfRenderer=new n.PDFRenderer,this.strokeCanvas=this._createStrokeCanvas(),this.strokeRenderer=new i.StrokeRenderer(this.strokeCanvas,e.strokeConfig||{}),this.timelineSync=new s.TimelineSync,this.currentPage=e.initialPage||1,this.currentScale=e.initialScale||1,this.annotations=e.annotations||[],this.pageCount=0,this.currentViewport=null,this.pdfUrl=null,this.timelineSync.subscribe(t=>{this.strokeRenderer.render(t)}),e.pdfUrl&&this.loadPDF(e.pdfUrl).catch(t=>{console.error("AnnotationRenderer: Failed to auto-load PDF:",t)})}_createStrokeCanvas(){const e=document.createElement("canvas");return e.className="stroke-canvas",e.style.position="absolute",e.style.top="0",e.style.left="0",e.style.pointerEvents="none",e.style.zIndex="10",this.container.appendChild(e),e}async loadPDF(e){try{if(!e||typeof e!="string")return{success:!1,error:"Invalid PDF URL provided"};const t=await this.pdfRenderer.loadDocument(e);return t.success?(this.pdfUrl=e,this.pageCount=t.pageCount,{success:!0,pageCount:t.pageCount}):t}catch(t){return console.error("AnnotationRenderer.loadPDF: Error loading PDF:",t),{success:!1,error:`Failed to load PDF: ${t.message}`}}}async setPage(e){try{if(typeof e!="number"||e<1)return{success:!1,error:"Invalid page number"};if(this.pageCount>0&&e>this.pageCount)return{success:!1,error:`Page ${e} exceeds document page count (${this.pageCount})`};this.pdfRenderer.cancelRender();const t=await this.pdfRenderer.renderPage(e,this.canvasElement,this.currentScale);if(t.success){this.currentPage=e,this.currentViewport=t.viewport,this.strokeRenderer.setViewport(t.viewport.width,t.viewport.height),this.strokeRenderer.setAnnotations(this.annotations,e);const r=this.timelineSync.getCurrentTime();return this.strokeRenderer.render(r),{success:!0,viewport:t.viewport}}return t}catch(t){return console.error("AnnotationRenderer.setPage: Error rendering page:",t),{success:!1,error:`Failed to render page: ${t.message}`}}}async setScale(e){try{return typeof e!="number"||e<=0?{success:!1,error:"Invalid scale value (must be positive number)"}:(this.currentScale=e,await this.setPage(this.currentPage))}catch(t){return console.error("AnnotationRenderer.setScale: Error changing scale:",t),{success:!1,error:`Failed to change scale: ${t.message}`}}}setAnnotations(e){Array.isArray(e)||(console.warn("AnnotationRenderer.setAnnotations: annotations must be an array"),e=[]),this.annotations=e,this.strokeRenderer.setAnnotations(e,this.currentPage);const t=this.timelineSync.getCurrentTime();this.strokeRenderer.render(t)}setStrokes(e){this.strokeRenderer.setStrokes(e);const t=this.timelineSync.getCurrentTime();this.strokeRenderer.render(t)}setTime(e){if(typeof e!="number"){console.warn("AnnotationRenderer.setTime: timestamp must be a number");return}this.timelineSync.setTime(e)}startContinuousSync(e){this.timelineSync.startContinuousSync(e)}stopContinuousSync(){this.timelineSync.stopContinuousSync()}isContinuousSyncActive(){return this.timelineSync.isRunning}updateStrokeConfig(e){if(!e||typeof e!="object")return;this.strokeRenderer.setConfig(e),this.strokeRenderer.setAnnotations(this.annotations,this.currentPage);const t=this.timelineSync.getCurrentTime();this.strokeRenderer.render(t)}getState(){return{page:this.currentPage,scale:this.currentScale,annotations:this.annotations,pageCount:this.pageCount,time:this.timelineSync.getCurrentTime(),viewport:this.currentViewport,pdfUrl:this.pdfUrl}}destroy(){this.pdfRenderer&&this.pdfRenderer.destroy(),this.strokeRenderer&&this.strokeRenderer.destroy(),this.timelineSync&&this.timelineSync.destroy(),this.strokeCanvas&&this.strokeCanvas.parentNode&&this.strokeCanvas.parentNode.removeChild(this.strokeCanvas),this.pdfRenderer=null,this.strokeRenderer=null,this.timelineSync=null,this.strokeCanvas=null,this.config=null,this.canvasElement=null,this.container=null,this.annotations=[],this.currentPage=0,this.currentScale=1,this.pageCount=0,this.currentViewport=null,this.pdfUrl=null}}exports.AnnotationRenderer=o;
2
2
  //# sourceMappingURL=index2.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index2.cjs","sources":["../src/core/AnnotationRenderer.js"],"sourcesContent":["/**\n * AnnotationRenderer - Main facade for PDF annotation rendering engine\n *\n * Orchestrates PDFRenderer, StrokeRenderer, and TimelineSync subsystems.\n * Provides the primary public API for rendering PDFs with timeline-synchronized\n * annotations. Framework-agnostic core that can be wrapped by React/Vue adapters.\n *\n * @module core/AnnotationRenderer\n */\n\nimport { PDFRenderer } from './PDFRenderer.js';\nimport { TimelineSync } from './TimelineSync.js';\nimport { StrokeRenderer } from '../renderer/StrokeRenderer.js';\nimport { deepMerge } from '../pen/effects.js';\n\n/**\n * AnnotationRenderer class\n *\n * Main engine that coordinates PDF rendering, stroke-based annotation rendering,\n * and timeline synchronization. Provides simple imperative API for consumers.\n *\n * @class\n * @example\n * const renderer = new AnnotationRenderer({\n * container: document.getElementById('container'),\n * canvasElement: document.getElementById('pdf-canvas')\n * });\n *\n * await renderer.loadPDF('/path/to/doc.pdf');\n * await renderer.setPage(1);\n * renderer.setAnnotations(annotationData);\n * renderer.setTime(3.5);\n */\nexport class AnnotationRenderer {\n /**\n * Create AnnotationRenderer instance\n *\n * @param {Object} config - Configuration object\n * @param {HTMLElement} config.container - DOM element for annotation canvas\n * @param {HTMLCanvasElement} config.canvasElement - Canvas element for PDF rendering\n * @param {string} [config.pdfUrl] - PDF URL to load immediately\n * @param {number} [config.initialPage=1] - Initial page number\n * @param {number} [config.initialScale=1.0] - Initial scale factor\n * @param {Array} [config.annotations=[]] - Initial annotation data\n * @param {Object} [config.strokeConfig] - StrokeRenderer configuration\n * @throws {Error} If config is invalid or required elements are missing\n */\n constructor(config) {\n if (!config || typeof config !== 'object') {\n throw new Error('AnnotationRenderer: config object is required');\n }\n\n if (!config.container || !(config.container instanceof HTMLElement)) {\n throw new Error('AnnotationRenderer: config.container must be a valid DOM element');\n }\n\n if (!config.canvasElement || !(config.canvasElement instanceof HTMLCanvasElement)) {\n throw new Error('AnnotationRenderer: config.canvasElement must be a valid canvas element');\n }\n\n this.config = config;\n this.canvasElement = config.canvasElement;\n this.container = config.container;\n\n // Initialize PDFRenderer\n this.pdfRenderer = new PDFRenderer();\n\n // Create stroke canvas and StrokeRenderer\n this.strokeCanvas = this._createStrokeCanvas();\n this.strokeRenderer = new StrokeRenderer(this.strokeCanvas, config.strokeConfig || {});\n\n // Initialize TimelineSync\n this.timelineSync = new TimelineSync();\n\n // State\n this.currentPage = config.initialPage || 1;\n this.currentScale = config.initialScale || 1.0;\n this.annotations = config.annotations || [];\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n\n // Wire up timeline to render\n this.timelineSync.subscribe((time) => {\n this.strokeRenderer.render(time);\n });\n\n // Auto-load PDF if provided\n if (config.pdfUrl) {\n this.loadPDF(config.pdfUrl).catch(err => {\n console.error('AnnotationRenderer: Failed to auto-load PDF:', err);\n });\n }\n }\n\n /**\n * Create stroke canvas overlay\n *\n * @private\n * @returns {HTMLCanvasElement} Stroke canvas element\n */\n _createStrokeCanvas() {\n const canvas = document.createElement('canvas');\n canvas.className = 'stroke-canvas';\n canvas.style.position = 'absolute';\n canvas.style.top = '0';\n canvas.style.left = '0';\n canvas.style.pointerEvents = 'none';\n canvas.style.zIndex = '10';\n this.container.appendChild(canvas);\n return canvas;\n }\n\n /**\n * Load PDF document from URL\n *\n * @param {string} url - URL or path to PDF file\n * @returns {Promise<Object>} Load result with success status and page count\n */\n async loadPDF(url) {\n try {\n if (!url || typeof url !== 'string') {\n return { success: false, error: 'Invalid PDF URL provided' };\n }\n\n const result = await this.pdfRenderer.loadDocument(url);\n\n if (result.success) {\n this.pdfUrl = url;\n this.pageCount = result.pageCount;\n return { success: true, pageCount: result.pageCount };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.loadPDF: Error loading PDF:', err);\n return { success: false, error: `Failed to load PDF: ${err.message}` };\n }\n }\n\n /**\n * Navigate to specific page and render it\n *\n * @param {number} pageNum - Page number (1-indexed)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setPage(pageNum) {\n try {\n if (typeof pageNum !== 'number' || pageNum < 1) {\n return { success: false, error: 'Invalid page number' };\n }\n\n if (this.pageCount > 0 && pageNum > this.pageCount) {\n return { success: false, error: `Page ${pageNum} exceeds document page count (${this.pageCount})` };\n }\n\n this.pdfRenderer.cancelRender();\n\n const result = await this.pdfRenderer.renderPage(\n pageNum,\n this.canvasElement,\n this.currentScale\n );\n\n if (result.success) {\n this.currentPage = pageNum;\n this.currentViewport = result.viewport;\n\n // Update StrokeRenderer viewport\n this.strokeRenderer.setViewport(result.viewport.width, result.viewport.height);\n\n // Re-set annotations for new page\n this.strokeRenderer.setAnnotations(this.annotations, pageNum);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n\n return { success: true, viewport: result.viewport };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.setPage: Error rendering page:', err);\n return { success: false, error: `Failed to render page: ${err.message}` };\n }\n }\n\n /**\n * Change zoom scale and re-render current page\n *\n * @param {number} scale - Scale factor (e.g., 1.0, 1.5, 2.0)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setScale(scale) {\n try {\n if (typeof scale !== 'number' || scale <= 0) {\n return { success: false, error: 'Invalid scale value (must be positive number)' };\n }\n\n this.currentScale = scale;\n return await this.setPage(this.currentPage);\n } catch (err) {\n console.error('AnnotationRenderer.setScale: Error changing scale:', err);\n return { success: false, error: `Failed to change scale: ${err.message}` };\n }\n }\n\n /**\n * Update annotation data for rendering\n *\n * @param {Array} annotations - Complete annotation array (all pages, all types)\n */\n setAnnotations(annotations) {\n if (!Array.isArray(annotations)) {\n console.warn('AnnotationRenderer.setAnnotations: annotations must be an array');\n annotations = [];\n }\n\n this.annotations = annotations;\n this.strokeRenderer.setAnnotations(annotations, this.currentPage);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Set pre-converted strokes directly\n *\n * Bypasses annotation conversion, useful for stroke commands from backend.\n *\n * @param {Array} strokes - Array of stroke command objects\n */\n setStrokes(strokes) {\n this.strokeRenderer.setStrokes(strokes);\n\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Update timeline position for animation\n *\n * @param {number} timestamp - Current timeline position in seconds\n */\n setTime(timestamp) {\n if (typeof timestamp !== 'number') {\n console.warn('AnnotationRenderer.setTime: timestamp must be a number');\n return;\n }\n\n this.timelineSync.setTime(timestamp);\n }\n\n /**\n * Start continuous timeline synchronization using requestAnimationFrame\n *\n * Polls the provided function at ~60fps for smooth animation.\n * Use this for audio/video synchronization instead of setTime().\n *\n * @param {Function} getTimeFunction - Function that returns current time in seconds\n * @example\n * const audio = document.getElementById('audio');\n * renderer.startContinuousSync(() => audio.currentTime);\n */\n startContinuousSync(getTimeFunction) {\n this.timelineSync.startContinuousSync(getTimeFunction);\n }\n\n /**\n * Stop continuous timeline synchronization\n *\n * Call this when audio/video stops or component unmounts.\n */\n stopContinuousSync() {\n this.timelineSync.stopContinuousSync();\n }\n\n /**\n * Check if continuous sync is currently active\n *\n * @returns {boolean} True if continuous sync is running\n */\n isContinuousSyncActive() {\n return this.timelineSync.isRunning;\n }\n\n /**\n * Update stroke rendering configuration at runtime\n *\n * Merges new config with existing and re-renders annotations.\n * Used for live preview of pen style changes.\n *\n * @param {Object} newConfig - New stroke configuration to merge\n */\n updateStrokeConfig(newConfig) {\n if (!newConfig || typeof newConfig !== 'object') {\n return;\n }\n\n // Merge new config into existing\n this.strokeRenderer.config = deepMerge(this.strokeRenderer.config, newConfig);\n\n // Re-convert annotations with new style and render\n this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Get current engine state snapshot\n *\n * @returns {Object} Current state\n */\n getState() {\n return {\n page: this.currentPage,\n scale: this.currentScale,\n annotations: this.annotations,\n pageCount: this.pageCount,\n time: this.timelineSync.getCurrentTime(),\n viewport: this.currentViewport,\n pdfUrl: this.pdfUrl\n };\n }\n\n /**\n * Clean up all resources and subsystems\n */\n destroy() {\n if (this.pdfRenderer) {\n this.pdfRenderer.destroy();\n }\n\n if (this.strokeRenderer) {\n this.strokeRenderer.destroy();\n }\n\n if (this.timelineSync) {\n this.timelineSync.destroy();\n }\n\n if (this.strokeCanvas && this.strokeCanvas.parentNode) {\n this.strokeCanvas.parentNode.removeChild(this.strokeCanvas);\n }\n\n this.pdfRenderer = null;\n this.strokeRenderer = null;\n this.timelineSync = null;\n this.strokeCanvas = null;\n this.config = null;\n this.canvasElement = null;\n this.container = null;\n this.annotations = [];\n this.currentPage = 0;\n this.currentScale = 1.0;\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n }\n}\n"],"names":["AnnotationRenderer","config","PDFRenderer","StrokeRenderer","TimelineSync","time","err","canvas","url","result","pageNum","currentTime","scale","annotations","strokes","timestamp","getTimeFunction","newConfig","deepMerge"],"mappings":"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"}
1
+ {"version":3,"file":"index2.cjs","sources":["../src/core/AnnotationRenderer.js"],"sourcesContent":["/**\n * AnnotationRenderer - Main facade for PDF annotation rendering engine\n *\n * Orchestrates PDFRenderer, StrokeRenderer, and TimelineSync subsystems.\n * Provides the primary public API for rendering PDFs with timeline-synchronized\n * annotations. Framework-agnostic core that can be wrapped by React/Vue adapters.\n *\n * @module core/AnnotationRenderer\n */\n\nimport { PDFRenderer } from './PDFRenderer.js';\nimport { TimelineSync } from './TimelineSync.js';\nimport { StrokeRenderer } from '../renderer/StrokeRenderer.js';\n\n/**\n * AnnotationRenderer class\n *\n * Main engine that coordinates PDF rendering, stroke-based annotation rendering,\n * and timeline synchronization. Provides simple imperative API for consumers.\n *\n * @class\n * @example\n * const renderer = new AnnotationRenderer({\n * container: document.getElementById('container'),\n * canvasElement: document.getElementById('pdf-canvas')\n * });\n *\n * await renderer.loadPDF('/path/to/doc.pdf');\n * await renderer.setPage(1);\n * renderer.setAnnotations(annotationData);\n * renderer.setTime(3.5);\n */\nexport class AnnotationRenderer {\n /**\n * Create AnnotationRenderer instance\n *\n * @param {Object} config - Configuration object\n * @param {HTMLElement} config.container - DOM element for annotation canvas\n * @param {HTMLCanvasElement} config.canvasElement - Canvas element for PDF rendering\n * @param {string} [config.pdfUrl] - PDF URL to load immediately\n * @param {number} [config.initialPage=1] - Initial page number\n * @param {number} [config.initialScale=1.0] - Initial scale factor\n * @param {Array} [config.annotations=[]] - Initial annotation data\n * @param {Object} [config.strokeConfig] - StrokeRenderer configuration\n * @throws {Error} If config is invalid or required elements are missing\n */\n constructor(config) {\n if (!config || typeof config !== 'object') {\n throw new Error('AnnotationRenderer: config object is required');\n }\n\n if (!config.container || !(config.container instanceof HTMLElement)) {\n throw new Error('AnnotationRenderer: config.container must be a valid DOM element');\n }\n\n if (!config.canvasElement || !(config.canvasElement instanceof HTMLCanvasElement)) {\n throw new Error('AnnotationRenderer: config.canvasElement must be a valid canvas element');\n }\n\n this.config = config;\n this.canvasElement = config.canvasElement;\n this.container = config.container;\n\n // Initialize PDFRenderer\n this.pdfRenderer = new PDFRenderer();\n\n // Create stroke canvas and StrokeRenderer\n this.strokeCanvas = this._createStrokeCanvas();\n this.strokeRenderer = new StrokeRenderer(this.strokeCanvas, config.strokeConfig || {});\n\n // Initialize TimelineSync\n this.timelineSync = new TimelineSync();\n\n // State\n this.currentPage = config.initialPage || 1;\n this.currentScale = config.initialScale || 1.0;\n this.annotations = config.annotations || [];\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n\n // Wire up timeline to render\n this.timelineSync.subscribe((time) => {\n this.strokeRenderer.render(time);\n });\n\n // Auto-load PDF if provided\n if (config.pdfUrl) {\n this.loadPDF(config.pdfUrl).catch(err => {\n console.error('AnnotationRenderer: Failed to auto-load PDF:', err);\n });\n }\n }\n\n /**\n * Create stroke canvas overlay\n *\n * @private\n * @returns {HTMLCanvasElement} Stroke canvas element\n */\n _createStrokeCanvas() {\n const canvas = document.createElement('canvas');\n canvas.className = 'stroke-canvas';\n canvas.style.position = 'absolute';\n canvas.style.top = '0';\n canvas.style.left = '0';\n canvas.style.pointerEvents = 'none';\n canvas.style.zIndex = '10';\n this.container.appendChild(canvas);\n return canvas;\n }\n\n /**\n * Load PDF document from URL\n *\n * @param {string} url - URL or path to PDF file\n * @returns {Promise<Object>} Load result with success status and page count\n */\n async loadPDF(url) {\n try {\n if (!url || typeof url !== 'string') {\n return { success: false, error: 'Invalid PDF URL provided' };\n }\n\n const result = await this.pdfRenderer.loadDocument(url);\n\n if (result.success) {\n this.pdfUrl = url;\n this.pageCount = result.pageCount;\n return { success: true, pageCount: result.pageCount };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.loadPDF: Error loading PDF:', err);\n return { success: false, error: `Failed to load PDF: ${err.message}` };\n }\n }\n\n /**\n * Navigate to specific page and render it\n *\n * @param {number} pageNum - Page number (1-indexed)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setPage(pageNum) {\n try {\n if (typeof pageNum !== 'number' || pageNum < 1) {\n return { success: false, error: 'Invalid page number' };\n }\n\n if (this.pageCount > 0 && pageNum > this.pageCount) {\n return { success: false, error: `Page ${pageNum} exceeds document page count (${this.pageCount})` };\n }\n\n this.pdfRenderer.cancelRender();\n\n const result = await this.pdfRenderer.renderPage(\n pageNum,\n this.canvasElement,\n this.currentScale\n );\n\n if (result.success) {\n this.currentPage = pageNum;\n this.currentViewport = result.viewport;\n\n // Update StrokeRenderer viewport\n this.strokeRenderer.setViewport(result.viewport.width, result.viewport.height);\n\n // Re-set annotations for new page\n this.strokeRenderer.setAnnotations(this.annotations, pageNum);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n\n return { success: true, viewport: result.viewport };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.setPage: Error rendering page:', err);\n return { success: false, error: `Failed to render page: ${err.message}` };\n }\n }\n\n /**\n * Change zoom scale and re-render current page\n *\n * @param {number} scale - Scale factor (e.g., 1.0, 1.5, 2.0)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setScale(scale) {\n try {\n if (typeof scale !== 'number' || scale <= 0) {\n return { success: false, error: 'Invalid scale value (must be positive number)' };\n }\n\n this.currentScale = scale;\n return await this.setPage(this.currentPage);\n } catch (err) {\n console.error('AnnotationRenderer.setScale: Error changing scale:', err);\n return { success: false, error: `Failed to change scale: ${err.message}` };\n }\n }\n\n /**\n * Update annotation data for rendering\n *\n * @param {Array} annotations - Complete annotation array (all pages, all types)\n */\n setAnnotations(annotations) {\n if (!Array.isArray(annotations)) {\n console.warn('AnnotationRenderer.setAnnotations: annotations must be an array');\n annotations = [];\n }\n\n this.annotations = annotations;\n this.strokeRenderer.setAnnotations(annotations, this.currentPage);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Set pre-converted strokes directly\n *\n * Bypasses annotation conversion, useful for stroke commands from backend.\n *\n * @param {Array} strokes - Array of stroke command objects\n */\n setStrokes(strokes) {\n this.strokeRenderer.setStrokes(strokes);\n\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Update timeline position for animation\n *\n * @param {number} timestamp - Current timeline position in seconds\n */\n setTime(timestamp) {\n if (typeof timestamp !== 'number') {\n console.warn('AnnotationRenderer.setTime: timestamp must be a number');\n return;\n }\n\n this.timelineSync.setTime(timestamp);\n }\n\n /**\n * Start continuous timeline synchronization using requestAnimationFrame\n *\n * Polls the provided function at ~60fps for smooth animation.\n * Use this for audio/video synchronization instead of setTime().\n *\n * @param {Function} getTimeFunction - Function that returns current time in seconds\n * @example\n * const audio = document.getElementById('audio');\n * renderer.startContinuousSync(() => audio.currentTime);\n */\n startContinuousSync(getTimeFunction) {\n this.timelineSync.startContinuousSync(getTimeFunction);\n }\n\n /**\n * Stop continuous timeline synchronization\n *\n * Call this when audio/video stops or component unmounts.\n */\n stopContinuousSync() {\n this.timelineSync.stopContinuousSync();\n }\n\n /**\n * Check if continuous sync is currently active\n *\n * @returns {boolean} True if continuous sync is running\n */\n isContinuousSyncActive() {\n return this.timelineSync.isRunning;\n }\n\n /**\n * Update stroke rendering configuration at runtime\n *\n * Updates config via setConfig and re-renders annotations.\n * Used for live preview of pen style changes.\n *\n * @param {Object} newConfig - New stroke configuration\n */\n updateStrokeConfig(newConfig) {\n if (!newConfig || typeof newConfig !== 'object') {\n return;\n }\n\n // Update config via setConfig\n this.strokeRenderer.setConfig(newConfig);\n\n // Re-convert annotations with new style and render\n this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Get current engine state snapshot\n *\n * @returns {Object} Current state\n */\n getState() {\n return {\n page: this.currentPage,\n scale: this.currentScale,\n annotations: this.annotations,\n pageCount: this.pageCount,\n time: this.timelineSync.getCurrentTime(),\n viewport: this.currentViewport,\n pdfUrl: this.pdfUrl\n };\n }\n\n /**\n * Clean up all resources and subsystems\n */\n destroy() {\n if (this.pdfRenderer) {\n this.pdfRenderer.destroy();\n }\n\n if (this.strokeRenderer) {\n this.strokeRenderer.destroy();\n }\n\n if (this.timelineSync) {\n this.timelineSync.destroy();\n }\n\n if (this.strokeCanvas && this.strokeCanvas.parentNode) {\n this.strokeCanvas.parentNode.removeChild(this.strokeCanvas);\n }\n\n this.pdfRenderer = null;\n this.strokeRenderer = null;\n this.timelineSync = null;\n this.strokeCanvas = null;\n this.config = null;\n this.canvasElement = null;\n this.container = null;\n this.annotations = [];\n this.currentPage = 0;\n this.currentScale = 1.0;\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n }\n}\n"],"names":["AnnotationRenderer","config","PDFRenderer","StrokeRenderer","TimelineSync","time","err","canvas","url","result","pageNum","currentTime","scale","annotations","strokes","timestamp","getTimeFunction","newConfig"],"mappings":"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"}
package/dist/index2.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import { PDFRenderer as n } from "./index3.js";
2
2
  import { TimelineSync as s } from "./index4.js";
3
3
  import { StrokeRenderer as i } from "./index5.js";
4
- import { deepMerge as o } from "./index6.js";
5
- class d {
4
+ class u {
6
5
  /**
7
6
  * Create AnnotationRenderer instance
8
7
  *
@@ -163,15 +162,15 @@ class d {
163
162
  /**
164
163
  * Update stroke rendering configuration at runtime
165
164
  *
166
- * Merges new config with existing and re-renders annotations.
165
+ * Updates config via setConfig and re-renders annotations.
167
166
  * Used for live preview of pen style changes.
168
167
  *
169
- * @param {Object} newConfig - New stroke configuration to merge
168
+ * @param {Object} newConfig - New stroke configuration
170
169
  */
171
170
  updateStrokeConfig(e) {
172
171
  if (!e || typeof e != "object")
173
172
  return;
174
- this.strokeRenderer.config = o(this.strokeRenderer.config, e), this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);
173
+ this.strokeRenderer.setConfig(e), this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);
175
174
  const t = this.timelineSync.getCurrentTime();
176
175
  this.strokeRenderer.render(t);
177
176
  }
@@ -199,6 +198,6 @@ class d {
199
198
  }
200
199
  }
201
200
  export {
202
- d as AnnotationRenderer
201
+ u as AnnotationRenderer
203
202
  };
204
203
  //# sourceMappingURL=index2.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index2.js","sources":["../src/core/AnnotationRenderer.js"],"sourcesContent":["/**\n * AnnotationRenderer - Main facade for PDF annotation rendering engine\n *\n * Orchestrates PDFRenderer, StrokeRenderer, and TimelineSync subsystems.\n * Provides the primary public API for rendering PDFs with timeline-synchronized\n * annotations. Framework-agnostic core that can be wrapped by React/Vue adapters.\n *\n * @module core/AnnotationRenderer\n */\n\nimport { PDFRenderer } from './PDFRenderer.js';\nimport { TimelineSync } from './TimelineSync.js';\nimport { StrokeRenderer } from '../renderer/StrokeRenderer.js';\nimport { deepMerge } from '../pen/effects.js';\n\n/**\n * AnnotationRenderer class\n *\n * Main engine that coordinates PDF rendering, stroke-based annotation rendering,\n * and timeline synchronization. Provides simple imperative API for consumers.\n *\n * @class\n * @example\n * const renderer = new AnnotationRenderer({\n * container: document.getElementById('container'),\n * canvasElement: document.getElementById('pdf-canvas')\n * });\n *\n * await renderer.loadPDF('/path/to/doc.pdf');\n * await renderer.setPage(1);\n * renderer.setAnnotations(annotationData);\n * renderer.setTime(3.5);\n */\nexport class AnnotationRenderer {\n /**\n * Create AnnotationRenderer instance\n *\n * @param {Object} config - Configuration object\n * @param {HTMLElement} config.container - DOM element for annotation canvas\n * @param {HTMLCanvasElement} config.canvasElement - Canvas element for PDF rendering\n * @param {string} [config.pdfUrl] - PDF URL to load immediately\n * @param {number} [config.initialPage=1] - Initial page number\n * @param {number} [config.initialScale=1.0] - Initial scale factor\n * @param {Array} [config.annotations=[]] - Initial annotation data\n * @param {Object} [config.strokeConfig] - StrokeRenderer configuration\n * @throws {Error} If config is invalid or required elements are missing\n */\n constructor(config) {\n if (!config || typeof config !== 'object') {\n throw new Error('AnnotationRenderer: config object is required');\n }\n\n if (!config.container || !(config.container instanceof HTMLElement)) {\n throw new Error('AnnotationRenderer: config.container must be a valid DOM element');\n }\n\n if (!config.canvasElement || !(config.canvasElement instanceof HTMLCanvasElement)) {\n throw new Error('AnnotationRenderer: config.canvasElement must be a valid canvas element');\n }\n\n this.config = config;\n this.canvasElement = config.canvasElement;\n this.container = config.container;\n\n // Initialize PDFRenderer\n this.pdfRenderer = new PDFRenderer();\n\n // Create stroke canvas and StrokeRenderer\n this.strokeCanvas = this._createStrokeCanvas();\n this.strokeRenderer = new StrokeRenderer(this.strokeCanvas, config.strokeConfig || {});\n\n // Initialize TimelineSync\n this.timelineSync = new TimelineSync();\n\n // State\n this.currentPage = config.initialPage || 1;\n this.currentScale = config.initialScale || 1.0;\n this.annotations = config.annotations || [];\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n\n // Wire up timeline to render\n this.timelineSync.subscribe((time) => {\n this.strokeRenderer.render(time);\n });\n\n // Auto-load PDF if provided\n if (config.pdfUrl) {\n this.loadPDF(config.pdfUrl).catch(err => {\n console.error('AnnotationRenderer: Failed to auto-load PDF:', err);\n });\n }\n }\n\n /**\n * Create stroke canvas overlay\n *\n * @private\n * @returns {HTMLCanvasElement} Stroke canvas element\n */\n _createStrokeCanvas() {\n const canvas = document.createElement('canvas');\n canvas.className = 'stroke-canvas';\n canvas.style.position = 'absolute';\n canvas.style.top = '0';\n canvas.style.left = '0';\n canvas.style.pointerEvents = 'none';\n canvas.style.zIndex = '10';\n this.container.appendChild(canvas);\n return canvas;\n }\n\n /**\n * Load PDF document from URL\n *\n * @param {string} url - URL or path to PDF file\n * @returns {Promise<Object>} Load result with success status and page count\n */\n async loadPDF(url) {\n try {\n if (!url || typeof url !== 'string') {\n return { success: false, error: 'Invalid PDF URL provided' };\n }\n\n const result = await this.pdfRenderer.loadDocument(url);\n\n if (result.success) {\n this.pdfUrl = url;\n this.pageCount = result.pageCount;\n return { success: true, pageCount: result.pageCount };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.loadPDF: Error loading PDF:', err);\n return { success: false, error: `Failed to load PDF: ${err.message}` };\n }\n }\n\n /**\n * Navigate to specific page and render it\n *\n * @param {number} pageNum - Page number (1-indexed)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setPage(pageNum) {\n try {\n if (typeof pageNum !== 'number' || pageNum < 1) {\n return { success: false, error: 'Invalid page number' };\n }\n\n if (this.pageCount > 0 && pageNum > this.pageCount) {\n return { success: false, error: `Page ${pageNum} exceeds document page count (${this.pageCount})` };\n }\n\n this.pdfRenderer.cancelRender();\n\n const result = await this.pdfRenderer.renderPage(\n pageNum,\n this.canvasElement,\n this.currentScale\n );\n\n if (result.success) {\n this.currentPage = pageNum;\n this.currentViewport = result.viewport;\n\n // Update StrokeRenderer viewport\n this.strokeRenderer.setViewport(result.viewport.width, result.viewport.height);\n\n // Re-set annotations for new page\n this.strokeRenderer.setAnnotations(this.annotations, pageNum);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n\n return { success: true, viewport: result.viewport };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.setPage: Error rendering page:', err);\n return { success: false, error: `Failed to render page: ${err.message}` };\n }\n }\n\n /**\n * Change zoom scale and re-render current page\n *\n * @param {number} scale - Scale factor (e.g., 1.0, 1.5, 2.0)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setScale(scale) {\n try {\n if (typeof scale !== 'number' || scale <= 0) {\n return { success: false, error: 'Invalid scale value (must be positive number)' };\n }\n\n this.currentScale = scale;\n return await this.setPage(this.currentPage);\n } catch (err) {\n console.error('AnnotationRenderer.setScale: Error changing scale:', err);\n return { success: false, error: `Failed to change scale: ${err.message}` };\n }\n }\n\n /**\n * Update annotation data for rendering\n *\n * @param {Array} annotations - Complete annotation array (all pages, all types)\n */\n setAnnotations(annotations) {\n if (!Array.isArray(annotations)) {\n console.warn('AnnotationRenderer.setAnnotations: annotations must be an array');\n annotations = [];\n }\n\n this.annotations = annotations;\n this.strokeRenderer.setAnnotations(annotations, this.currentPage);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Set pre-converted strokes directly\n *\n * Bypasses annotation conversion, useful for stroke commands from backend.\n *\n * @param {Array} strokes - Array of stroke command objects\n */\n setStrokes(strokes) {\n this.strokeRenderer.setStrokes(strokes);\n\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Update timeline position for animation\n *\n * @param {number} timestamp - Current timeline position in seconds\n */\n setTime(timestamp) {\n if (typeof timestamp !== 'number') {\n console.warn('AnnotationRenderer.setTime: timestamp must be a number');\n return;\n }\n\n this.timelineSync.setTime(timestamp);\n }\n\n /**\n * Start continuous timeline synchronization using requestAnimationFrame\n *\n * Polls the provided function at ~60fps for smooth animation.\n * Use this for audio/video synchronization instead of setTime().\n *\n * @param {Function} getTimeFunction - Function that returns current time in seconds\n * @example\n * const audio = document.getElementById('audio');\n * renderer.startContinuousSync(() => audio.currentTime);\n */\n startContinuousSync(getTimeFunction) {\n this.timelineSync.startContinuousSync(getTimeFunction);\n }\n\n /**\n * Stop continuous timeline synchronization\n *\n * Call this when audio/video stops or component unmounts.\n */\n stopContinuousSync() {\n this.timelineSync.stopContinuousSync();\n }\n\n /**\n * Check if continuous sync is currently active\n *\n * @returns {boolean} True if continuous sync is running\n */\n isContinuousSyncActive() {\n return this.timelineSync.isRunning;\n }\n\n /**\n * Update stroke rendering configuration at runtime\n *\n * Merges new config with existing and re-renders annotations.\n * Used for live preview of pen style changes.\n *\n * @param {Object} newConfig - New stroke configuration to merge\n */\n updateStrokeConfig(newConfig) {\n if (!newConfig || typeof newConfig !== 'object') {\n return;\n }\n\n // Merge new config into existing\n this.strokeRenderer.config = deepMerge(this.strokeRenderer.config, newConfig);\n\n // Re-convert annotations with new style and render\n this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Get current engine state snapshot\n *\n * @returns {Object} Current state\n */\n getState() {\n return {\n page: this.currentPage,\n scale: this.currentScale,\n annotations: this.annotations,\n pageCount: this.pageCount,\n time: this.timelineSync.getCurrentTime(),\n viewport: this.currentViewport,\n pdfUrl: this.pdfUrl\n };\n }\n\n /**\n * Clean up all resources and subsystems\n */\n destroy() {\n if (this.pdfRenderer) {\n this.pdfRenderer.destroy();\n }\n\n if (this.strokeRenderer) {\n this.strokeRenderer.destroy();\n }\n\n if (this.timelineSync) {\n this.timelineSync.destroy();\n }\n\n if (this.strokeCanvas && this.strokeCanvas.parentNode) {\n this.strokeCanvas.parentNode.removeChild(this.strokeCanvas);\n }\n\n this.pdfRenderer = null;\n this.strokeRenderer = null;\n this.timelineSync = null;\n this.strokeCanvas = null;\n this.config = null;\n this.canvasElement = null;\n this.container = null;\n this.annotations = [];\n this.currentPage = 0;\n this.currentScale = 1.0;\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n }\n}\n"],"names":["AnnotationRenderer","config","PDFRenderer","StrokeRenderer","TimelineSync","time","err","canvas","url","result","pageNum","currentTime","scale","annotations","strokes","timestamp","getTimeFunction","newConfig","deepMerge"],"mappings":"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"}
1
+ {"version":3,"file":"index2.js","sources":["../src/core/AnnotationRenderer.js"],"sourcesContent":["/**\n * AnnotationRenderer - Main facade for PDF annotation rendering engine\n *\n * Orchestrates PDFRenderer, StrokeRenderer, and TimelineSync subsystems.\n * Provides the primary public API for rendering PDFs with timeline-synchronized\n * annotations. Framework-agnostic core that can be wrapped by React/Vue adapters.\n *\n * @module core/AnnotationRenderer\n */\n\nimport { PDFRenderer } from './PDFRenderer.js';\nimport { TimelineSync } from './TimelineSync.js';\nimport { StrokeRenderer } from '../renderer/StrokeRenderer.js';\n\n/**\n * AnnotationRenderer class\n *\n * Main engine that coordinates PDF rendering, stroke-based annotation rendering,\n * and timeline synchronization. Provides simple imperative API for consumers.\n *\n * @class\n * @example\n * const renderer = new AnnotationRenderer({\n * container: document.getElementById('container'),\n * canvasElement: document.getElementById('pdf-canvas')\n * });\n *\n * await renderer.loadPDF('/path/to/doc.pdf');\n * await renderer.setPage(1);\n * renderer.setAnnotations(annotationData);\n * renderer.setTime(3.5);\n */\nexport class AnnotationRenderer {\n /**\n * Create AnnotationRenderer instance\n *\n * @param {Object} config - Configuration object\n * @param {HTMLElement} config.container - DOM element for annotation canvas\n * @param {HTMLCanvasElement} config.canvasElement - Canvas element for PDF rendering\n * @param {string} [config.pdfUrl] - PDF URL to load immediately\n * @param {number} [config.initialPage=1] - Initial page number\n * @param {number} [config.initialScale=1.0] - Initial scale factor\n * @param {Array} [config.annotations=[]] - Initial annotation data\n * @param {Object} [config.strokeConfig] - StrokeRenderer configuration\n * @throws {Error} If config is invalid or required elements are missing\n */\n constructor(config) {\n if (!config || typeof config !== 'object') {\n throw new Error('AnnotationRenderer: config object is required');\n }\n\n if (!config.container || !(config.container instanceof HTMLElement)) {\n throw new Error('AnnotationRenderer: config.container must be a valid DOM element');\n }\n\n if (!config.canvasElement || !(config.canvasElement instanceof HTMLCanvasElement)) {\n throw new Error('AnnotationRenderer: config.canvasElement must be a valid canvas element');\n }\n\n this.config = config;\n this.canvasElement = config.canvasElement;\n this.container = config.container;\n\n // Initialize PDFRenderer\n this.pdfRenderer = new PDFRenderer();\n\n // Create stroke canvas and StrokeRenderer\n this.strokeCanvas = this._createStrokeCanvas();\n this.strokeRenderer = new StrokeRenderer(this.strokeCanvas, config.strokeConfig || {});\n\n // Initialize TimelineSync\n this.timelineSync = new TimelineSync();\n\n // State\n this.currentPage = config.initialPage || 1;\n this.currentScale = config.initialScale || 1.0;\n this.annotations = config.annotations || [];\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n\n // Wire up timeline to render\n this.timelineSync.subscribe((time) => {\n this.strokeRenderer.render(time);\n });\n\n // Auto-load PDF if provided\n if (config.pdfUrl) {\n this.loadPDF(config.pdfUrl).catch(err => {\n console.error('AnnotationRenderer: Failed to auto-load PDF:', err);\n });\n }\n }\n\n /**\n * Create stroke canvas overlay\n *\n * @private\n * @returns {HTMLCanvasElement} Stroke canvas element\n */\n _createStrokeCanvas() {\n const canvas = document.createElement('canvas');\n canvas.className = 'stroke-canvas';\n canvas.style.position = 'absolute';\n canvas.style.top = '0';\n canvas.style.left = '0';\n canvas.style.pointerEvents = 'none';\n canvas.style.zIndex = '10';\n this.container.appendChild(canvas);\n return canvas;\n }\n\n /**\n * Load PDF document from URL\n *\n * @param {string} url - URL or path to PDF file\n * @returns {Promise<Object>} Load result with success status and page count\n */\n async loadPDF(url) {\n try {\n if (!url || typeof url !== 'string') {\n return { success: false, error: 'Invalid PDF URL provided' };\n }\n\n const result = await this.pdfRenderer.loadDocument(url);\n\n if (result.success) {\n this.pdfUrl = url;\n this.pageCount = result.pageCount;\n return { success: true, pageCount: result.pageCount };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.loadPDF: Error loading PDF:', err);\n return { success: false, error: `Failed to load PDF: ${err.message}` };\n }\n }\n\n /**\n * Navigate to specific page and render it\n *\n * @param {number} pageNum - Page number (1-indexed)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setPage(pageNum) {\n try {\n if (typeof pageNum !== 'number' || pageNum < 1) {\n return { success: false, error: 'Invalid page number' };\n }\n\n if (this.pageCount > 0 && pageNum > this.pageCount) {\n return { success: false, error: `Page ${pageNum} exceeds document page count (${this.pageCount})` };\n }\n\n this.pdfRenderer.cancelRender();\n\n const result = await this.pdfRenderer.renderPage(\n pageNum,\n this.canvasElement,\n this.currentScale\n );\n\n if (result.success) {\n this.currentPage = pageNum;\n this.currentViewport = result.viewport;\n\n // Update StrokeRenderer viewport\n this.strokeRenderer.setViewport(result.viewport.width, result.viewport.height);\n\n // Re-set annotations for new page\n this.strokeRenderer.setAnnotations(this.annotations, pageNum);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n\n return { success: true, viewport: result.viewport };\n }\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.setPage: Error rendering page:', err);\n return { success: false, error: `Failed to render page: ${err.message}` };\n }\n }\n\n /**\n * Change zoom scale and re-render current page\n *\n * @param {number} scale - Scale factor (e.g., 1.0, 1.5, 2.0)\n * @returns {Promise<Object>} Render result with viewport information\n */\n async setScale(scale) {\n try {\n if (typeof scale !== 'number' || scale <= 0) {\n return { success: false, error: 'Invalid scale value (must be positive number)' };\n }\n\n this.currentScale = scale;\n return await this.setPage(this.currentPage);\n } catch (err) {\n console.error('AnnotationRenderer.setScale: Error changing scale:', err);\n return { success: false, error: `Failed to change scale: ${err.message}` };\n }\n }\n\n /**\n * Update annotation data for rendering\n *\n * @param {Array} annotations - Complete annotation array (all pages, all types)\n */\n setAnnotations(annotations) {\n if (!Array.isArray(annotations)) {\n console.warn('AnnotationRenderer.setAnnotations: annotations must be an array');\n annotations = [];\n }\n\n this.annotations = annotations;\n this.strokeRenderer.setAnnotations(annotations, this.currentPage);\n\n // Render at current time\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Set pre-converted strokes directly\n *\n * Bypasses annotation conversion, useful for stroke commands from backend.\n *\n * @param {Array} strokes - Array of stroke command objects\n */\n setStrokes(strokes) {\n this.strokeRenderer.setStrokes(strokes);\n\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Update timeline position for animation\n *\n * @param {number} timestamp - Current timeline position in seconds\n */\n setTime(timestamp) {\n if (typeof timestamp !== 'number') {\n console.warn('AnnotationRenderer.setTime: timestamp must be a number');\n return;\n }\n\n this.timelineSync.setTime(timestamp);\n }\n\n /**\n * Start continuous timeline synchronization using requestAnimationFrame\n *\n * Polls the provided function at ~60fps for smooth animation.\n * Use this for audio/video synchronization instead of setTime().\n *\n * @param {Function} getTimeFunction - Function that returns current time in seconds\n * @example\n * const audio = document.getElementById('audio');\n * renderer.startContinuousSync(() => audio.currentTime);\n */\n startContinuousSync(getTimeFunction) {\n this.timelineSync.startContinuousSync(getTimeFunction);\n }\n\n /**\n * Stop continuous timeline synchronization\n *\n * Call this when audio/video stops or component unmounts.\n */\n stopContinuousSync() {\n this.timelineSync.stopContinuousSync();\n }\n\n /**\n * Check if continuous sync is currently active\n *\n * @returns {boolean} True if continuous sync is running\n */\n isContinuousSyncActive() {\n return this.timelineSync.isRunning;\n }\n\n /**\n * Update stroke rendering configuration at runtime\n *\n * Updates config via setConfig and re-renders annotations.\n * Used for live preview of pen style changes.\n *\n * @param {Object} newConfig - New stroke configuration\n */\n updateStrokeConfig(newConfig) {\n if (!newConfig || typeof newConfig !== 'object') {\n return;\n }\n\n // Update config via setConfig\n this.strokeRenderer.setConfig(newConfig);\n\n // Re-convert annotations with new style and render\n this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);\n const currentTime = this.timelineSync.getCurrentTime();\n this.strokeRenderer.render(currentTime);\n }\n\n /**\n * Get current engine state snapshot\n *\n * @returns {Object} Current state\n */\n getState() {\n return {\n page: this.currentPage,\n scale: this.currentScale,\n annotations: this.annotations,\n pageCount: this.pageCount,\n time: this.timelineSync.getCurrentTime(),\n viewport: this.currentViewport,\n pdfUrl: this.pdfUrl\n };\n }\n\n /**\n * Clean up all resources and subsystems\n */\n destroy() {\n if (this.pdfRenderer) {\n this.pdfRenderer.destroy();\n }\n\n if (this.strokeRenderer) {\n this.strokeRenderer.destroy();\n }\n\n if (this.timelineSync) {\n this.timelineSync.destroy();\n }\n\n if (this.strokeCanvas && this.strokeCanvas.parentNode) {\n this.strokeCanvas.parentNode.removeChild(this.strokeCanvas);\n }\n\n this.pdfRenderer = null;\n this.strokeRenderer = null;\n this.timelineSync = null;\n this.strokeCanvas = null;\n this.config = null;\n this.canvasElement = null;\n this.container = null;\n this.annotations = [];\n this.currentPage = 0;\n this.currentScale = 1.0;\n this.pageCount = 0;\n this.currentViewport = null;\n this.pdfUrl = null;\n }\n}\n"],"names":["AnnotationRenderer","config","PDFRenderer","StrokeRenderer","TimelineSync","time","err","canvas","url","result","pageNum","currentTime","scale","annotations","strokes","timestamp","getTimeFunction","newConfig"],"mappings":"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"}
package/dist/index21.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e={name:"default",highlight:{color:"rgba(255, 255, 0, 0.3)",width:24},handText:{color:"rgba(220, 20, 60, 1.0)",width:2},ink:{color:"rgba(31, 41, 55, 1.0)",width:3}},r={name:"blue",highlight:{color:"rgba(100, 149, 237, 0.35)",width:24},handText:{color:"rgba(30, 64, 175, 1.0)",width:2},ink:{color:"rgba(30, 64, 175, 1.0)",width:3}},o={name:"minimal",highlight:{color:"rgba(156, 163, 175, 0.25)",width:20},handText:{color:"rgba(75, 85, 99, 1.0)",width:1.5},ink:{color:"rgba(75, 85, 99, 1.0)",width:2}},t={default:e,blue:r,minimal:o};function a(i){return t[i]||t.default}function l(){return Object.keys(t)}exports.BLUE_PRESET=r;exports.DEFAULT_PRESET=e;exports.MINIMAL_PRESET=o;exports.default=t;exports.getPreset=a;exports.getPresetNames=l;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t={highlight:{color:"rgba(255, 255, 0, 0.3)",width:24},text:{color:"rgba(220, 20, 60, 1.0)",width:2},underline:{color:"rgba(0, 80, 255, 1.0)",width:2},arrow:{color:"rgba(220, 30, 30, 1.0)",width:2},circle:{color:"rgba(255, 140, 0, 1.0)",width:3}},e={highlight:{color:"rgba(100, 149, 237, 0.35)",width:24},text:{color:"rgba(30, 64, 175, 1.0)",width:2},underline:{color:"rgba(30, 64, 175, 1.0)",width:2},arrow:{color:"rgba(30, 64, 175, 1.0)",width:2},circle:{color:"rgba(30, 64, 175, 1.0)",width:3}},o={highlight:{color:"rgba(156, 163, 175, 0.25)",width:20},text:{color:"rgba(75, 85, 99, 1.0)",width:1.5},underline:{color:"rgba(75, 85, 99, 1.0)",width:1.5},arrow:{color:"rgba(75, 85, 99, 1.0)",width:1.5},circle:{color:"rgba(75, 85, 99, 1.0)",width:2}},r={default:t,blue:e,minimal:o};function l(i){return r[i]||r.default}function c(){return Object.keys(r)}exports.BLUE_PRESET=e;exports.DEFAULT_PRESET=t;exports.MINIMAL_PRESET=o;exports.default=r;exports.getPreset=l;exports.getPresetNames=c;
2
2
  //# sourceMappingURL=index21.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index21.cjs","sources":["../src/pen/presets.js"],"sourcesContent":["/**\n * Client-side style presets for Digital Pen\n *\n * These presets mirror the backend presets and are used for\n * client-side preview or when backend presets aren't available.\n */\n\n/**\n * Default preset - Yellow highlights, crimson handwriting\n */\nexport const DEFAULT_PRESET = {\n name: 'default',\n highlight: {\n color: 'rgba(255, 255, 0, 0.3)',\n width: 24\n },\n handText: {\n color: 'rgba(220, 20, 60, 1.0)',\n width: 2\n },\n ink: {\n color: 'rgba(31, 41, 55, 1.0)',\n width: 3\n }\n};\n\n/**\n * Blue preset - Blue highlights and handwriting\n */\nexport const BLUE_PRESET = {\n name: 'blue',\n highlight: {\n color: 'rgba(100, 149, 237, 0.35)',\n width: 24\n },\n handText: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n ink: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 3\n }\n};\n\n/**\n * Minimal preset - Subtle gray, less visible effects\n */\nexport const MINIMAL_PRESET = {\n name: 'minimal',\n highlight: {\n color: 'rgba(156, 163, 175, 0.25)',\n width: 20\n },\n handText: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n ink: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 2\n }\n};\n\n/**\n * Preset registry\n */\nconst PRESETS = {\n default: DEFAULT_PRESET,\n blue: BLUE_PRESET,\n minimal: MINIMAL_PRESET\n};\n\n/**\n * Get a preset by name\n *\n * @param {string} name - Preset name\n * @returns {Object} Preset configuration\n */\nexport function getPreset(name) {\n return PRESETS[name] || PRESETS.default;\n}\n\n/**\n * Get all available preset names\n *\n * @returns {string[]} Array of preset names\n */\nexport function getPresetNames() {\n return Object.keys(PRESETS);\n}\n\nexport default PRESETS;\n"],"names":["DEFAULT_PRESET","BLUE_PRESET","MINIMAL_PRESET","PRESETS","getPreset","name","getPresetNames"],"mappings":"4GAUY,MAACA,EAAiB,CAC5B,KAAM,UACN,UAAW,CACT,MAAO,yBACP,MAAO,EACX,EACE,SAAU,CACR,MAAO,yBACP,MAAO,CACX,EACE,IAAK,CACH,MAAO,wBACP,MAAO,CACX,CACA,EAKaC,EAAc,CACzB,KAAM,OACN,UAAW,CACT,MAAO,4BACP,MAAO,EACX,EACE,SAAU,CACR,MAAO,yBACP,MAAO,CACX,EACE,IAAK,CACH,MAAO,yBACP,MAAO,CACX,CACA,EAKaC,EAAiB,CAC5B,KAAM,UACN,UAAW,CACT,MAAO,4BACP,MAAO,EACX,EACE,SAAU,CACR,MAAO,wBACP,MAAO,GACX,EACE,IAAK,CACH,MAAO,wBACP,MAAO,CACX,CACA,EAKMC,EAAU,CACd,QAASH,EACT,KAAMC,EACN,QAASC,CACX,EAQO,SAASE,EAAUC,EAAM,CAC9B,OAAOF,EAAQE,CAAI,GAAKF,EAAQ,OAClC,CAOO,SAASG,GAAiB,CAC/B,OAAO,OAAO,KAAKH,CAAO,CAC5B"}
1
+ {"version":3,"file":"index21.cjs","sources":["../src/pen/presets.js"],"sourcesContent":["/**\n * Client-side style presets for Digital Pen\n *\n * These presets use the same format as StrokeRenderer.setConfig().\n * Keys match annotation types: highlight, text, underline, arrow, circle.\n */\n\n/**\n * Default preset - Yellow highlights, crimson text\n */\nexport const DEFAULT_PRESET = {\n highlight: {\n color: 'rgba(255, 255, 0, 0.3)',\n width: 24\n },\n text: {\n color: 'rgba(220, 20, 60, 1.0)',\n width: 2\n },\n underline: {\n color: 'rgba(0, 80, 255, 1.0)',\n width: 2\n },\n arrow: {\n color: 'rgba(220, 30, 30, 1.0)',\n width: 2\n },\n circle: {\n color: 'rgba(255, 140, 0, 1.0)',\n width: 3\n }\n};\n\n/**\n * Blue preset - Blue theme\n */\nexport const BLUE_PRESET = {\n highlight: {\n color: 'rgba(100, 149, 237, 0.35)',\n width: 24\n },\n text: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n underline: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n arrow: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n circle: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 3\n }\n};\n\n/**\n * Minimal preset - Subtle gray\n */\nexport const MINIMAL_PRESET = {\n highlight: {\n color: 'rgba(156, 163, 175, 0.25)',\n width: 20\n },\n text: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n underline: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n arrow: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n circle: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 2\n }\n};\n\n/**\n * Preset registry\n */\nconst PRESETS = {\n default: DEFAULT_PRESET,\n blue: BLUE_PRESET,\n minimal: MINIMAL_PRESET\n};\n\n/**\n * Get a preset by name\n *\n * @param {string} name - Preset name\n * @returns {Object} Preset configuration\n */\nexport function getPreset(name) {\n return PRESETS[name] || PRESETS.default;\n}\n\n/**\n * Get all available preset names\n *\n * @returns {string[]} Array of preset names\n */\nexport function getPresetNames() {\n return Object.keys(PRESETS);\n}\n\nexport default PRESETS;\n"],"names":["DEFAULT_PRESET","BLUE_PRESET","MINIMAL_PRESET","PRESETS","getPreset","name","getPresetNames"],"mappings":"4GAUY,MAACA,EAAiB,CAC5B,UAAW,CACT,MAAO,yBACP,MAAO,EACX,EACE,KAAM,CACJ,MAAO,yBACP,MAAO,CACX,EACE,UAAW,CACT,MAAO,wBACP,MAAO,CACX,EACE,MAAO,CACL,MAAO,yBACP,MAAO,CACX,EACE,OAAQ,CACN,MAAO,yBACP,MAAO,CACX,CACA,EAKaC,EAAc,CACzB,UAAW,CACT,MAAO,4BACP,MAAO,EACX,EACE,KAAM,CACJ,MAAO,yBACP,MAAO,CACX,EACE,UAAW,CACT,MAAO,yBACP,MAAO,CACX,EACE,MAAO,CACL,MAAO,yBACP,MAAO,CACX,EACE,OAAQ,CACN,MAAO,yBACP,MAAO,CACX,CACA,EAKaC,EAAiB,CAC5B,UAAW,CACT,MAAO,4BACP,MAAO,EACX,EACE,KAAM,CACJ,MAAO,wBACP,MAAO,GACX,EACE,UAAW,CACT,MAAO,wBACP,MAAO,GACX,EACE,MAAO,CACL,MAAO,wBACP,MAAO,GACX,EACE,OAAQ,CACN,MAAO,wBACP,MAAO,CACX,CACA,EAKMC,EAAU,CACd,QAASH,EACT,KAAMC,EACN,QAASC,CACX,EAQO,SAASE,EAAUC,EAAM,CAC9B,OAAOF,EAAQE,CAAI,GAAKF,EAAQ,OAClC,CAOO,SAASG,GAAiB,CAC/B,OAAO,OAAO,KAAKH,CAAO,CAC5B"}
package/dist/index21.js CHANGED
@@ -1,62 +1,83 @@
1
- const r = {
2
- name: "default",
1
+ const o = {
3
2
  highlight: {
4
3
  color: "rgba(255, 255, 0, 0.3)",
5
4
  width: 24
6
5
  },
7
- handText: {
6
+ text: {
8
7
  color: "rgba(220, 20, 60, 1.0)",
9
8
  width: 2
10
9
  },
11
- ink: {
12
- color: "rgba(31, 41, 55, 1.0)",
10
+ underline: {
11
+ color: "rgba(0, 80, 255, 1.0)",
12
+ width: 2
13
+ },
14
+ arrow: {
15
+ color: "rgba(220, 30, 30, 1.0)",
16
+ width: 2
17
+ },
18
+ circle: {
19
+ color: "rgba(255, 140, 0, 1.0)",
13
20
  width: 3
14
21
  }
15
- }, e = {
16
- name: "blue",
22
+ }, i = {
17
23
  highlight: {
18
24
  color: "rgba(100, 149, 237, 0.35)",
19
25
  width: 24
20
26
  },
21
- handText: {
27
+ text: {
28
+ color: "rgba(30, 64, 175, 1.0)",
29
+ width: 2
30
+ },
31
+ underline: {
32
+ color: "rgba(30, 64, 175, 1.0)",
33
+ width: 2
34
+ },
35
+ arrow: {
22
36
  color: "rgba(30, 64, 175, 1.0)",
23
37
  width: 2
24
38
  },
25
- ink: {
39
+ circle: {
26
40
  color: "rgba(30, 64, 175, 1.0)",
27
41
  width: 3
28
42
  }
29
- }, i = {
30
- name: "minimal",
43
+ }, l = {
31
44
  highlight: {
32
45
  color: "rgba(156, 163, 175, 0.25)",
33
46
  width: 20
34
47
  },
35
- handText: {
48
+ text: {
49
+ color: "rgba(75, 85, 99, 1.0)",
50
+ width: 1.5
51
+ },
52
+ underline: {
53
+ color: "rgba(75, 85, 99, 1.0)",
54
+ width: 1.5
55
+ },
56
+ arrow: {
36
57
  color: "rgba(75, 85, 99, 1.0)",
37
58
  width: 1.5
38
59
  },
39
- ink: {
60
+ circle: {
40
61
  color: "rgba(75, 85, 99, 1.0)",
41
62
  width: 2
42
63
  }
43
- }, t = {
44
- default: r,
45
- blue: e,
46
- minimal: i
64
+ }, r = {
65
+ default: o,
66
+ blue: i,
67
+ minimal: l
47
68
  };
48
- function a(o) {
49
- return t[o] || t.default;
69
+ function c(t) {
70
+ return r[t] || r.default;
50
71
  }
51
- function h() {
52
- return Object.keys(t);
72
+ function e() {
73
+ return Object.keys(r);
53
74
  }
54
75
  export {
55
- e as BLUE_PRESET,
56
- r as DEFAULT_PRESET,
57
- i as MINIMAL_PRESET,
58
- t as default,
59
- a as getPreset,
60
- h as getPresetNames
76
+ i as BLUE_PRESET,
77
+ o as DEFAULT_PRESET,
78
+ l as MINIMAL_PRESET,
79
+ r as default,
80
+ c as getPreset,
81
+ e as getPresetNames
61
82
  };
62
83
  //# sourceMappingURL=index21.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index21.js","sources":["../src/pen/presets.js"],"sourcesContent":["/**\n * Client-side style presets for Digital Pen\n *\n * These presets mirror the backend presets and are used for\n * client-side preview or when backend presets aren't available.\n */\n\n/**\n * Default preset - Yellow highlights, crimson handwriting\n */\nexport const DEFAULT_PRESET = {\n name: 'default',\n highlight: {\n color: 'rgba(255, 255, 0, 0.3)',\n width: 24\n },\n handText: {\n color: 'rgba(220, 20, 60, 1.0)',\n width: 2\n },\n ink: {\n color: 'rgba(31, 41, 55, 1.0)',\n width: 3\n }\n};\n\n/**\n * Blue preset - Blue highlights and handwriting\n */\nexport const BLUE_PRESET = {\n name: 'blue',\n highlight: {\n color: 'rgba(100, 149, 237, 0.35)',\n width: 24\n },\n handText: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n ink: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 3\n }\n};\n\n/**\n * Minimal preset - Subtle gray, less visible effects\n */\nexport const MINIMAL_PRESET = {\n name: 'minimal',\n highlight: {\n color: 'rgba(156, 163, 175, 0.25)',\n width: 20\n },\n handText: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n ink: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 2\n }\n};\n\n/**\n * Preset registry\n */\nconst PRESETS = {\n default: DEFAULT_PRESET,\n blue: BLUE_PRESET,\n minimal: MINIMAL_PRESET\n};\n\n/**\n * Get a preset by name\n *\n * @param {string} name - Preset name\n * @returns {Object} Preset configuration\n */\nexport function getPreset(name) {\n return PRESETS[name] || PRESETS.default;\n}\n\n/**\n * Get all available preset names\n *\n * @returns {string[]} Array of preset names\n */\nexport function getPresetNames() {\n return Object.keys(PRESETS);\n}\n\nexport default PRESETS;\n"],"names":["DEFAULT_PRESET","BLUE_PRESET","MINIMAL_PRESET","PRESETS","getPreset","name","getPresetNames"],"mappings":"AAUY,MAACA,IAAiB;AAAA,EAC5B,MAAM;AAAA,EACN,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,UAAU;AAAA,IACR,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,KAAK;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AACA,GAKaC,IAAc;AAAA,EACzB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,UAAU;AAAA,IACR,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,KAAK;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AACA,GAKaC,IAAiB;AAAA,EAC5B,MAAM;AAAA,EACN,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,UAAU;AAAA,IACR,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,KAAK;AAAA,IACH,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AACA,GAKMC,IAAU;AAAA,EACd,SAASH;AAAA,EACT,MAAMC;AAAA,EACN,SAASC;AACX;AAQO,SAASE,EAAUC,GAAM;AAC9B,SAAOF,EAAQE,CAAI,KAAKF,EAAQ;AAClC;AAOO,SAASG,IAAiB;AAC/B,SAAO,OAAO,KAAKH,CAAO;AAC5B;"}
1
+ {"version":3,"file":"index21.js","sources":["../src/pen/presets.js"],"sourcesContent":["/**\n * Client-side style presets for Digital Pen\n *\n * These presets use the same format as StrokeRenderer.setConfig().\n * Keys match annotation types: highlight, text, underline, arrow, circle.\n */\n\n/**\n * Default preset - Yellow highlights, crimson text\n */\nexport const DEFAULT_PRESET = {\n highlight: {\n color: 'rgba(255, 255, 0, 0.3)',\n width: 24\n },\n text: {\n color: 'rgba(220, 20, 60, 1.0)',\n width: 2\n },\n underline: {\n color: 'rgba(0, 80, 255, 1.0)',\n width: 2\n },\n arrow: {\n color: 'rgba(220, 30, 30, 1.0)',\n width: 2\n },\n circle: {\n color: 'rgba(255, 140, 0, 1.0)',\n width: 3\n }\n};\n\n/**\n * Blue preset - Blue theme\n */\nexport const BLUE_PRESET = {\n highlight: {\n color: 'rgba(100, 149, 237, 0.35)',\n width: 24\n },\n text: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n underline: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n arrow: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 2\n },\n circle: {\n color: 'rgba(30, 64, 175, 1.0)',\n width: 3\n }\n};\n\n/**\n * Minimal preset - Subtle gray\n */\nexport const MINIMAL_PRESET = {\n highlight: {\n color: 'rgba(156, 163, 175, 0.25)',\n width: 20\n },\n text: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n underline: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n arrow: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 1.5\n },\n circle: {\n color: 'rgba(75, 85, 99, 1.0)',\n width: 2\n }\n};\n\n/**\n * Preset registry\n */\nconst PRESETS = {\n default: DEFAULT_PRESET,\n blue: BLUE_PRESET,\n minimal: MINIMAL_PRESET\n};\n\n/**\n * Get a preset by name\n *\n * @param {string} name - Preset name\n * @returns {Object} Preset configuration\n */\nexport function getPreset(name) {\n return PRESETS[name] || PRESETS.default;\n}\n\n/**\n * Get all available preset names\n *\n * @returns {string[]} Array of preset names\n */\nexport function getPresetNames() {\n return Object.keys(PRESETS);\n}\n\nexport default PRESETS;\n"],"names":["DEFAULT_PRESET","BLUE_PRESET","MINIMAL_PRESET","PRESETS","getPreset","name","getPresetNames"],"mappings":"AAUY,MAACA,IAAiB;AAAA,EAC5B,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,OAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AACA,GAKaC,IAAc;AAAA,EACzB,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,OAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AACA,GAKaC,IAAiB;AAAA,EAC5B,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,WAAW;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,OAAO;AAAA,IACL,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AAAA,EACE,QAAQ;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,EACX;AACA,GAKMC,IAAU;AAAA,EACd,SAASH;AAAA,EACT,MAAMC;AAAA,EACN,SAASC;AACX;AAQO,SAASE,EAAUC,GAAM;AAC9B,SAAOF,EAAQE,CAAI,KAAKF,EAAQ;AAClC;AAOO,SAASG,IAAiB;AAC/B,SAAO,OAAO,KAAKH,CAAO;AAC5B;"}
package/dist/index24.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./index29.cjs");function h(e){if(!e.quads||!Array.isArray(e.quads)||e.quads.length===0)throw new Error("Highlight annotation requires at least one quad");if(!e.page||typeof e.page!="number"||e.page<1)throw new Error("Highlight annotation requires a valid page number (>= 1)");if(!e.sentence_ref||typeof e.sentence_ref!="string")throw new Error("Highlight annotation requires a sentence_ref for timing");e.quads.forEach((r,o)=>{if(typeof r!="object"||r===null||Array.isArray(r))throw new Error(`Quad at index ${o} must be an object with {x, y, w, h} properties`);const i=["x","y","w","h"];for(const t of i){if(typeof r[t]!="number")throw new Error(`Quad at index ${o} is missing required property '${t}' or it's not a number`);if(r[t]<0||r[t]>1)throw new Error(`Quad property '${t}' at index ${o} must be between 0 and 1 (got ${r[t]})`)}});const n=e.color||"rgba(255, 255, 0, 0.3)";return{id:a.generateId("highlight"),type:"highlight",mode:"quads",page:e.page,quads:e.quads,style:{color:n},sentence_ref:e.sentence_ref}}exports.createHighlight=h;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./index30.cjs");function h(e){if(!e.quads||!Array.isArray(e.quads)||e.quads.length===0)throw new Error("Highlight annotation requires at least one quad");if(!e.page||typeof e.page!="number"||e.page<1)throw new Error("Highlight annotation requires a valid page number (>= 1)");if(!e.sentence_ref||typeof e.sentence_ref!="string")throw new Error("Highlight annotation requires a sentence_ref for timing");e.quads.forEach((r,o)=>{if(typeof r!="object"||r===null||Array.isArray(r))throw new Error(`Quad at index ${o} must be an object with {x, y, w, h} properties`);const i=["x","y","w","h"];for(const t of i){if(typeof r[t]!="number")throw new Error(`Quad at index ${o} is missing required property '${t}' or it's not a number`);if(r[t]<0||r[t]>1)throw new Error(`Quad property '${t}' at index ${o} must be between 0 and 1 (got ${r[t]})`)}});const n=e.color||"rgba(255, 255, 0, 0.3)";return{id:a.generateId("highlight"),type:"highlight",mode:"quads",page:e.page,quads:e.quads,style:{color:n},sentence_ref:e.sentence_ref}}exports.createHighlight=h;
2
2
  //# sourceMappingURL=index24.cjs.map
package/dist/index24.js CHANGED
@@ -1,4 +1,4 @@
1
- import { generateId as h } from "./index29.js";
1
+ import { generateId as h } from "./index30.js";
2
2
  function p(e) {
3
3
  if (!e.quads || !Array.isArray(e.quads) || e.quads.length === 0)
4
4
  throw new Error("Highlight annotation requires at least one quad");
package/dist/index25.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./index29.cjs");function r(e){if(!e.content||typeof e.content!="string"||e.content.trim().length===0)throw new Error("Text annotation requires non-empty content");if(typeof e.x!="number"||e.x<0||e.x>1)throw new Error("Text annotation x position must be between 0 and 1");if(typeof e.y!="number"||e.y<0||e.y>1)throw new Error("Text annotation y position must be between 0 and 1");if(typeof e.w!="number"||e.w<0||e.w>1)throw new Error("Text annotation width (w) must be between 0 and 1");if(typeof e.h!="number"||e.h<0||e.h>1)throw new Error("Text annotation height (h) must be between 0 and 1");if(!e.page||typeof e.page!="number"||e.page<1)throw new Error("Text annotation requires a valid page number (>= 1)");if(!e.sentence_ref||typeof e.sentence_ref!="string")throw new Error("Text annotation requires a sentence_ref for timing");const t=e.textColor||"#1f2937",n=e.bgColor||"transparent";return{id:o.generateId("text"),type:"text",page:e.page,content:e.content.trim(),x:e.x,y:e.y,w:e.w,h:e.h,style:{bg:n,color:t},sentence_ref:e.sentence_ref}}exports.createText=r;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./index30.cjs");function r(e){if(!e.content||typeof e.content!="string"||e.content.trim().length===0)throw new Error("Text annotation requires non-empty content");if(typeof e.x!="number"||e.x<0||e.x>1)throw new Error("Text annotation x position must be between 0 and 1");if(typeof e.y!="number"||e.y<0||e.y>1)throw new Error("Text annotation y position must be between 0 and 1");if(typeof e.w!="number"||e.w<0||e.w>1)throw new Error("Text annotation width (w) must be between 0 and 1");if(typeof e.h!="number"||e.h<0||e.h>1)throw new Error("Text annotation height (h) must be between 0 and 1");if(!e.page||typeof e.page!="number"||e.page<1)throw new Error("Text annotation requires a valid page number (>= 1)");if(!e.sentence_ref||typeof e.sentence_ref!="string")throw new Error("Text annotation requires a sentence_ref for timing");const t=e.textColor||"#1f2937",n=e.bgColor||"transparent";return{id:o.generateId("text"),type:"text",page:e.page,content:e.content.trim(),x:e.x,y:e.y,w:e.w,h:e.h,style:{bg:n,color:t},sentence_ref:e.sentence_ref}}exports.createText=r;
2
2
  //# sourceMappingURL=index25.cjs.map
package/dist/index25.js CHANGED
@@ -1,4 +1,4 @@
1
- import { generateId as o } from "./index29.js";
1
+ import { generateId as o } from "./index30.js";
2
2
  function i(e) {
3
3
  if (!e.content || typeof e.content != "string" || e.content.trim().length === 0)
4
4
  throw new Error("Text annotation requires non-empty content");
package/dist/index29.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function o(t="anno"){const n=Date.now().toString(36),e=Math.random().toString(36).substring(2,9);return`${t}-${n}${e}`}exports.generateId=o;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("./index31.cjs"),l=v.default.generator();function M(n,t,r,o,e){const s=1-e;return[s**3*n[0]+3*s**2*e*t[0]+3*s*e**2*r[0]+e**3*o[0],s**3*n[1]+3*s**2*e*t[1]+3*s*e**2*r[1]+e**3*o[1]]}function x(n){const t=[];let r=[0,0];for(const{op:o,data:e}of n)switch(o){case"move":r=[e[0],e[1]],t.push([...r]);break;case"lineTo":r=[e[0],e[1]],t.push([...r]);break;case"bcurveTo":{const[s,h,f,d,a,c]=e,g=r,b=[s,h],m=[f,d],S=[a,c];for(let u=.25;u<=1;u+=.25)t.push(M(g,b,m,S,u));r=[a,c];break}}return t}function i(n){const t=[];for(const r of n.sets)r.type==="path"&&t.push(...x(r.ops));return t}function k(n){let t=0;for(let r=0;r<n.length;r++)t=(t<<5)-t+n.charCodeAt(r),t|=0;return Math.abs(t)}function w(n,t,r,o,e={}){const s=l.line(n,t,r,o,{roughness:e.roughness??1,bowing:e.bowing??1,seed:e.seed??Math.floor(Math.random()*2147483648),curveFitting:e.curveFitting??.95,curveStepCount:e.curveStepCount??9,maxRandomnessOffset:e.maxRandomnessOffset??2,disableMultiStroke:e.disableMultiStroke??!1,...e});return i(s)}function y(n,t,r,o,e={}){const s=l.ellipse(n,t,r,o,{roughness:e.roughness??1,bowing:e.bowing??1,seed:e.seed??Math.floor(Math.random()*2147483648),curveFitting:e.curveFitting??.95,curveStepCount:e.curveStepCount??9,maxRandomnessOffset:e.maxRandomnessOffset??2,disableMultiStroke:e.disableMultiStroke??!1,...e});return i(s)}exports.hashSeed=k;exports.roughEllipse=y;exports.roughLine=w;
2
2
  //# sourceMappingURL=index29.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index29.cjs","sources":["../src/utils/idGenerator.js"],"sourcesContent":["/**\n * ID Generator Utility\n *\n * Generates unique IDs for annotations.\n *\n * @module utils/idGenerator\n */\n\n/**\n * Generate a unique ID for an annotation\n *\n * @param {string} [prefix='anno'] - ID prefix (e.g., 'highlight', 'text', 'ink')\n * @returns {string} Unique annotation ID\n * @example\n * ```javascript\n * const id = generateId('highlight');\n * // Returns: \"highlight-1234567890abc\"\n * ```\n */\nexport function generateId(prefix = 'anno') {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 9);\n return `${prefix}-${timestamp}${random}`;\n}\n"],"names":["generateId","prefix","timestamp","random"],"mappings":"gFAmBO,SAASA,EAAWC,EAAS,OAAQ,CAC1C,MAAMC,EAAY,KAAK,IAAG,EAAG,SAAS,EAAE,EAClCC,EAAS,KAAK,SAAS,SAAS,EAAE,EAAE,UAAU,EAAG,CAAC,EACxD,MAAO,GAAGF,CAAM,IAAIC,CAAS,GAAGC,CAAM,EACxC"}
1
+ {"version":3,"file":"index29.cjs","sources":["../src/rough/roughPathExtractor.js"],"sourcesContent":["/**\n * RoughJS Path Extractor - Utility functions for hand-drawn style paths\n *\n * Wraps RoughJS Generator API to extract path data as points arrays,\n * compatible with the existing StrokeRenderer pipeline.\n *\n * @module rough/roughPathExtractor\n */\n\nimport rough from 'roughjs';\n\nconst generator = rough.generator();\n\n/**\n * Cubic bezier interpolation\n *\n * @param {Array} p0 - Start point [x, y]\n * @param {Array} p1 - Control point 1 [x, y]\n * @param {Array} p2 - Control point 2 [x, y]\n * @param {Array} p3 - End point [x, y]\n * @param {number} t - Interpolation factor (0-1)\n * @returns {Array} Interpolated point [x, y]\n */\nfunction bezierPoint(p0, p1, p2, p3, t) {\n const mt = 1 - t;\n return [\n mt ** 3 * p0[0] + 3 * mt ** 2 * t * p1[0] + 3 * mt * t ** 2 * p2[0] + t ** 3 * p3[0],\n mt ** 3 * p0[1] + 3 * mt ** 2 * t * p1[1] + 3 * mt * t ** 2 * p2[1] + t ** 3 * p3[1]\n ];\n}\n\n/**\n * Convert RoughJS ops array to points array\n *\n * Processes move, lineTo, and bcurveTo operations.\n * Bezier curves are linearized with 4 intermediate points.\n *\n * @param {Array} ops - Array of RoughJS op objects\n * @returns {Array} Array of [x, y] points\n */\nfunction opsToPoints(ops) {\n const points = [];\n let current = [0, 0];\n\n for (const { op, data } of ops) {\n switch (op) {\n case 'move':\n current = [data[0], data[1]];\n points.push([...current]);\n break;\n\n case 'lineTo':\n current = [data[0], data[1]];\n points.push([...current]);\n break;\n\n case 'bcurveTo': {\n const [cx1, cy1, cx2, cy2, x, y] = data;\n const p0 = current;\n const p1 = [cx1, cy1];\n const p2 = [cx2, cy2];\n const p3 = [x, y];\n\n for (let t = 0.25; t <= 1; t += 0.25) {\n points.push(bezierPoint(p0, p1, p2, p3, t));\n }\n current = [x, y];\n break;\n }\n }\n }\n\n return points;\n}\n\n/**\n * Extract points from a RoughJS drawable\n *\n * Collects all path operations from drawable.sets and converts to points.\n *\n * @param {Object} drawable - RoughJS drawable object\n * @returns {Array} Array of [x, y] points\n */\nfunction extractPoints(drawable) {\n const allPoints = [];\n\n for (const set of drawable.sets) {\n if (set.type === 'path') {\n allPoints.push(...opsToPoints(set.ops));\n }\n }\n\n return allPoints;\n}\n\n/**\n * Generate a hash seed from a string\n *\n * Produces a deterministic number from string input for reproducible randomness.\n *\n * @param {string} str - Input string (e.g., annotation ID)\n * @returns {number} Hash value for use as seed\n */\nexport function hashSeed(str) {\n let hash = 0;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) - hash) + str.charCodeAt(i);\n hash |= 0;\n }\n return Math.abs(hash);\n}\n\n/**\n * Convert a line to RoughJS style points\n *\n * @param {number} x1 - Start x coordinate\n * @param {number} y1 - Start y coordinate\n * @param {number} x2 - End x coordinate\n * @param {number} y2 - End y coordinate\n * @param {Object} [options={}] - RoughJS options\n * @param {number} [options.roughness=1.0] - Line irregularity (0=clean, 3+=very rough)\n * @param {number} [options.bowing=1.0] - Line curvature (0=straight, 2+=very curved)\n * @param {number} [options.seed] - Seed for reproducible randomness\n * @param {number} [options.curveFitting=0.95] - Curve fitting (0=loose, 1=tight)\n * @param {number} [options.curveStepCount=9] - Curve resolution (higher=smoother)\n * @param {number} [options.maxRandomnessOffset=2] - Max random offset\n * @param {boolean} [options.disableMultiStroke=false] - Disable double-stroke effect\n * @returns {Array} Array of [x, y] points with hand-drawn style\n */\nexport function roughLine(x1, y1, x2, y2, options = {}) {\n const drawable = generator.line(x1, y1, x2, y2, {\n roughness: options.roughness ?? 1.0,\n bowing: options.bowing ?? 1.0,\n seed: options.seed ?? Math.floor(Math.random() * 2 ** 31),\n curveFitting: options.curveFitting ?? 0.95,\n curveStepCount: options.curveStepCount ?? 9,\n maxRandomnessOffset: options.maxRandomnessOffset ?? 2,\n disableMultiStroke: options.disableMultiStroke ?? false,\n ...options\n });\n\n return extractPoints(drawable);\n}\n\n/**\n * Convert an ellipse to RoughJS style points\n *\n * @param {number} cx - Center x coordinate\n * @param {number} cy - Center y coordinate\n * @param {number} width - Ellipse width\n * @param {number} height - Ellipse height\n * @param {Object} [options={}] - RoughJS options\n * @param {number} [options.roughness=1.0] - Shape irregularity\n * @param {number} [options.bowing=1.0] - Line curvature\n * @param {number} [options.seed] - Seed for reproducible randomness\n * @param {number} [options.curveFitting=0.95] - Curve fitting (0=loose, 1=tight)\n * @param {number} [options.curveStepCount=9] - Curve resolution (higher=smoother)\n * @param {number} [options.maxRandomnessOffset=2] - Max random offset\n * @param {boolean} [options.disableMultiStroke=false] - Disable double-stroke effect\n * @returns {Array} Array of [x, y] points with hand-drawn style\n */\nexport function roughEllipse(cx, cy, width, height, options = {}) {\n const drawable = generator.ellipse(cx, cy, width, height, {\n roughness: options.roughness ?? 1.0,\n bowing: options.bowing ?? 1.0,\n seed: options.seed ?? Math.floor(Math.random() * 2 ** 31),\n curveFitting: options.curveFitting ?? 0.95,\n curveStepCount: options.curveStepCount ?? 9,\n maxRandomnessOffset: options.maxRandomnessOffset ?? 2,\n disableMultiStroke: options.disableMultiStroke ?? false,\n ...options\n });\n\n return extractPoints(drawable);\n}\n\n/**\n * Convert a linear path (multiple connected points) to RoughJS style\n *\n * @param {Array} points - Array of [x, y] points to connect\n * @param {Object} [options={}] - RoughJS options\n * @param {number} [options.roughness=1.0] - Path irregularity\n * @param {number} [options.bowing=1.0] - Line curvature\n * @param {number} [options.seed] - Seed for reproducible randomness\n * @returns {Array} Array of [x, y] points with hand-drawn style\n */\nexport function roughLinearPath(points, options = {}) {\n if (!points || points.length < 2) {\n return points || [];\n }\n\n const drawable = generator.linearPath(points, {\n roughness: options.roughness ?? 1.0,\n bowing: options.bowing ?? 1.0,\n seed: options.seed ?? Math.floor(Math.random() * 2 ** 31),\n ...options\n });\n\n return extractPoints(drawable);\n}\n\nexport default {\n roughLine,\n roughEllipse,\n roughLinearPath,\n hashSeed\n};\n"],"names":["generator","rough","bezierPoint","p0","p1","p2","p3","t","mt","opsToPoints","ops","points","current","op","data","cx1","cy1","cx2","cy2","x","y","extractPoints","drawable","allPoints","set","hashSeed","str","hash","i","roughLine","x1","y1","x2","y2","options","roughEllipse","cx","cy","width","height"],"mappings":"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"}