web-annotation-renderer 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/ai-tools.js +11 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +49 -30
  5. package/dist/index.js.map +1 -1
  6. package/dist/index10.cjs +1 -1
  7. package/dist/index10.cjs.map +1 -1
  8. package/dist/index10.js +172 -17
  9. package/dist/index10.js.map +1 -1
  10. package/dist/index11.cjs +1 -1
  11. package/dist/index11.cjs.map +1 -1
  12. package/dist/index11.js +13 -20
  13. package/dist/index11.js.map +1 -1
  14. package/dist/index12.cjs +1 -1
  15. package/dist/index12.cjs.map +1 -1
  16. package/dist/index12.js +148 -123
  17. package/dist/index12.js.map +1 -1
  18. package/dist/index13.cjs +1 -1
  19. package/dist/index13.cjs.map +1 -1
  20. package/dist/index13.js +29 -198
  21. package/dist/index13.js.map +1 -1
  22. package/dist/index14.cjs +1 -1
  23. package/dist/index14.cjs.map +1 -1
  24. package/dist/index14.js +56 -15
  25. package/dist/index14.js.map +1 -1
  26. package/dist/index15.cjs +1 -1
  27. package/dist/index15.cjs.map +1 -1
  28. package/dist/index15.js +115 -120
  29. package/dist/index15.js.map +1 -1
  30. package/dist/index16.cjs +1 -1
  31. package/dist/index16.cjs.map +1 -1
  32. package/dist/index16.js +104 -32
  33. package/dist/index16.js.map +1 -1
  34. package/dist/index17.cjs +2 -0
  35. package/dist/index17.cjs.map +1 -0
  36. package/dist/index17.js +62 -0
  37. package/dist/index17.js.map +1 -0
  38. package/dist/index18.cjs +2 -0
  39. package/dist/index18.cjs.map +1 -0
  40. package/dist/index18.js +144 -0
  41. package/dist/index18.js.map +1 -0
  42. package/dist/index19.cjs +2 -0
  43. package/dist/index19.cjs.map +1 -0
  44. package/dist/index19.js +41 -0
  45. package/dist/index19.js.map +1 -0
  46. package/dist/index2.cjs +1 -1
  47. package/dist/index2.cjs.map +1 -1
  48. package/dist/index2.js +65 -73
  49. package/dist/index2.js.map +1 -1
  50. package/dist/index20.cjs +2 -0
  51. package/dist/index20.cjs.map +1 -0
  52. package/dist/index20.js +40 -0
  53. package/dist/index20.js.map +1 -0
  54. package/dist/index21.cjs +2 -0
  55. package/dist/index21.cjs.map +1 -0
  56. package/dist/index21.js +41 -0
  57. package/dist/index21.js.map +1 -0
  58. package/dist/index22.cjs +2 -0
  59. package/dist/index22.cjs.map +1 -0
  60. package/dist/index22.js +25 -0
  61. package/dist/index22.js.map +1 -0
  62. package/dist/index23.cjs +2 -0
  63. package/dist/index23.cjs.map +1 -0
  64. package/dist/index23.js +8 -0
  65. package/dist/index23.js.map +1 -0
  66. package/dist/index24.cjs +2 -0
  67. package/dist/index24.cjs.map +1 -0
  68. package/dist/index24.js +8 -0
  69. package/dist/index24.js.map +1 -0
  70. package/dist/index3.cjs +1 -1
  71. package/dist/index3.cjs.map +1 -1
  72. package/dist/index3.js +1 -1
  73. package/dist/index4.cjs +1 -1
  74. package/dist/index4.cjs.map +1 -1
  75. package/dist/index4.js +72 -71
  76. package/dist/index4.js.map +1 -1
  77. package/dist/index5.cjs +1 -1
  78. package/dist/index5.cjs.map +1 -1
  79. package/dist/index5.js +153 -65
  80. package/dist/index5.js.map +1 -1
  81. package/dist/index6.cjs +1 -1
  82. package/dist/index6.cjs.map +1 -1
  83. package/dist/index6.js +60 -114
  84. package/dist/index6.js.map +1 -1
  85. package/dist/index7.cjs +1 -1
  86. package/dist/index7.cjs.map +1 -1
  87. package/dist/index7.js +19 -91
  88. package/dist/index7.js.map +1 -1
  89. package/dist/index8.cjs +1 -1
  90. package/dist/index8.cjs.map +1 -1
  91. package/dist/index8.js +19 -105
  92. package/dist/index8.js.map +1 -1
  93. package/dist/index9.cjs +1 -1
  94. package/dist/index9.cjs.map +1 -1
  95. package/dist/index9.js +123 -98
  96. package/dist/index9.js.map +1 -1
  97. package/package.json +9 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index17.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;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=[{type:"function",function:{name:"create_highlight_annotation",description:"Create a highlight annotation at specified coordinates on the PDF page. Use this to emphasize important text or regions. Highlights are rectangular regions that can span multiple lines.",parameters:{type:"object",properties:{quads:{type:"array",description:"Array of rectangular regions defining the highlight areas. Each quad is an object with normalized coordinates (0-1): {x, y, w, h}. Multiple quads can be used for multi-line highlights.",items:{type:"object",properties:{x:{type:"number",description:"Normalized x position (0 = left, 1 = right)",minimum:0,maximum:1},y:{type:"number",description:"Normalized y position (0 = top, 1 = bottom)",minimum:0,maximum:1},w:{type:"number",description:"Normalized width (0-1)",minimum:0,maximum:1},h:{type:"number",description:"Normalized height (0-1)",minimum:0,maximum:1}},required:["x","y","w","h"]},minItems:1},color:{type:"string",description:"Highlight color in rgba format (e.g., 'rgba(255, 255, 0, 0.3)'). Default is semi-transparent yellow. Use rgba for transparency control.",default:"rgba(255, 255, 0, 0.3)"},page:{type:"integer",description:"Page number (1-indexed) where the annotation appears",minimum:1},sentence_ref:{type:"string",description:"Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization",pattern:"^S\\d+$"}},required:["quads","page","sentence_ref"]}}},{type:"function",function:{name:"create_text_annotation",description:"Create a text box annotation with explanatory content. Use this to add clarifying notes, definitions, or explanations. Text boxes have background and appear as overlays.",parameters:{type:"object",properties:{content:{type:"string",description:"The text content of the annotation",minLength:1,maxLength:500},x:{type:"number",description:"Normalized x position (0 = left edge, 1 = right edge)",minimum:0,maximum:1},y:{type:"number",description:"Normalized y position (0 = top edge, 1 = bottom edge)",minimum:0,maximum:1},w:{type:"number",description:"Normalized width (0-1) of the text box",minimum:0,maximum:1},h:{type:"number",description:"Normalized height (0-1) of the text box",minimum:0,maximum:1},page:{type:"integer",description:"Page number (1-indexed) where the annotation appears",minimum:1},textColor:{type:"string",description:"Text color in hex format (e.g., '#000000' for black). Default is dark gray.",default:"#1f2937"},bgColor:{type:"string",description:"Background color in rgba format or 'transparent' (e.g., 'rgba(255, 255, 255, 0.9)' or 'transparent'). Default is transparent for better visibility of underlying content. Use rgba format when background is needed.",default:"transparent"},sentence_ref:{type:"string",description:"Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization",pattern:"^S\\d+$"}},required:["content","x","y","w","h","page","sentence_ref"]}}}];function o(e=[]){if(!Array.isArray(e)||e.length===0)return[];const i={highlight:"create_highlight_annotation",text:"create_text_annotation"},r=e.map(t=>i[t]).filter(Boolean);return n.filter(t=>r.includes(t.function.name))}exports.annotationTools=n;exports.getAnnotationTools=o;
2
+ //# sourceMappingURL=index18.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index18.cjs","sources":["../src/ai-tools/openai/schemas.js"],"sourcesContent":["/**\n * OpenAI Tool Schemas for PDF Annotation Generation\n *\n * Provides OpenAI-compatible function calling schemas for creating PDF annotations.\n * These schemas define the structure and parameters for AI-generated annotations.\n * Compatible with web-annotation-renderer library format.\n *\n * @module ai-tools/openai/schemas\n */\n\n/**\n * Complete set of annotation tools for OpenAI function calling\n *\n * Export this array to the OpenAI API's `tools` parameter to enable\n * AI-generated annotations.\n *\n * @constant {Array<Object>}\n * @example\n * ```javascript\n * import { annotationTools } from 'web-annotation-renderer/ai-tools';\n *\n * const response = await openai.chat.completions.create({\n * model: \"gpt-4\",\n * messages: [...],\n * tools: annotationTools\n * });\n * ```\n */\nexport const annotationTools = [\n {\n type: \"function\",\n function: {\n name: \"create_highlight_annotation\",\n description: \"Create a highlight annotation at specified coordinates on the PDF page. Use this to emphasize important text or regions. Highlights are rectangular regions that can span multiple lines.\",\n parameters: {\n type: \"object\",\n properties: {\n quads: {\n type: \"array\",\n description: \"Array of rectangular regions defining the highlight areas. Each quad is an object with normalized coordinates (0-1): {x, y, w, h}. Multiple quads can be used for multi-line highlights.\",\n items: {\n type: \"object\",\n properties: {\n x: {\n type: \"number\",\n description: \"Normalized x position (0 = left, 1 = right)\",\n minimum: 0,\n maximum: 1\n },\n y: {\n type: \"number\",\n description: \"Normalized y position (0 = top, 1 = bottom)\",\n minimum: 0,\n maximum: 1\n },\n w: {\n type: \"number\",\n description: \"Normalized width (0-1)\",\n minimum: 0,\n maximum: 1\n },\n h: {\n type: \"number\",\n description: \"Normalized height (0-1)\",\n minimum: 0,\n maximum: 1\n }\n },\n required: [\"x\", \"y\", \"w\", \"h\"]\n },\n minItems: 1\n },\n color: {\n type: \"string\",\n description: \"Highlight color in rgba format (e.g., 'rgba(255, 255, 0, 0.3)'). Default is semi-transparent yellow. Use rgba for transparency control.\",\n default: \"rgba(255, 255, 0, 0.3)\"\n },\n page: {\n type: \"integer\",\n description: \"Page number (1-indexed) where the annotation appears\",\n minimum: 1\n },\n sentence_ref: {\n type: \"string\",\n description: \"Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization\",\n pattern: \"^S\\\\d+$\"\n }\n },\n required: [\"quads\", \"page\", \"sentence_ref\"]\n }\n }\n },\n {\n type: \"function\",\n function: {\n name: \"create_text_annotation\",\n description: \"Create a text box annotation with explanatory content. Use this to add clarifying notes, definitions, or explanations. Text boxes have background and appear as overlays.\",\n parameters: {\n type: \"object\",\n properties: {\n content: {\n type: \"string\",\n description: \"The text content of the annotation\",\n minLength: 1,\n maxLength: 500\n },\n x: {\n type: \"number\",\n description: \"Normalized x position (0 = left edge, 1 = right edge)\",\n minimum: 0,\n maximum: 1\n },\n y: {\n type: \"number\",\n description: \"Normalized y position (0 = top edge, 1 = bottom edge)\",\n minimum: 0,\n maximum: 1\n },\n w: {\n type: \"number\",\n description: \"Normalized width (0-1) of the text box\",\n minimum: 0,\n maximum: 1\n },\n h: {\n type: \"number\",\n description: \"Normalized height (0-1) of the text box\",\n minimum: 0,\n maximum: 1\n },\n page: {\n type: \"integer\",\n description: \"Page number (1-indexed) where the annotation appears\",\n minimum: 1\n },\n textColor: {\n type: \"string\",\n description: \"Text color in hex format (e.g., '#000000' for black). Default is dark gray.\",\n default: \"#1f2937\"\n },\n bgColor: {\n type: \"string\",\n description: \"Background color in rgba format or 'transparent' (e.g., 'rgba(255, 255, 255, 0.9)' or 'transparent'). Default is transparent for better visibility of underlying content. Use rgba format when background is needed.\",\n default: \"transparent\"\n },\n sentence_ref: {\n type: \"string\",\n description: \"Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization\",\n pattern: \"^S\\\\d+$\"\n }\n },\n required: [\"content\", \"x\", \"y\", \"w\", \"h\", \"page\", \"sentence_ref\"]\n }\n }\n }\n];\n\n/**\n * Get filtered annotation tools based on enabled types\n *\n * @param {Array<string>} enabledTypes - Array of enabled tool types: ['highlight', 'text']\n * @returns {Array<Object>} Filtered annotation tools\n * @example\n * ```javascript\n * // Only enable highlights and text notes\n * const tools = getAnnotationTools(['highlight', 'text']);\n * ```\n */\nexport function getAnnotationTools(enabledTypes = []) {\n if (!Array.isArray(enabledTypes) || enabledTypes.length === 0) {\n return [];\n }\n\n const typeMap = {\n 'highlight': 'create_highlight_annotation',\n 'text': 'create_text_annotation'\n };\n\n const enabledFunctionNames = enabledTypes\n .map(type => typeMap[type])\n .filter(Boolean);\n\n return annotationTools.filter(tool =>\n enabledFunctionNames.includes(tool.function.name)\n );\n}\n"],"names":["annotationTools","getAnnotationTools","enabledTypes","typeMap","enabledFunctionNames","type","tool"],"mappings":"gFA4BY,MAACA,EAAkB,CAC7B,CACE,KAAM,WACN,SAAU,CACR,KAAM,8BACN,YAAa,4LACb,WAAY,CACV,KAAM,SACN,WAAY,CACV,MAAO,CACL,KAAM,QACN,YAAa,2LACb,MAAO,CACL,KAAM,SACN,WAAY,CACV,EAAG,CACD,KAAM,SACN,YAAa,8CACb,QAAS,EACT,QAAS,CAC3B,EACgB,EAAG,CACD,KAAM,SACN,YAAa,8CACb,QAAS,EACT,QAAS,CAC3B,EACgB,EAAG,CACD,KAAM,SACN,YAAa,yBACb,QAAS,EACT,QAAS,CAC3B,EACgB,EAAG,CACD,KAAM,SACN,YAAa,0BACb,QAAS,EACT,QAAS,CAC3B,CACA,EACc,SAAU,CAAC,IAAK,IAAK,IAAK,GAAG,CAC3C,EACY,SAAU,CACtB,EACU,MAAO,CACL,KAAM,SACN,YAAa,0IACb,QAAS,wBACrB,EACU,KAAM,CACJ,KAAM,UACN,YAAa,uDACb,QAAS,CACrB,EACU,aAAc,CACZ,KAAM,SACN,YAAa,6EACb,QAAS,SACrB,CACA,EACQ,SAAU,CAAC,QAAS,OAAQ,cAAc,CAClD,CACA,CACA,EACE,CACE,KAAM,WACN,SAAU,CACR,KAAM,yBACN,YAAa,4KACb,WAAY,CACV,KAAM,SACN,WAAY,CACV,QAAS,CACP,KAAM,SACN,YAAa,qCACb,UAAW,EACX,UAAW,GACvB,EACU,EAAG,CACD,KAAM,SACN,YAAa,wDACb,QAAS,EACT,QAAS,CACrB,EACU,EAAG,CACD,KAAM,SACN,YAAa,wDACb,QAAS,EACT,QAAS,CACrB,EACU,EAAG,CACD,KAAM,SACN,YAAa,yCACb,QAAS,EACT,QAAS,CACrB,EACU,EAAG,CACD,KAAM,SACN,YAAa,0CACb,QAAS,EACT,QAAS,CACrB,EACU,KAAM,CACJ,KAAM,UACN,YAAa,uDACb,QAAS,CACrB,EACU,UAAW,CACT,KAAM,SACN,YAAa,8EACb,QAAS,SACrB,EACU,QAAS,CACP,KAAM,SACN,YAAa,uNACb,QAAS,aACrB,EACU,aAAc,CACZ,KAAM,SACN,YAAa,6EACb,QAAS,SACrB,CACA,EACQ,SAAU,CAAC,UAAW,IAAK,IAAK,IAAK,IAAK,OAAQ,cAAc,CACxE,CACA,CACA,CACA,EAaO,SAASC,EAAmBC,EAAe,GAAI,CACpD,GAAI,CAAC,MAAM,QAAQA,CAAY,GAAKA,EAAa,SAAW,EAC1D,MAAO,CAAA,EAGT,MAAMC,EAAU,CACd,UAAa,8BACb,KAAQ,wBACZ,EAEQC,EAAuBF,EAC1B,IAAIG,GAAQF,EAAQE,CAAI,CAAC,EACzB,OAAO,OAAO,EAEjB,OAAOL,EAAgB,OAAOM,GAC5BF,EAAqB,SAASE,EAAK,SAAS,IAAI,CACpD,CACA"}
@@ -0,0 +1,144 @@
1
+ const r = [
2
+ {
3
+ type: "function",
4
+ function: {
5
+ name: "create_highlight_annotation",
6
+ description: "Create a highlight annotation at specified coordinates on the PDF page. Use this to emphasize important text or regions. Highlights are rectangular regions that can span multiple lines.",
7
+ parameters: {
8
+ type: "object",
9
+ properties: {
10
+ quads: {
11
+ type: "array",
12
+ description: "Array of rectangular regions defining the highlight areas. Each quad is an object with normalized coordinates (0-1): {x, y, w, h}. Multiple quads can be used for multi-line highlights.",
13
+ items: {
14
+ type: "object",
15
+ properties: {
16
+ x: {
17
+ type: "number",
18
+ description: "Normalized x position (0 = left, 1 = right)",
19
+ minimum: 0,
20
+ maximum: 1
21
+ },
22
+ y: {
23
+ type: "number",
24
+ description: "Normalized y position (0 = top, 1 = bottom)",
25
+ minimum: 0,
26
+ maximum: 1
27
+ },
28
+ w: {
29
+ type: "number",
30
+ description: "Normalized width (0-1)",
31
+ minimum: 0,
32
+ maximum: 1
33
+ },
34
+ h: {
35
+ type: "number",
36
+ description: "Normalized height (0-1)",
37
+ minimum: 0,
38
+ maximum: 1
39
+ }
40
+ },
41
+ required: ["x", "y", "w", "h"]
42
+ },
43
+ minItems: 1
44
+ },
45
+ color: {
46
+ type: "string",
47
+ description: "Highlight color in rgba format (e.g., 'rgba(255, 255, 0, 0.3)'). Default is semi-transparent yellow. Use rgba for transparency control.",
48
+ default: "rgba(255, 255, 0, 0.3)"
49
+ },
50
+ page: {
51
+ type: "integer",
52
+ description: "Page number (1-indexed) where the annotation appears",
53
+ minimum: 1
54
+ },
55
+ sentence_ref: {
56
+ type: "string",
57
+ description: "Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization",
58
+ pattern: "^S\\d+$"
59
+ }
60
+ },
61
+ required: ["quads", "page", "sentence_ref"]
62
+ }
63
+ }
64
+ },
65
+ {
66
+ type: "function",
67
+ function: {
68
+ name: "create_text_annotation",
69
+ description: "Create a text box annotation with explanatory content. Use this to add clarifying notes, definitions, or explanations. Text boxes have background and appear as overlays.",
70
+ parameters: {
71
+ type: "object",
72
+ properties: {
73
+ content: {
74
+ type: "string",
75
+ description: "The text content of the annotation",
76
+ minLength: 1,
77
+ maxLength: 500
78
+ },
79
+ x: {
80
+ type: "number",
81
+ description: "Normalized x position (0 = left edge, 1 = right edge)",
82
+ minimum: 0,
83
+ maximum: 1
84
+ },
85
+ y: {
86
+ type: "number",
87
+ description: "Normalized y position (0 = top edge, 1 = bottom edge)",
88
+ minimum: 0,
89
+ maximum: 1
90
+ },
91
+ w: {
92
+ type: "number",
93
+ description: "Normalized width (0-1) of the text box",
94
+ minimum: 0,
95
+ maximum: 1
96
+ },
97
+ h: {
98
+ type: "number",
99
+ description: "Normalized height (0-1) of the text box",
100
+ minimum: 0,
101
+ maximum: 1
102
+ },
103
+ page: {
104
+ type: "integer",
105
+ description: "Page number (1-indexed) where the annotation appears",
106
+ minimum: 1
107
+ },
108
+ textColor: {
109
+ type: "string",
110
+ description: "Text color in hex format (e.g., '#000000' for black). Default is dark gray.",
111
+ default: "#1f2937"
112
+ },
113
+ bgColor: {
114
+ type: "string",
115
+ description: "Background color in rgba format or 'transparent' (e.g., 'rgba(255, 255, 255, 0.9)' or 'transparent'). Default is transparent for better visibility of underlying content. Use rgba format when background is needed.",
116
+ default: "transparent"
117
+ },
118
+ sentence_ref: {
119
+ type: "string",
120
+ description: "Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization",
121
+ pattern: "^S\\d+$"
122
+ }
123
+ },
124
+ required: ["content", "x", "y", "w", "h", "page", "sentence_ref"]
125
+ }
126
+ }
127
+ }
128
+ ];
129
+ function o(e = []) {
130
+ if (!Array.isArray(e) || e.length === 0)
131
+ return [];
132
+ const n = {
133
+ highlight: "create_highlight_annotation",
134
+ text: "create_text_annotation"
135
+ }, i = e.map((t) => n[t]).filter(Boolean);
136
+ return r.filter(
137
+ (t) => i.includes(t.function.name)
138
+ );
139
+ }
140
+ export {
141
+ r as annotationTools,
142
+ o as getAnnotationTools
143
+ };
144
+ //# sourceMappingURL=index18.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index18.js","sources":["../src/ai-tools/openai/schemas.js"],"sourcesContent":["/**\n * OpenAI Tool Schemas for PDF Annotation Generation\n *\n * Provides OpenAI-compatible function calling schemas for creating PDF annotations.\n * These schemas define the structure and parameters for AI-generated annotations.\n * Compatible with web-annotation-renderer library format.\n *\n * @module ai-tools/openai/schemas\n */\n\n/**\n * Complete set of annotation tools for OpenAI function calling\n *\n * Export this array to the OpenAI API's `tools` parameter to enable\n * AI-generated annotations.\n *\n * @constant {Array<Object>}\n * @example\n * ```javascript\n * import { annotationTools } from 'web-annotation-renderer/ai-tools';\n *\n * const response = await openai.chat.completions.create({\n * model: \"gpt-4\",\n * messages: [...],\n * tools: annotationTools\n * });\n * ```\n */\nexport const annotationTools = [\n {\n type: \"function\",\n function: {\n name: \"create_highlight_annotation\",\n description: \"Create a highlight annotation at specified coordinates on the PDF page. Use this to emphasize important text or regions. Highlights are rectangular regions that can span multiple lines.\",\n parameters: {\n type: \"object\",\n properties: {\n quads: {\n type: \"array\",\n description: \"Array of rectangular regions defining the highlight areas. Each quad is an object with normalized coordinates (0-1): {x, y, w, h}. Multiple quads can be used for multi-line highlights.\",\n items: {\n type: \"object\",\n properties: {\n x: {\n type: \"number\",\n description: \"Normalized x position (0 = left, 1 = right)\",\n minimum: 0,\n maximum: 1\n },\n y: {\n type: \"number\",\n description: \"Normalized y position (0 = top, 1 = bottom)\",\n minimum: 0,\n maximum: 1\n },\n w: {\n type: \"number\",\n description: \"Normalized width (0-1)\",\n minimum: 0,\n maximum: 1\n },\n h: {\n type: \"number\",\n description: \"Normalized height (0-1)\",\n minimum: 0,\n maximum: 1\n }\n },\n required: [\"x\", \"y\", \"w\", \"h\"]\n },\n minItems: 1\n },\n color: {\n type: \"string\",\n description: \"Highlight color in rgba format (e.g., 'rgba(255, 255, 0, 0.3)'). Default is semi-transparent yellow. Use rgba for transparency control.\",\n default: \"rgba(255, 255, 0, 0.3)\"\n },\n page: {\n type: \"integer\",\n description: \"Page number (1-indexed) where the annotation appears\",\n minimum: 1\n },\n sentence_ref: {\n type: \"string\",\n description: \"Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization\",\n pattern: \"^S\\\\d+$\"\n }\n },\n required: [\"quads\", \"page\", \"sentence_ref\"]\n }\n }\n },\n {\n type: \"function\",\n function: {\n name: \"create_text_annotation\",\n description: \"Create a text box annotation with explanatory content. Use this to add clarifying notes, definitions, or explanations. Text boxes have background and appear as overlays.\",\n parameters: {\n type: \"object\",\n properties: {\n content: {\n type: \"string\",\n description: \"The text content of the annotation\",\n minLength: 1,\n maxLength: 500\n },\n x: {\n type: \"number\",\n description: \"Normalized x position (0 = left edge, 1 = right edge)\",\n minimum: 0,\n maximum: 1\n },\n y: {\n type: \"number\",\n description: \"Normalized y position (0 = top edge, 1 = bottom edge)\",\n minimum: 0,\n maximum: 1\n },\n w: {\n type: \"number\",\n description: \"Normalized width (0-1) of the text box\",\n minimum: 0,\n maximum: 1\n },\n h: {\n type: \"number\",\n description: \"Normalized height (0-1) of the text box\",\n minimum: 0,\n maximum: 1\n },\n page: {\n type: \"integer\",\n description: \"Page number (1-indexed) where the annotation appears\",\n minimum: 1\n },\n textColor: {\n type: \"string\",\n description: \"Text color in hex format (e.g., '#000000' for black). Default is dark gray.\",\n default: \"#1f2937\"\n },\n bgColor: {\n type: \"string\",\n description: \"Background color in rgba format or 'transparent' (e.g., 'rgba(255, 255, 255, 0.9)' or 'transparent'). Default is transparent for better visibility of underlying content. Use rgba format when background is needed.\",\n default: \"transparent\"\n },\n sentence_ref: {\n type: \"string\",\n description: \"Reference to sentence marker (e.g., 'S1', 'S2') for timing synchronization\",\n pattern: \"^S\\\\d+$\"\n }\n },\n required: [\"content\", \"x\", \"y\", \"w\", \"h\", \"page\", \"sentence_ref\"]\n }\n }\n }\n];\n\n/**\n * Get filtered annotation tools based on enabled types\n *\n * @param {Array<string>} enabledTypes - Array of enabled tool types: ['highlight', 'text']\n * @returns {Array<Object>} Filtered annotation tools\n * @example\n * ```javascript\n * // Only enable highlights and text notes\n * const tools = getAnnotationTools(['highlight', 'text']);\n * ```\n */\nexport function getAnnotationTools(enabledTypes = []) {\n if (!Array.isArray(enabledTypes) || enabledTypes.length === 0) {\n return [];\n }\n\n const typeMap = {\n 'highlight': 'create_highlight_annotation',\n 'text': 'create_text_annotation'\n };\n\n const enabledFunctionNames = enabledTypes\n .map(type => typeMap[type])\n .filter(Boolean);\n\n return annotationTools.filter(tool =>\n enabledFunctionNames.includes(tool.function.name)\n );\n}\n"],"names":["annotationTools","getAnnotationTools","enabledTypes","typeMap","enabledFunctionNames","type","tool"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index20.cjs"),c=require("./index21.cjs");function o(r){if(!r||typeof r!="object")throw new Error("Invalid tool call: must be an object");if(!r.function||typeof r.function!="object")throw new Error("Invalid tool call: missing function property");const{name:t,arguments:e}=r.function;if(!t||typeof t!="string")throw new Error("Invalid tool call: missing or invalid function name");let n;try{n=typeof e=="string"?JSON.parse(e):e}catch(a){throw new Error(`Failed to parse tool call arguments: ${a.message}`)}switch(t){case"create_highlight_annotation":return i.createHighlight(n);case"create_text_annotation":return c.createText(n);default:throw new Error(`Unknown tool: ${t}. Supported tools: create_highlight_annotation, create_text_annotation`)}}function l(r){if(!Array.isArray(r))throw new Error("Tool calls must be an array");return r.map((t,e)=>{try{return o(t)}catch(n){throw new Error(`Error processing tool call at index ${e}: ${n.message}`)}})}exports.handleToolCall=o;exports.handleToolCalls=l;
2
+ //# sourceMappingURL=index19.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index19.cjs","sources":["../src/ai-tools/openai/handler.js"],"sourcesContent":["/**\n * OpenAI Tool Call Handler\n *\n * Processes OpenAI function calling responses and converts them into\n * valid annotation objects.\n *\n * @module ai-tools/openai/handler\n */\n\nimport { createHighlight } from '../creators/createHighlight.js';\nimport { createText } from '../creators/createText.js';\n\n/**\n * Handle an OpenAI tool call and convert it to a valid annotation\n *\n * @param {Object} toolCall - Tool call object from OpenAI API response\n * @param {Object} toolCall.function - Function call details\n * @param {string} toolCall.function.name - Function name\n * @param {string} toolCall.function.arguments - JSON string of arguments\n * @returns {Object} Valid annotation object\n * @throws {Error} If tool call is invalid or unsupported\n * @example\n * ```javascript\n * import { handleToolCall } from 'web-annotation-renderer/ai-tools';\n *\n * const response = await openai.chat.completions.create({\n * model: \"gpt-4\",\n * messages: [...],\n * tools: annotationTools\n * });\n *\n * const annotations = [];\n * if (response.choices[0].message.tool_calls) {\n * for (const toolCall of response.choices[0].message.tool_calls) {\n * const annotation = handleToolCall(toolCall);\n * annotations.push(annotation);\n * }\n * }\n * ```\n */\nexport function handleToolCall(toolCall) {\n // Validate tool call structure\n if (!toolCall || typeof toolCall !== 'object') {\n throw new Error('Invalid tool call: must be an object');\n }\n\n if (!toolCall.function || typeof toolCall.function !== 'object') {\n throw new Error('Invalid tool call: missing function property');\n }\n\n const { name, arguments: argsString } = toolCall.function;\n\n if (!name || typeof name !== 'string') {\n throw new Error('Invalid tool call: missing or invalid function name');\n }\n\n // Parse arguments\n let args;\n try {\n args = typeof argsString === 'string' ? JSON.parse(argsString) : argsString;\n } catch (error) {\n throw new Error(`Failed to parse tool call arguments: ${error.message}`);\n }\n\n // Route to appropriate creator function\n switch (name) {\n case 'create_highlight_annotation':\n return createHighlight(args);\n\n case 'create_text_annotation':\n return createText(args);\n\n default:\n throw new Error(`Unknown tool: ${name}. Supported tools: create_highlight_annotation, create_text_annotation`);\n }\n}\n\n/**\n * Process multiple tool calls from an OpenAI response\n *\n * @param {Array<Object>} toolCalls - Array of tool call objects from OpenAI\n * @returns {Array<Object>} Array of valid annotation objects\n * @example\n * ```javascript\n * const annotations = handleToolCalls(response.choices[0].message.tool_calls);\n * ```\n */\nexport function handleToolCalls(toolCalls) {\n if (!Array.isArray(toolCalls)) {\n throw new Error('Tool calls must be an array');\n }\n\n return toolCalls.map((toolCall, index) => {\n try {\n return handleToolCall(toolCall);\n } catch (error) {\n throw new Error(`Error processing tool call at index ${index}: ${error.message}`);\n }\n });\n}\n"],"names":["handleToolCall","toolCall","name","argsString","args","error","createHighlight","createText","handleToolCalls","toolCalls","index"],"mappings":"4IAwCO,SAASA,EAAeC,EAAU,CAEvC,GAAI,CAACA,GAAY,OAAOA,GAAa,SACnC,MAAM,IAAI,MAAM,sCAAsC,EAGxD,GAAI,CAACA,EAAS,UAAY,OAAOA,EAAS,UAAa,SACrD,MAAM,IAAI,MAAM,8CAA8C,EAGhE,KAAM,CAAE,KAAAC,EAAM,UAAWC,CAAU,EAAKF,EAAS,SAEjD,GAAI,CAACC,GAAQ,OAAOA,GAAS,SAC3B,MAAM,IAAI,MAAM,qDAAqD,EAIvE,IAAIE,EACJ,GAAI,CACFA,EAAO,OAAOD,GAAe,SAAW,KAAK,MAAMA,CAAU,EAAIA,CACnE,OAASE,EAAO,CACd,MAAM,IAAI,MAAM,wCAAwCA,EAAM,OAAO,EAAE,CACzE,CAGA,OAAQH,EAAI,CACV,IAAK,8BACH,OAAOI,EAAAA,gBAAgBF,CAAI,EAE7B,IAAK,yBACH,OAAOG,EAAAA,WAAWH,CAAI,EAExB,QACE,MAAM,IAAI,MAAM,iBAAiBF,CAAI,wEAAwE,CACnH,CACA,CAYO,SAASM,EAAgBC,EAAW,CACzC,GAAI,CAAC,MAAM,QAAQA,CAAS,EAC1B,MAAM,IAAI,MAAM,6BAA6B,EAG/C,OAAOA,EAAU,IAAI,CAACR,EAAUS,IAAU,CACxC,GAAI,CACF,OAAOV,EAAeC,CAAQ,CAChC,OAASI,EAAO,CACd,MAAM,IAAI,MAAM,uCAAuCK,CAAK,KAAKL,EAAM,OAAO,EAAE,CAClF,CACF,CAAC,CACH"}
@@ -0,0 +1,41 @@
1
+ import { createHighlight as a } from "./index20.js";
2
+ import { createText as i } from "./index21.js";
3
+ function c(r) {
4
+ if (!r || typeof r != "object")
5
+ throw new Error("Invalid tool call: must be an object");
6
+ if (!r.function || typeof r.function != "object")
7
+ throw new Error("Invalid tool call: missing function property");
8
+ const { name: t, arguments: o } = r.function;
9
+ if (!t || typeof t != "string")
10
+ throw new Error("Invalid tool call: missing or invalid function name");
11
+ let n;
12
+ try {
13
+ n = typeof o == "string" ? JSON.parse(o) : o;
14
+ } catch (e) {
15
+ throw new Error(`Failed to parse tool call arguments: ${e.message}`);
16
+ }
17
+ switch (t) {
18
+ case "create_highlight_annotation":
19
+ return a(n);
20
+ case "create_text_annotation":
21
+ return i(n);
22
+ default:
23
+ throw new Error(`Unknown tool: ${t}. Supported tools: create_highlight_annotation, create_text_annotation`);
24
+ }
25
+ }
26
+ function h(r) {
27
+ if (!Array.isArray(r))
28
+ throw new Error("Tool calls must be an array");
29
+ return r.map((t, o) => {
30
+ try {
31
+ return c(t);
32
+ } catch (n) {
33
+ throw new Error(`Error processing tool call at index ${o}: ${n.message}`);
34
+ }
35
+ });
36
+ }
37
+ export {
38
+ c as handleToolCall,
39
+ h as handleToolCalls
40
+ };
41
+ //# sourceMappingURL=index19.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index19.js","sources":["../src/ai-tools/openai/handler.js"],"sourcesContent":["/**\n * OpenAI Tool Call Handler\n *\n * Processes OpenAI function calling responses and converts them into\n * valid annotation objects.\n *\n * @module ai-tools/openai/handler\n */\n\nimport { createHighlight } from '../creators/createHighlight.js';\nimport { createText } from '../creators/createText.js';\n\n/**\n * Handle an OpenAI tool call and convert it to a valid annotation\n *\n * @param {Object} toolCall - Tool call object from OpenAI API response\n * @param {Object} toolCall.function - Function call details\n * @param {string} toolCall.function.name - Function name\n * @param {string} toolCall.function.arguments - JSON string of arguments\n * @returns {Object} Valid annotation object\n * @throws {Error} If tool call is invalid or unsupported\n * @example\n * ```javascript\n * import { handleToolCall } from 'web-annotation-renderer/ai-tools';\n *\n * const response = await openai.chat.completions.create({\n * model: \"gpt-4\",\n * messages: [...],\n * tools: annotationTools\n * });\n *\n * const annotations = [];\n * if (response.choices[0].message.tool_calls) {\n * for (const toolCall of response.choices[0].message.tool_calls) {\n * const annotation = handleToolCall(toolCall);\n * annotations.push(annotation);\n * }\n * }\n * ```\n */\nexport function handleToolCall(toolCall) {\n // Validate tool call structure\n if (!toolCall || typeof toolCall !== 'object') {\n throw new Error('Invalid tool call: must be an object');\n }\n\n if (!toolCall.function || typeof toolCall.function !== 'object') {\n throw new Error('Invalid tool call: missing function property');\n }\n\n const { name, arguments: argsString } = toolCall.function;\n\n if (!name || typeof name !== 'string') {\n throw new Error('Invalid tool call: missing or invalid function name');\n }\n\n // Parse arguments\n let args;\n try {\n args = typeof argsString === 'string' ? JSON.parse(argsString) : argsString;\n } catch (error) {\n throw new Error(`Failed to parse tool call arguments: ${error.message}`);\n }\n\n // Route to appropriate creator function\n switch (name) {\n case 'create_highlight_annotation':\n return createHighlight(args);\n\n case 'create_text_annotation':\n return createText(args);\n\n default:\n throw new Error(`Unknown tool: ${name}. Supported tools: create_highlight_annotation, create_text_annotation`);\n }\n}\n\n/**\n * Process multiple tool calls from an OpenAI response\n *\n * @param {Array<Object>} toolCalls - Array of tool call objects from OpenAI\n * @returns {Array<Object>} Array of valid annotation objects\n * @example\n * ```javascript\n * const annotations = handleToolCalls(response.choices[0].message.tool_calls);\n * ```\n */\nexport function handleToolCalls(toolCalls) {\n if (!Array.isArray(toolCalls)) {\n throw new Error('Tool calls must be an array');\n }\n\n return toolCalls.map((toolCall, index) => {\n try {\n return handleToolCall(toolCall);\n } catch (error) {\n throw new Error(`Error processing tool call at index ${index}: ${error.message}`);\n }\n });\n}\n"],"names":["handleToolCall","toolCall","name","argsString","args","error","createHighlight","createText","handleToolCalls","toolCalls","index"],"mappings":";;AAwCO,SAASA,EAAeC,GAAU;AAEvC,MAAI,CAACA,KAAY,OAAOA,KAAa;AACnC,UAAM,IAAI,MAAM,sCAAsC;AAGxD,MAAI,CAACA,EAAS,YAAY,OAAOA,EAAS,YAAa;AACrD,UAAM,IAAI,MAAM,8CAA8C;AAGhE,QAAM,EAAE,MAAAC,GAAM,WAAWC,EAAU,IAAKF,EAAS;AAEjD,MAAI,CAACC,KAAQ,OAAOA,KAAS;AAC3B,UAAM,IAAI,MAAM,qDAAqD;AAIvE,MAAIE;AACJ,MAAI;AACF,IAAAA,IAAO,OAAOD,KAAe,WAAW,KAAK,MAAMA,CAAU,IAAIA;AAAA,EACnE,SAASE,GAAO;AACd,UAAM,IAAI,MAAM,wCAAwCA,EAAM,OAAO,EAAE;AAAA,EACzE;AAGA,UAAQH,GAAI;AAAA,IACV,KAAK;AACH,aAAOI,EAAgBF,CAAI;AAAA,IAE7B,KAAK;AACH,aAAOG,EAAWH,CAAI;AAAA,IAExB;AACE,YAAM,IAAI,MAAM,iBAAiBF,CAAI,wEAAwE;AAAA,EACnH;AACA;AAYO,SAASM,EAAgBC,GAAW;AACzC,MAAI,CAAC,MAAM,QAAQA,CAAS;AAC1B,UAAM,IAAI,MAAM,6BAA6B;AAG/C,SAAOA,EAAU,IAAI,CAACR,GAAUS,MAAU;AACxC,QAAI;AACF,aAAOV,EAAeC,CAAQ;AAAA,IAChC,SAASI,GAAO;AACd,YAAM,IAAI,MAAM,uCAAuCK,CAAK,KAAKL,EAAM,OAAO,EAAE;AAAA,IAClF;AAAA,EACF,CAAC;AACH;"}
package/dist/index2.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./index3.cjs"),n=require("./index4.cjs"),s=require("./index5.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 r.PDFRenderer,this.layerManager=new n.LayerManager(e.container,{width:1,height:1,scale:1}),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.layerManager.updateTimeline(t)}),e.pdfUrl&&this.loadPDF(e.pdfUrl).catch(t=>{console.error("AnnotationRenderer: Failed to auto-load PDF:",t)})}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);return t.success?(this.currentPage=e,this.currentViewport=t.viewport,this.layerManager.setAnnotations(this.annotations,e),this.layerManager.setViewport(t.viewport),{success:!0,viewport:t.viewport}):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.layerManager.setAnnotations(e,this.currentPage)}setTime(e){if(typeof e!="number"){console.warn("AnnotationRenderer.setTime: timestamp must be a number");return}this.timelineSync.setTime(e)}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.layerManager&&this.layerManager.destroy(),this.timelineSync&&this.timelineSync.destroy(),this.pdfRenderer=null,this.layerManager=null,this.timelineSync=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"),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)}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;
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 * This module orchestrates all subsystems (PDFRenderer, LayerManager, TimelineSync)\n * and 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 { LayerManager } from './LayerManager.js';\nimport { TimelineSync } from './TimelineSync.js';\n\n/**\n * AnnotationRenderer class\n *\n * Main engine that coordinates PDF rendering, annotation layers, and timeline\n * synchronization. Provides simple imperative API for consumers.\n *\n * @class\n * @example\n * const renderer = new AnnotationRenderer({\n * container: document.getElementById('layer-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.setScale(1.5);\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 layer rendering\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 * @throws {Error} If config is invalid or required elements are missing\n */\n constructor(config) {\n // Validate 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 /**\n * @private\n * @type {Object}\n */\n this.config = config;\n\n /**\n * @private\n * @type {HTMLCanvasElement}\n */\n this.canvasElement = config.canvasElement;\n\n /**\n * @private\n * @type {HTMLElement}\n */\n this.container = config.container;\n\n /**\n * @private\n * @type {PDFRenderer}\n */\n this.pdfRenderer = new PDFRenderer();\n\n /**\n * @private\n * @type {LayerManager}\n */\n // Initialize LayerManager with a minimal default viewport that will be updated when PDF loads\n // BaseLayer requires positive width/height, so use 1x1 as placeholder\n this.layerManager = new LayerManager(config.container, {\n width: 1,\n height: 1,\n scale: 1.0\n });\n\n /**\n * @private\n * @type {TimelineSync}\n */\n this.timelineSync = new TimelineSync();\n\n /**\n * @private\n * @type {number}\n */\n this.currentPage = config.initialPage || 1;\n\n /**\n * @private\n * @type {number}\n */\n this.currentScale = config.initialScale || 1.0;\n\n /**\n * @private\n * @type {Array}\n */\n this.annotations = config.annotations || [];\n\n /**\n * @private\n * @type {number}\n */\n this.pageCount = 0;\n\n /**\n * @private\n * @type {Object|null}\n */\n this.currentViewport = null;\n\n /**\n * @private\n * @type {string|null}\n */\n this.pdfUrl = null;\n\n // Wire up subsystem communication\n // Timeline updates automatically propagate to LayerManager\n this.timelineSync.subscribe((time) => {\n this.layerManager.updateTimeline(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 * 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 * @returns {boolean} return.success - Whether loading succeeded\n * @returns {number} [return.pageCount] - Number of pages if successful\n * @returns {string} [return.error] - Error message if failed\n */\n async loadPDF(url) {\n try {\n // Validate URL\n if (!url || typeof url !== 'string') {\n return {\n success: false,\n error: 'Invalid PDF URL provided'\n };\n }\n\n // Load via PDFRenderer\n const result = await this.pdfRenderer.loadDocument(url);\n\n if (result.success) {\n // Store PDF metadata\n this.pdfUrl = url;\n this.pageCount = result.pageCount;\n\n return {\n success: true,\n pageCount: result.pageCount\n };\n } else {\n return result;\n }\n } catch (err) {\n console.error('AnnotationRenderer.loadPDF: Error loading PDF:', err);\n return {\n success: false,\n error: `Failed to load PDF: ${err.message}`\n };\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 * @returns {boolean} return.success - Whether rendering succeeded\n * @returns {Object} [return.viewport] - Viewport dimensions if successful\n * @returns {string} [return.error] - Error message if failed\n */\n async setPage(pageNum) {\n try {\n // Validate page number\n if (typeof pageNum !== 'number' || pageNum < 1) {\n return {\n success: false,\n error: 'Invalid page number'\n };\n }\n\n if (this.pageCount > 0 && pageNum > this.pageCount) {\n return {\n success: false,\n error: `Page ${pageNum} exceeds document page count (${this.pageCount})`\n };\n }\n\n // Cancel any in-progress rendering\n this.pdfRenderer.cancelRender();\n\n // Render page via PDFRenderer\n const result = await this.pdfRenderer.renderPage(\n pageNum,\n this.canvasElement,\n this.currentScale\n );\n\n if (result.success) {\n // Store current state\n this.currentPage = pageNum;\n this.currentViewport = result.viewport;\n\n // Update LayerManager with new page and viewport\n this.layerManager.setAnnotations(this.annotations, pageNum);\n this.layerManager.setViewport(result.viewport);\n\n return {\n success: true,\n viewport: result.viewport\n };\n } else {\n return result;\n }\n } catch (err) {\n console.error('AnnotationRenderer.setPage: Error rendering page:', err);\n return {\n success: false,\n error: `Failed to render page: ${err.message}`\n };\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 * @returns {boolean} return.success - Whether rendering succeeded\n * @returns {Object} [return.viewport] - Viewport dimensions if successful\n * @returns {string} [return.error] - Error message if failed\n */\n async setScale(scale) {\n try {\n // Validate scale\n if (typeof scale !== 'number' || scale <= 0) {\n return {\n success: false,\n error: 'Invalid scale value (must be positive number)'\n };\n }\n\n // Store new scale\n this.currentScale = scale;\n\n // Re-render current page at new scale\n const result = await this.setPage(this.currentPage);\n\n return result;\n } catch (err) {\n console.error('AnnotationRenderer.setScale: Error changing scale:', err);\n return {\n success: false,\n error: `Failed to change scale: ${err.message}`\n };\n }\n }\n\n /**\n * Update annotation data for rendering\n *\n * @param {Array} annotations - Complete annotation array (all pages, all types)\n * @returns {void}\n */\n setAnnotations(annotations) {\n // Validate annotations\n if (!Array.isArray(annotations)) {\n console.warn('AnnotationRenderer.setAnnotations: annotations must be an array');\n annotations = [];\n }\n\n // Store annotations\n this.annotations = annotations;\n\n // Route to LayerManager for current page\n this.layerManager.setAnnotations(annotations, this.currentPage);\n }\n\n /**\n * Update timeline position for animation\n *\n * @param {number} timestamp - Current timeline position in seconds\n * @returns {void}\n */\n setTime(timestamp) {\n // Validate timestamp\n if (typeof timestamp !== 'number') {\n console.warn('AnnotationRenderer.setTime: timestamp must be a number');\n return;\n }\n\n // Forward to TimelineSync\n // TimelineSync will notify LayerManager automatically via subscription\n this.timelineSync.setTime(timestamp);\n }\n\n /**\n * Get current engine state snapshot\n *\n * @returns {Object} Current state\n * @returns {number} return.page - Current page number\n * @returns {number} return.scale - Current scale factor\n * @returns {Array} return.annotations - Current annotation array\n * @returns {number} return.pageCount - Total page count\n * @returns {number} return.time - Current timeline position\n * @returns {Object|null} return.viewport - Current viewport dimensions\n * @returns {string|null} return.pdfUrl - Current PDF URL\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 * Call before removing AnnotationRenderer instance.\n * Destroys all subsystems and releases references.\n *\n * @returns {void}\n */\n destroy() {\n // Destroy all subsystems\n if (this.pdfRenderer) {\n this.pdfRenderer.destroy();\n }\n\n if (this.layerManager) {\n this.layerManager.destroy();\n }\n\n if (this.timelineSync) {\n this.timelineSync.destroy();\n }\n\n // Clear all references\n this.pdfRenderer = null;\n this.layerManager = null;\n this.timelineSync = 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","LayerManager","TimelineSync","time","err","url","result","pageNum","scale","annotations","timestamp"],"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';\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 * 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","newConfig","deepMerge"],"mappings":"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"}
package/dist/index2.js CHANGED
@@ -1,17 +1,19 @@
1
- import { PDFRenderer as r } from "./index3.js";
2
- import { LayerManager as n } from "./index4.js";
3
- import { TimelineSync as s } from "./index5.js";
4
- class c {
1
+ import { PDFRenderer as n } from "./index3.js";
2
+ import { TimelineSync as s } from "./index4.js";
3
+ import { StrokeRenderer as i } from "./index5.js";
4
+ import { deepMerge as o } from "./index6.js";
5
+ class u {
5
6
  /**
6
7
  * Create AnnotationRenderer instance
7
8
  *
8
9
  * @param {Object} config - Configuration object
9
- * @param {HTMLElement} config.container - DOM element for layer rendering
10
+ * @param {HTMLElement} config.container - DOM element for annotation canvas
10
11
  * @param {HTMLCanvasElement} config.canvasElement - Canvas element for PDF rendering
11
12
  * @param {string} [config.pdfUrl] - PDF URL to load immediately
12
13
  * @param {number} [config.initialPage=1] - Initial page number
13
14
  * @param {number} [config.initialScale=1.0] - Initial scale factor
14
15
  * @param {Array} [config.annotations=[]] - Initial annotation data
16
+ * @param {Object} [config.strokeConfig] - StrokeRenderer configuration
15
17
  * @throws {Error} If config is invalid or required elements are missing
16
18
  */
17
19
  constructor(e) {
@@ -21,42 +23,36 @@ class c {
21
23
  throw new Error("AnnotationRenderer: config.container must be a valid DOM element");
22
24
  if (!e.canvasElement || !(e.canvasElement instanceof HTMLCanvasElement))
23
25
  throw new Error("AnnotationRenderer: config.canvasElement must be a valid canvas element");
24
- this.config = e, this.canvasElement = e.canvasElement, this.container = e.container, this.pdfRenderer = new r(), this.layerManager = new n(e.container, {
25
- width: 1,
26
- height: 1,
27
- scale: 1
28
- }), this.timelineSync = new s(), 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) => {
29
- this.layerManager.updateTimeline(t);
26
+ this.config = e, this.canvasElement = e.canvasElement, this.container = e.container, this.pdfRenderer = new n(), this.strokeCanvas = this._createStrokeCanvas(), this.strokeRenderer = new i(this.strokeCanvas, e.strokeConfig || {}), this.timelineSync = new s(), 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) => {
27
+ this.strokeRenderer.render(t);
30
28
  }), e.pdfUrl && this.loadPDF(e.pdfUrl).catch((t) => {
31
29
  console.error("AnnotationRenderer: Failed to auto-load PDF:", t);
32
30
  });
33
31
  }
32
+ /**
33
+ * Create stroke canvas overlay
34
+ *
35
+ * @private
36
+ * @returns {HTMLCanvasElement} Stroke canvas element
37
+ */
38
+ _createStrokeCanvas() {
39
+ const e = document.createElement("canvas");
40
+ 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;
41
+ }
34
42
  /**
35
43
  * Load PDF document from URL
36
44
  *
37
45
  * @param {string} url - URL or path to PDF file
38
46
  * @returns {Promise<Object>} Load result with success status and page count
39
- * @returns {boolean} return.success - Whether loading succeeded
40
- * @returns {number} [return.pageCount] - Number of pages if successful
41
- * @returns {string} [return.error] - Error message if failed
42
47
  */
43
48
  async loadPDF(e) {
44
49
  try {
45
50
  if (!e || typeof e != "string")
46
- return {
47
- success: !1,
48
- error: "Invalid PDF URL provided"
49
- };
51
+ return { success: !1, error: "Invalid PDF URL provided" };
50
52
  const t = await this.pdfRenderer.loadDocument(e);
51
- return t.success ? (this.pdfUrl = e, this.pageCount = t.pageCount, {
52
- success: !0,
53
- pageCount: t.pageCount
54
- }) : t;
53
+ return t.success ? (this.pdfUrl = e, this.pageCount = t.pageCount, { success: !0, pageCount: t.pageCount }) : t;
55
54
  } catch (t) {
56
- return console.error("AnnotationRenderer.loadPDF: Error loading PDF:", t), {
57
- success: !1,
58
- error: `Failed to load PDF: ${t.message}`
59
- };
55
+ return console.error("AnnotationRenderer.loadPDF: Error loading PDF:", t), { success: !1, error: `Failed to load PDF: ${t.message}` };
60
56
  }
61
57
  }
62
58
  /**
@@ -64,37 +60,27 @@ class c {
64
60
  *
65
61
  * @param {number} pageNum - Page number (1-indexed)
66
62
  * @returns {Promise<Object>} Render result with viewport information
67
- * @returns {boolean} return.success - Whether rendering succeeded
68
- * @returns {Object} [return.viewport] - Viewport dimensions if successful
69
- * @returns {string} [return.error] - Error message if failed
70
63
  */
71
64
  async setPage(e) {
72
65
  try {
73
66
  if (typeof e != "number" || e < 1)
74
- return {
75
- success: !1,
76
- error: "Invalid page number"
77
- };
67
+ return { success: !1, error: "Invalid page number" };
78
68
  if (this.pageCount > 0 && e > this.pageCount)
79
- return {
80
- success: !1,
81
- error: `Page ${e} exceeds document page count (${this.pageCount})`
82
- };
69
+ return { success: !1, error: `Page ${e} exceeds document page count (${this.pageCount})` };
83
70
  this.pdfRenderer.cancelRender();
84
71
  const t = await this.pdfRenderer.renderPage(
85
72
  e,
86
73
  this.canvasElement,
87
74
  this.currentScale
88
75
  );
89
- return t.success ? (this.currentPage = e, this.currentViewport = t.viewport, this.layerManager.setAnnotations(this.annotations, e), this.layerManager.setViewport(t.viewport), {
90
- success: !0,
91
- viewport: t.viewport
92
- }) : t;
76
+ if (t.success) {
77
+ this.currentPage = e, this.currentViewport = t.viewport, this.strokeRenderer.setViewport(t.viewport.width, t.viewport.height), this.strokeRenderer.setAnnotations(this.annotations, e);
78
+ const r = this.timelineSync.getCurrentTime();
79
+ return this.strokeRenderer.render(r), { success: !0, viewport: t.viewport };
80
+ }
81
+ return t;
93
82
  } catch (t) {
94
- return console.error("AnnotationRenderer.setPage: Error rendering page:", t), {
95
- success: !1,
96
- error: `Failed to render page: ${t.message}`
97
- };
83
+ return console.error("AnnotationRenderer.setPage: Error rendering page:", t), { success: !1, error: `Failed to render page: ${t.message}` };
98
84
  }
99
85
  }
100
86
  /**
@@ -102,37 +88,40 @@ class c {
102
88
  *
103
89
  * @param {number} scale - Scale factor (e.g., 1.0, 1.5, 2.0)
104
90
  * @returns {Promise<Object>} Render result with viewport information
105
- * @returns {boolean} return.success - Whether rendering succeeded
106
- * @returns {Object} [return.viewport] - Viewport dimensions if successful
107
- * @returns {string} [return.error] - Error message if failed
108
91
  */
109
92
  async setScale(e) {
110
93
  try {
111
- return typeof e != "number" || e <= 0 ? {
112
- success: !1,
113
- error: "Invalid scale value (must be positive number)"
114
- } : (this.currentScale = e, await this.setPage(this.currentPage));
94
+ return typeof e != "number" || e <= 0 ? { success: !1, error: "Invalid scale value (must be positive number)" } : (this.currentScale = e, await this.setPage(this.currentPage));
115
95
  } catch (t) {
116
- return console.error("AnnotationRenderer.setScale: Error changing scale:", t), {
117
- success: !1,
118
- error: `Failed to change scale: ${t.message}`
119
- };
96
+ return console.error("AnnotationRenderer.setScale: Error changing scale:", t), { success: !1, error: `Failed to change scale: ${t.message}` };
120
97
  }
121
98
  }
122
99
  /**
123
100
  * Update annotation data for rendering
124
101
  *
125
102
  * @param {Array} annotations - Complete annotation array (all pages, all types)
126
- * @returns {void}
127
103
  */
128
104
  setAnnotations(e) {
129
- Array.isArray(e) || (console.warn("AnnotationRenderer.setAnnotations: annotations must be an array"), e = []), this.annotations = e, this.layerManager.setAnnotations(e, this.currentPage);
105
+ Array.isArray(e) || (console.warn("AnnotationRenderer.setAnnotations: annotations must be an array"), e = []), this.annotations = e, this.strokeRenderer.setAnnotations(e, this.currentPage);
106
+ const t = this.timelineSync.getCurrentTime();
107
+ this.strokeRenderer.render(t);
108
+ }
109
+ /**
110
+ * Set pre-converted strokes directly
111
+ *
112
+ * Bypasses annotation conversion, useful for stroke commands from backend.
113
+ *
114
+ * @param {Array} strokes - Array of stroke command objects
115
+ */
116
+ setStrokes(e) {
117
+ this.strokeRenderer.setStrokes(e);
118
+ const t = this.timelineSync.getCurrentTime();
119
+ this.strokeRenderer.render(t);
130
120
  }
131
121
  /**
132
122
  * Update timeline position for animation
133
123
  *
134
124
  * @param {number} timestamp - Current timeline position in seconds
135
- * @returns {void}
136
125
  */
137
126
  setTime(e) {
138
127
  if (typeof e != "number") {
@@ -141,17 +130,25 @@ class c {
141
130
  }
142
131
  this.timelineSync.setTime(e);
143
132
  }
133
+ /**
134
+ * Update stroke rendering configuration at runtime
135
+ *
136
+ * Merges new config with existing and re-renders annotations.
137
+ * Used for live preview of pen style changes.
138
+ *
139
+ * @param {Object} newConfig - New stroke configuration to merge
140
+ */
141
+ updateStrokeConfig(e) {
142
+ if (!e || typeof e != "object")
143
+ return;
144
+ this.strokeRenderer.config = o(this.strokeRenderer.config, e), this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);
145
+ const t = this.timelineSync.getCurrentTime();
146
+ this.strokeRenderer.render(t);
147
+ }
144
148
  /**
145
149
  * Get current engine state snapshot
146
150
  *
147
151
  * @returns {Object} Current state
148
- * @returns {number} return.page - Current page number
149
- * @returns {number} return.scale - Current scale factor
150
- * @returns {Array} return.annotations - Current annotation array
151
- * @returns {number} return.pageCount - Total page count
152
- * @returns {number} return.time - Current timeline position
153
- * @returns {Object|null} return.viewport - Current viewport dimensions
154
- * @returns {string|null} return.pdfUrl - Current PDF URL
155
152
  */
156
153
  getState() {
157
154
  return {
@@ -166,17 +163,12 @@ class c {
166
163
  }
167
164
  /**
168
165
  * Clean up all resources and subsystems
169
- *
170
- * Call before removing AnnotationRenderer instance.
171
- * Destroys all subsystems and releases references.
172
- *
173
- * @returns {void}
174
166
  */
175
167
  destroy() {
176
- this.pdfRenderer && this.pdfRenderer.destroy(), this.layerManager && this.layerManager.destroy(), this.timelineSync && this.timelineSync.destroy(), this.pdfRenderer = null, this.layerManager = null, this.timelineSync = 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;
168
+ 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;
177
169
  }
178
170
  }
179
171
  export {
180
- c as AnnotationRenderer
172
+ u as AnnotationRenderer
181
173
  };
182
174
  //# sourceMappingURL=index2.js.map