web-annotation-renderer 0.6.4 → 0.7.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 (112) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +62 -61
  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 +160 -13
  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 -50
  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 +48 -155
  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 +150 -34
  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 +32 -65
  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 +66 -33
  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 +35 -77
  33. package/dist/index16.js.map +1 -1
  34. package/dist/index17.cjs +1 -1
  35. package/dist/index17.cjs.map +1 -1
  36. package/dist/index17.js +53 -28
  37. package/dist/index17.js.map +1 -1
  38. package/dist/index18.cjs +1 -1
  39. package/dist/index18.cjs.map +1 -1
  40. package/dist/index18.js +28 -22
  41. package/dist/index18.js.map +1 -1
  42. package/dist/index19.cjs +1 -1
  43. package/dist/index19.cjs.map +1 -1
  44. package/dist/index19.js +22 -117
  45. package/dist/index19.js.map +1 -1
  46. package/dist/index2.cjs +1 -1
  47. package/dist/index2.cjs.map +1 -1
  48. package/dist/index2.js +94 -98
  49. package/dist/index2.js.map +1 -1
  50. package/dist/index20.cjs +1 -1
  51. package/dist/index20.cjs.map +1 -1
  52. package/dist/index20.js +137 -100
  53. package/dist/index20.js.map +1 -1
  54. package/dist/index21.cjs +1 -1
  55. package/dist/index21.cjs.map +1 -1
  56. package/dist/index21.js +34 -76
  57. package/dist/index21.js.map +1 -1
  58. package/dist/index22.cjs +1 -1
  59. package/dist/index22.cjs.map +1 -1
  60. package/dist/index22.js +35 -139
  61. package/dist/index22.js.map +1 -1
  62. package/dist/index23.cjs +1 -1
  63. package/dist/index23.cjs.map +1 -1
  64. package/dist/index23.js +37 -37
  65. package/dist/index23.js.map +1 -1
  66. package/dist/index24.cjs +1 -1
  67. package/dist/index24.cjs.map +1 -1
  68. package/dist/index24.js +69 -37
  69. package/dist/index24.js.map +1 -1
  70. package/dist/index25.cjs +1 -1
  71. package/dist/index25.cjs.map +1 -1
  72. package/dist/index25.js +40 -38
  73. package/dist/index25.js.map +1 -1
  74. package/dist/index26.cjs +1 -1
  75. package/dist/index26.cjs.map +1 -1
  76. package/dist/index26.js +4 -39
  77. package/dist/index26.js.map +1 -1
  78. package/dist/index27.cjs +1 -1
  79. package/dist/index27.js +4 -4
  80. package/dist/index28.cjs +1 -1
  81. package/dist/index28.cjs.map +1 -1
  82. package/dist/index28.js +71 -5
  83. package/dist/index28.js.map +1 -1
  84. package/dist/index29.cjs +1 -1
  85. package/dist/index29.cjs.map +1 -1
  86. package/dist/index29.js +24 -69
  87. package/dist/index29.js.map +1 -1
  88. package/dist/index3.cjs +1 -1
  89. package/dist/index3.cjs.map +1 -1
  90. package/dist/index3.js +31 -31
  91. package/dist/index3.js.map +1 -1
  92. package/dist/index5.cjs +1 -1
  93. package/dist/index5.cjs.map +1 -1
  94. package/dist/index5.js +237 -190
  95. package/dist/index5.js.map +1 -1
  96. package/dist/index6.cjs +1 -1
  97. package/dist/index6.cjs.map +1 -1
  98. package/dist/index6.js +37 -19
  99. package/dist/index6.js.map +1 -1
  100. package/dist/index7.cjs +1 -1
  101. package/dist/index7.cjs.map +1 -1
  102. package/dist/index7.js +11 -17
  103. package/dist/index7.js.map +1 -1
  104. package/dist/index8.cjs +1 -1
  105. package/dist/index8.cjs.map +1 -1
  106. package/dist/index8.js +16 -125
  107. package/dist/index8.js.map +1 -1
  108. package/dist/index9.cjs +1 -1
  109. package/dist/index9.cjs.map +1 -1
  110. package/dist/index9.js +118 -201
  111. package/dist/index9.js.map +1 -1
  112. package/package.json +6 -3
@@ -1 +1 @@
1
- {"version":3,"file":"index18.cjs","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":"gFAwBO,SAASA,EAAaC,EAAYC,EAAO,CAC9C,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,QAASC,CAAU,EAAKL,EAChD,GAAI,CAACK,GAAcA,EAAW,SAAW,EAAG,MAAO,CAAA,EAEnD,MAAMC,EAAgBF,EAAMD,EAC5B,GAAIG,GAAiB,EAAG,MAAO,CAAA,EAG/B,MAAMC,EAAkBF,EAAW,OACjC,CAACG,EAAKC,IAAM,KAAK,IAAID,GAAMC,EAAE,YAAc,IAAMA,EAAE,UAAY,GAAI,EACnE,CACJ,GAAO,EACCC,EAAYJ,EAAgBC,EAElC,OAAOF,EACJ,OAAQM,GAAQA,EAAI,QAAUA,EAAI,OAAO,QAAU,CAAC,EACpD,IAAI,CAACA,EAAKC,KAAO,CAChB,GAAI,GAAGV,CAAE,IAAIU,CAAC,GACd,OAAQD,EAAI,OACZ,MAAOR,GAASQ,EAAI,YAAc,GAAKD,EACvC,IAAK,KAAK,IACRP,IAAUQ,EAAI,YAAc,IAAMA,EAAI,UAAY,KAAQD,EAC1DN,CACR,EACM,MAAOO,EAAI,OAASV,EAAM,OAAS,UACnC,MAAOU,EAAI,OAASV,EAAM,OAAS,EACnC,QAASA,EAAM,SAAW,OAChC,EAAM,CACN"}
1
+ {"version":3,"file":"index18.cjs","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 with hand-drawn style.\n *\n * @module converters/circle\n */\n\nimport { roughEllipse } from '../rough/roughPathExtractor.js';\nimport { buildRoughOptions, resolveColor } from './_shared.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts a circle annotation to stroke commands\n *\n * Generates an ellipse path that renders progressively around the perimeter.\n * Uses RoughJS for hand-drawn circle style.\n *\n * Coordinate convention (Convention 1, see spec R6): `cx` / `rx` are\n * normalized as fractions of `viewport.width`; `cy` / `ry` are normalized\n * as fractions of `viewport.height`. This matches the convention used by\n * `quad.x` / `quad.w` (highlight, underline) and lets the same `(x, y)`\n * pair be passed verbatim to the renderer's page-coord pipeline.\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 (fraction of viewport.width, 0-1)\n * @param {number} annotation.cy - Center y position (fraction of viewport.height, 0-1)\n * @param {number} annotation.rx - Horizontal radius. Normalized as a fraction of\n * viewport.width (matches the convention used for `quad.x` / `quad.w`). For\n * an on-screen circle, set `ry = rx * (viewport.width / viewport.height)`.\n * @param {number} annotation.ry - Vertical radius. Normalized as a fraction of\n * viewport.height (matches the convention used for `quad.y` / `quad.h`). See\n * `rx` above for the conversion needed to produce a visually round circle.\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 * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\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 const roughOptions = buildRoughOptions(style, id, {\n roughness: 1.0,\n bowing: 1.0,\n });\n\n const roughPoints = roughEllipse(\n cx * SCALE,\n cy * SCALE,\n rx * 2 * SCALE,\n ry * 2 * SCALE,\n roughOptions\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n return [{\n id,\n points,\n start,\n end,\n color: resolveColor(style, 'rgba(255, 165, 0, 0.8)'),\n width: style.width || 3,\n lineCap: style.lineCap || 'round'\n }];\n}\n\nexport default circleToStrokes;\n"],"names":["SCALE","circleToStrokes","annotation","style","id","start","end","cx","cy","rx","ry","roughOptions","buildRoughOptions","points","roughEllipse","px","py","resolveColor"],"mappings":"wKAYMA,EAAQ,IAmCP,SAASC,EAAgBC,EAAYC,EAAO,CACjD,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,GAAAC,EAAI,GAAAC,EAAI,GAAAC,EAAI,GAAAC,CAAE,EAAKR,EAE3C,GAAI,OAAOK,GAAO,UAAY,OAAOC,GAAO,UACxC,OAAOC,GAAO,UAAY,OAAOC,GAAO,SAC1C,MAAO,CAAA,EAGT,MAAMC,EAAeC,EAAAA,kBAAkBT,EAAOC,EAAI,CAChD,UAAW,EACX,OAAQ,CACZ,CAAG,EAUKS,EARcC,EAAAA,aAClBP,EAAKP,EACLQ,EAAKR,EACLS,EAAK,EAAIT,EACTU,EAAK,EAAIV,EACTW,CACJ,EAE6B,IAAI,CAAC,CAACI,EAAIC,CAAE,IAAM,CAACD,EAAKf,EAAOgB,EAAKhB,CAAK,CAAC,EAErE,MAAO,CAAC,CACN,GAAAI,EACA,OAAAS,EACA,MAAAR,EACA,IAAAC,EACA,MAAOW,EAAAA,aAAad,EAAO,wBAAwB,EACnD,MAAOA,EAAM,OAAS,EACtB,QAASA,EAAM,SAAW,OAC9B,CAAG,CACH"}
package/dist/index18.js CHANGED
@@ -1,26 +1,32 @@
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
- }));
1
+ import { roughEllipse as a } from "./index28.js";
2
+ import { buildRoughOptions as b, resolveColor as d } from "./index29.js";
3
+ const o = 1e3;
4
+ function x(p, r) {
5
+ const { id: n, start: s, end: c, cx: t, cy: e, rx: i, ry: u } = p;
6
+ if (typeof t != "number" || typeof e != "number" || typeof i != "number" || typeof u != "number")
7
+ return [];
8
+ const f = b(r, n, {
9
+ roughness: 1,
10
+ bowing: 1
11
+ }), m = a(
12
+ t * o,
13
+ e * o,
14
+ i * 2 * o,
15
+ u * 2 * o,
16
+ f
17
+ ).map(([g, h]) => [g / o, h / o]);
18
+ return [{
19
+ id: n,
20
+ points: m,
21
+ start: s,
22
+ end: c,
23
+ color: d(r, "rgba(255, 165, 0, 0.8)"),
24
+ width: r.width || 3,
25
+ lineCap: r.lineCap || "round"
26
+ }];
22
27
  }
23
28
  export {
24
- l as inkToStrokes
29
+ x as circleToStrokes,
30
+ x as default
25
31
  };
26
32
  //# sourceMappingURL=index18.js.map
@@ -1 +1 @@
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;"}
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 with hand-drawn style.\n *\n * @module converters/circle\n */\n\nimport { roughEllipse } from '../rough/roughPathExtractor.js';\nimport { buildRoughOptions, resolveColor } from './_shared.js';\n\nconst SCALE = 1000;\n\n/**\n * Converts a circle annotation to stroke commands\n *\n * Generates an ellipse path that renders progressively around the perimeter.\n * Uses RoughJS for hand-drawn circle style.\n *\n * Coordinate convention (Convention 1, see spec R6): `cx` / `rx` are\n * normalized as fractions of `viewport.width`; `cy` / `ry` are normalized\n * as fractions of `viewport.height`. This matches the convention used by\n * `quad.x` / `quad.w` (highlight, underline) and lets the same `(x, y)`\n * pair be passed verbatim to the renderer's page-coord pipeline.\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 (fraction of viewport.width, 0-1)\n * @param {number} annotation.cy - Center y position (fraction of viewport.height, 0-1)\n * @param {number} annotation.rx - Horizontal radius. Normalized as a fraction of\n * viewport.width (matches the convention used for `quad.x` / `quad.w`). For\n * an on-screen circle, set `ry = rx * (viewport.width / viewport.height)`.\n * @param {number} annotation.ry - Vertical radius. Normalized as a fraction of\n * viewport.height (matches the convention used for `quad.y` / `quad.h`). See\n * `rx` above for the conversion needed to produce a visually round circle.\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 * @param {number} [style.roughness=1.0] - Hand-drawn roughness\n * @param {number} [style.bowing=1.0] - Line curvature\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 const roughOptions = buildRoughOptions(style, id, {\n roughness: 1.0,\n bowing: 1.0,\n });\n\n const roughPoints = roughEllipse(\n cx * SCALE,\n cy * SCALE,\n rx * 2 * SCALE,\n ry * 2 * SCALE,\n roughOptions\n );\n\n const points = roughPoints.map(([px, py]) => [px / SCALE, py / SCALE]);\n\n return [{\n id,\n points,\n start,\n end,\n color: resolveColor(style, 'rgba(255, 165, 0, 0.8)'),\n width: style.width || 3,\n lineCap: style.lineCap || 'round'\n }];\n}\n\nexport default circleToStrokes;\n"],"names":["SCALE","circleToStrokes","annotation","style","id","start","end","cx","cy","rx","ry","roughOptions","buildRoughOptions","points","roughEllipse","px","py","resolveColor"],"mappings":";;AAYA,MAAMA,IAAQ;AAmCP,SAASC,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;AAGT,QAAMC,IAAeC,EAAkBT,GAAOC,GAAI;AAAA,IAChD,WAAW;AAAA,IACX,QAAQ;AAAA,EACZ,CAAG,GAUKS,IARcC;AAAA,IAClBP,IAAKP;AAAA,IACLQ,IAAKR;AAAA,IACLS,IAAK,IAAIT;AAAA,IACTU,IAAK,IAAIV;AAAA,IACTW;AAAA,EACJ,EAE6B,IAAI,CAAC,CAACI,GAAIC,CAAE,MAAM,CAACD,IAAKf,GAAOgB,IAAKhB,CAAK,CAAC;AAErE,SAAO,CAAC;AAAA,IACN,IAAAI;AAAA,IACA,QAAAS;AAAA,IACA,OAAAR;AAAA,IACA,KAAAC;AAAA,IACA,OAAOW,EAAad,GAAO,wBAAwB;AAAA,IACnD,OAAOA,EAAM,SAAS;AAAA,IACtB,SAASA,EAAM,WAAW;AAAA,EAC9B,CAAG;AACH;"}
package/dist/index19.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const n=require("./index20.cjs");class o{constructor(t,s){this.canvas=t,this.dimensions={...s},this.ctx=null,this.strokeDrawer=null,this.strokeCommands=[],this.currentTime=0,this.isDestroyed=!1,this._setupCanvas()}_setupCanvas(){const t=window.devicePixelRatio||1,{width:s,height:e}=this.dimensions;this.canvas.width=Math.round(s*t),this.canvas.height=Math.round(e*t),this.canvas.style.width=`${s}px`,this.canvas.style.height=`${e}px`,this.ctx=this.canvas.getContext("2d"),this.ctx.setTransform(t,0,0,t,0,0),this.strokeDrawer=new n.default(this.ctx,this.dimensions)}setStrokeCommands(t){this.isDestroyed||(this.strokeCommands=t||[],this.strokeCommands.sort((s,e)=>{const r=s.start??0,i=e.start??0;return r-i}))}setTime(t){this.isDestroyed||(this.currentTime=t)}setDimensions(t){this.isDestroyed||(this.dimensions={...t},this._setupCanvas())}render(){if(!(this.isDestroyed||!this.ctx)){this.strokeDrawer.clear();for(const t of this.strokeCommands){const s=t.start??0,e=t.end??s+1;if(this.currentTime<s)continue;const r=this._calculateProgress(s,e);this.strokeDrawer.drawStroke(t,r)}}}_calculateProgress(t,s){if(this.currentTime>=s)return 1;const e=s-t;if(e<=0)return 1;const r=this.currentTime-t;return Math.max(0,Math.min(1,r/e))}clear(){this.isDestroyed||!this.strokeDrawer||this.strokeDrawer.clear()}getVisibleStrokeCount(){let t=0;for(const s of this.strokeCommands){const e=s.start??0;this.currentTime>=e&&t++}return t}destroy(){this.isDestroyed||(this.strokeCommands=[],this.strokeDrawer=null,this.ctx=null,this.canvas=null,this.isDestroyed=!0)}}exports.default=o;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function l(d,i){const{id:c,start:n,end:r,strokes:o}=d;if(!o||o.length===0)return[];const a=r-n;if(a<=0)return[];const f=o.reduce((t,e)=>Math.max(t,(e.timeOffset||0)+(e.duration||.5)),0)||1,s=a/f;return o.filter(t=>t.points&&t.points.length>=2).map((t,e)=>({id:`${c}-${e}`,points:t.points,start:n+(t.timeOffset||0)*s,end:Math.min(n+((t.timeOffset||0)+(t.duration||.5))*s,r),color:t.color||i.color,width:t.width||i.width||2,lineCap:i.lineCap||"round"}))}exports.inkToStrokes=l;
2
2
  //# sourceMappingURL=index19.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index19.cjs","sources":["../src/pen/GradualRenderer.js"],"sourcesContent":["import StrokeDrawer from './StrokeDrawer.js';\n\n/**\n * GradualRenderer - Progressive stroke rendering synced to timeline\n *\n * Renders stroke commands with progressive reveal based on current\n * audio/video timeline position.\n *\n * Features:\n * - Progressive stroke reveal synced to audio timeline\n * - High-DPI canvas support for crisp rendering\n * - Efficient single-pass render per timeline update\n * - Accepts timing in seconds (start/end fields)\n *\n * @example\n * const renderer = new GradualRenderer(canvas, { width: 800, height: 600 });\n * renderer.setStrokeCommands(commands);\n * renderer.setTime(1.5); // seconds\n * renderer.render();\n */\nclass GradualRenderer {\n /**\n * Creates a new GradualRenderer instance\n *\n * @param {HTMLCanvasElement} canvas - Canvas element for rendering\n * @param {Object} pdfDimensions - PDF page dimensions\n * @param {number} pdfDimensions.width - Page width in pixels\n * @param {number} pdfDimensions.height - Page height in pixels\n */\n constructor(canvas, pdfDimensions) {\n this.canvas = canvas;\n this.dimensions = { ...pdfDimensions };\n this.ctx = null;\n this.strokeDrawer = null;\n this.strokeCommands = [];\n this.currentTime = 0; // seconds\n this.isDestroyed = false;\n\n this._setupCanvas();\n }\n\n /**\n * Configures canvas for high-DPI rendering\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n const { width, height } = this.dimensions;\n\n // Set canvas buffer resolution (high-res)\n this.canvas.width = Math.round(width * dpr);\n this.canvas.height = Math.round(height * dpr);\n\n // Set canvas display size (CSS)\n this.canvas.style.width = `${width}px`;\n this.canvas.style.height = `${height}px`;\n\n // Get context and scale for DPR\n this.ctx = this.canvas.getContext('2d');\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n // Create stroke drawer\n this.strokeDrawer = new StrokeDrawer(this.ctx, this.dimensions);\n }\n\n /**\n * Sets the stroke commands to render\n *\n * @param {Array} commands - Array of stroke command objects\n * @param {string} commands[].id - Unique stroke identifier\n * @param {Array} commands[].points - [[x, y], ...] normalized coordinates\n * @param {string} commands[].color - Stroke color\n * @param {number} commands[].width - Stroke width in pixels\n * @param {number} commands[].start - Start time in seconds\n * @param {number} commands[].end - End time in seconds\n */\n setStrokeCommands(commands) {\n if (this.isDestroyed) return;\n\n this.strokeCommands = commands || [];\n\n // Sort by start time for efficient rendering\n this.strokeCommands.sort((a, b) => {\n const startA = a.start ?? 0;\n const startB = b.start ?? 0;\n return startA - startB;\n });\n }\n\n /**\n * Sets the current timeline position\n *\n * @param {number} time - Current time in seconds\n */\n setTime(time) {\n if (this.isDestroyed) return;\n this.currentTime = time;\n }\n\n /**\n * Updates dimensions when viewport changes\n *\n * @param {Object} dimensions - New dimensions\n * @param {number} dimensions.width - Width in pixels\n * @param {number} dimensions.height - Height in pixels\n */\n setDimensions(dimensions) {\n if (this.isDestroyed) return;\n\n this.dimensions = { ...dimensions };\n this._setupCanvas();\n }\n\n /**\n * Renders all visible strokes at current timeline position\n *\n * Called once per timeline update. Clears canvas and redraws\n * all strokes with appropriate progress.\n */\n render() {\n if (this.isDestroyed || !this.ctx) return;\n\n // Clear canvas\n this.strokeDrawer.clear();\n\n // Draw each stroke based on timing\n for (const stroke of this.strokeCommands) {\n const start = stroke.start ?? 0;\n const end = stroke.end ?? start + 1;\n\n // Skip strokes that haven't started\n if (this.currentTime < start) {\n continue;\n }\n\n // Calculate progress\n const progress = this._calculateProgress(start, end);\n\n // Draw stroke with progress\n this.strokeDrawer.drawStroke(stroke, progress);\n }\n }\n\n /**\n * Calculates stroke progress based on timing\n *\n * @private\n * @param {number} start - Stroke start time in seconds\n * @param {number} end - Stroke end time in seconds\n * @returns {number} Progress from 0 to 1\n */\n _calculateProgress(start, end) {\n if (this.currentTime >= end) {\n return 1.0; // Fully visible\n }\n\n const duration = end - start;\n if (duration <= 0) return 1.0;\n\n const elapsed = this.currentTime - start;\n return Math.max(0, Math.min(1, elapsed / duration));\n }\n\n /**\n * Clears the canvas\n */\n clear() {\n if (this.isDestroyed || !this.strokeDrawer) return;\n this.strokeDrawer.clear();\n }\n\n /**\n * Gets visible stroke count at current time\n *\n * @returns {number} Number of visible strokes\n */\n getVisibleStrokeCount() {\n let count = 0;\n for (const stroke of this.strokeCommands) {\n const start = stroke.start ?? 0;\n if (this.currentTime >= start) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * Destroys the renderer and releases resources\n */\n destroy() {\n if (this.isDestroyed) return;\n\n this.strokeCommands = [];\n this.strokeDrawer = null;\n this.ctx = null;\n this.canvas = null;\n this.isDestroyed = true;\n }\n}\n\nexport default GradualRenderer;\n"],"names":["GradualRenderer","canvas","pdfDimensions","dpr","width","height","StrokeDrawer","commands","a","b","startA","startB","time","dimensions","stroke","start","end","progress","duration","elapsed","count"],"mappings":"6IAoBA,MAAMA,CAAgB,CASpB,YAAYC,EAAQC,EAAe,CACjC,KAAK,OAASD,EACd,KAAK,WAAa,CAAE,GAAGC,CAAa,EACpC,KAAK,IAAM,KACX,KAAK,aAAe,KACpB,KAAK,eAAiB,CAAA,EACtB,KAAK,YAAc,EACnB,KAAK,YAAc,GAEnB,KAAK,aAAY,CACnB,CAOA,cAAe,CACb,MAAMC,EAAM,OAAO,kBAAoB,EACjC,CAAE,MAAAC,EAAO,OAAAC,CAAM,EAAK,KAAK,WAG/B,KAAK,OAAO,MAAQ,KAAK,MAAMD,EAAQD,CAAG,EAC1C,KAAK,OAAO,OAAS,KAAK,MAAME,EAASF,CAAG,EAG5C,KAAK,OAAO,MAAM,MAAQ,GAAGC,CAAK,KAClC,KAAK,OAAO,MAAM,OAAS,GAAGC,CAAM,KAGpC,KAAK,IAAM,KAAK,OAAO,WAAW,IAAI,EACtC,KAAK,IAAI,aAAaF,EAAK,EAAG,EAAGA,EAAK,EAAG,CAAC,EAG1C,KAAK,aAAe,IAAIG,EAAAA,QAAa,KAAK,IAAK,KAAK,UAAU,CAChE,CAaA,kBAAkBC,EAAU,CACtB,KAAK,cAET,KAAK,eAAiBA,GAAY,CAAA,EAGlC,KAAK,eAAe,KAAK,CAACC,EAAGC,IAAM,CACjC,MAAMC,EAASF,EAAE,OAAS,EACpBG,EAASF,EAAE,OAAS,EAC1B,OAAOC,EAASC,CAClB,CAAC,EACH,CAOA,QAAQC,EAAM,CACR,KAAK,cACT,KAAK,YAAcA,EACrB,CASA,cAAcC,EAAY,CACpB,KAAK,cAET,KAAK,WAAa,CAAE,GAAGA,CAAU,EACjC,KAAK,aAAY,EACnB,CAQA,QAAS,CACP,GAAI,OAAK,aAAe,CAAC,KAAK,KAG9B,MAAK,aAAa,MAAK,EAGvB,UAAWC,KAAU,KAAK,eAAgB,CACxC,MAAMC,EAAQD,EAAO,OAAS,EACxBE,EAAMF,EAAO,KAAOC,EAAQ,EAGlC,GAAI,KAAK,YAAcA,EACrB,SAIF,MAAME,EAAW,KAAK,mBAAmBF,EAAOC,CAAG,EAGnD,KAAK,aAAa,WAAWF,EAAQG,CAAQ,CAC/C,EACF,CAUA,mBAAmBF,EAAOC,EAAK,CAC7B,GAAI,KAAK,aAAeA,EACtB,MAAO,GAGT,MAAME,EAAWF,EAAMD,EACvB,GAAIG,GAAY,EAAG,MAAO,GAE1B,MAAMC,EAAU,KAAK,YAAcJ,EACnC,OAAO,KAAK,IAAI,EAAG,KAAK,IAAI,EAAGI,EAAUD,CAAQ,CAAC,CACpD,CAKA,OAAQ,CACF,KAAK,aAAe,CAAC,KAAK,cAC9B,KAAK,aAAa,MAAK,CACzB,CAOA,uBAAwB,CACtB,IAAIE,EAAQ,EACZ,UAAWN,KAAU,KAAK,eAAgB,CACxC,MAAMC,EAAQD,EAAO,OAAS,EAC1B,KAAK,aAAeC,GACtBK,GAEJ,CACA,OAAOA,CACT,CAKA,SAAU,CACJ,KAAK,cAET,KAAK,eAAiB,CAAA,EACtB,KAAK,aAAe,KACpB,KAAK,IAAM,KACX,KAAK,OAAS,KACd,KAAK,YAAc,GACrB,CACF"}
1
+ {"version":3,"file":"index19.cjs","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 * Color/width fall back to the resolved `style` (which itself draws from\n * `DEFAULT_CONFIG.ink` in `config/defaults.js`); per-substroke `sub.color`\n * and `sub.width` may override on a stroke-by-stroke basis.\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,\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":"gFA4BO,SAASA,EAAaC,EAAYC,EAAO,CAC9C,KAAM,CAAE,GAAAC,EAAI,MAAAC,EAAO,IAAAC,EAAK,QAASC,CAAU,EAAKL,EAChD,GAAI,CAACK,GAAcA,EAAW,SAAW,EAAG,MAAO,CAAA,EAEnD,MAAMC,EAAgBF,EAAMD,EAC5B,GAAIG,GAAiB,EAAG,MAAO,CAAA,EAG/B,MAAMC,EAAkBF,EAAW,OACjC,CAACG,EAAKC,IAAM,KAAK,IAAID,GAAMC,EAAE,YAAc,IAAMA,EAAE,UAAY,GAAI,EACnE,CACJ,GAAO,EACCC,EAAYJ,EAAgBC,EAElC,OAAOF,EACJ,OAAQM,GAAQA,EAAI,QAAUA,EAAI,OAAO,QAAU,CAAC,EACpD,IAAI,CAACA,EAAKC,KAAO,CAChB,GAAI,GAAGV,CAAE,IAAIU,CAAC,GACd,OAAQD,EAAI,OACZ,MAAOR,GAASQ,EAAI,YAAc,GAAKD,EACvC,IAAK,KAAK,IACRP,IAAUQ,EAAI,YAAc,IAAMA,EAAI,UAAY,KAAQD,EAC1DN,CACR,EACM,MAAOO,EAAI,OAASV,EAAM,MAC1B,MAAOU,EAAI,OAASV,EAAM,OAAS,EACnC,QAASA,EAAM,SAAW,OAChC,EAAM,CACN"}
package/dist/index19.js CHANGED
@@ -1,121 +1,26 @@
1
- import n from "./index20.js";
2
- class h {
3
- /**
4
- * Creates a new GradualRenderer instance
5
- *
6
- * @param {HTMLCanvasElement} canvas - Canvas element for rendering
7
- * @param {Object} pdfDimensions - PDF page dimensions
8
- * @param {number} pdfDimensions.width - Page width in pixels
9
- * @param {number} pdfDimensions.height - Page height in pixels
10
- */
11
- constructor(t, s) {
12
- this.canvas = t, this.dimensions = { ...s }, this.ctx = null, this.strokeDrawer = null, this.strokeCommands = [], this.currentTime = 0, this.isDestroyed = !1, this._setupCanvas();
13
- }
14
- /**
15
- * Configures canvas for high-DPI rendering
16
- *
17
- * @private
18
- */
19
- _setupCanvas() {
20
- const t = window.devicePixelRatio || 1, { width: s, height: e } = this.dimensions;
21
- this.canvas.width = Math.round(s * t), this.canvas.height = Math.round(e * t), this.canvas.style.width = `${s}px`, this.canvas.style.height = `${e}px`, this.ctx = this.canvas.getContext("2d"), this.ctx.setTransform(t, 0, 0, t, 0, 0), this.strokeDrawer = new n(this.ctx, this.dimensions);
22
- }
23
- /**
24
- * Sets the stroke commands to render
25
- *
26
- * @param {Array} commands - Array of stroke command objects
27
- * @param {string} commands[].id - Unique stroke identifier
28
- * @param {Array} commands[].points - [[x, y], ...] normalized coordinates
29
- * @param {string} commands[].color - Stroke color
30
- * @param {number} commands[].width - Stroke width in pixels
31
- * @param {number} commands[].start - Start time in seconds
32
- * @param {number} commands[].end - End time in seconds
33
- */
34
- setStrokeCommands(t) {
35
- this.isDestroyed || (this.strokeCommands = t || [], this.strokeCommands.sort((s, e) => {
36
- const r = s.start ?? 0, i = e.start ?? 0;
37
- return r - i;
38
- }));
39
- }
40
- /**
41
- * Sets the current timeline position
42
- *
43
- * @param {number} time - Current time in seconds
44
- */
45
- setTime(t) {
46
- this.isDestroyed || (this.currentTime = t);
47
- }
48
- /**
49
- * Updates dimensions when viewport changes
50
- *
51
- * @param {Object} dimensions - New dimensions
52
- * @param {number} dimensions.width - Width in pixels
53
- * @param {number} dimensions.height - Height in pixels
54
- */
55
- setDimensions(t) {
56
- this.isDestroyed || (this.dimensions = { ...t }, this._setupCanvas());
57
- }
58
- /**
59
- * Renders all visible strokes at current timeline position
60
- *
61
- * Called once per timeline update. Clears canvas and redraws
62
- * all strokes with appropriate progress.
63
- */
64
- render() {
65
- if (!(this.isDestroyed || !this.ctx)) {
66
- this.strokeDrawer.clear();
67
- for (const t of this.strokeCommands) {
68
- const s = t.start ?? 0, e = t.end ?? s + 1;
69
- if (this.currentTime < s)
70
- continue;
71
- const r = this._calculateProgress(s, e);
72
- this.strokeDrawer.drawStroke(t, r);
73
- }
74
- }
75
- }
76
- /**
77
- * Calculates stroke progress based on timing
78
- *
79
- * @private
80
- * @param {number} start - Stroke start time in seconds
81
- * @param {number} end - Stroke end time in seconds
82
- * @returns {number} Progress from 0 to 1
83
- */
84
- _calculateProgress(t, s) {
85
- if (this.currentTime >= s)
86
- return 1;
87
- const e = s - t;
88
- if (e <= 0) return 1;
89
- const r = this.currentTime - t;
90
- return Math.max(0, Math.min(1, r / e));
91
- }
92
- /**
93
- * Clears the canvas
94
- */
95
- clear() {
96
- this.isDestroyed || !this.strokeDrawer || this.strokeDrawer.clear();
97
- }
98
- /**
99
- * Gets visible stroke count at current time
100
- *
101
- * @returns {number} Number of visible strokes
102
- */
103
- getVisibleStrokeCount() {
104
- let t = 0;
105
- for (const s of this.strokeCommands) {
106
- const e = s.start ?? 0;
107
- this.currentTime >= e && t++;
108
- }
109
- return t;
110
- }
111
- /**
112
- * Destroys the renderer and releases resources
113
- */
114
- destroy() {
115
- this.isDestroyed || (this.strokeCommands = [], this.strokeDrawer = null, this.ctx = null, this.canvas = null, this.isDestroyed = !0);
116
- }
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,
19
+ width: t.width || i.width || 2,
20
+ lineCap: i.lineCap || "round"
21
+ }));
117
22
  }
118
23
  export {
119
- h as default
24
+ l as inkToStrokes
120
25
  };
121
26
  //# sourceMappingURL=index19.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index19.js","sources":["../src/pen/GradualRenderer.js"],"sourcesContent":["import StrokeDrawer from './StrokeDrawer.js';\n\n/**\n * GradualRenderer - Progressive stroke rendering synced to timeline\n *\n * Renders stroke commands with progressive reveal based on current\n * audio/video timeline position.\n *\n * Features:\n * - Progressive stroke reveal synced to audio timeline\n * - High-DPI canvas support for crisp rendering\n * - Efficient single-pass render per timeline update\n * - Accepts timing in seconds (start/end fields)\n *\n * @example\n * const renderer = new GradualRenderer(canvas, { width: 800, height: 600 });\n * renderer.setStrokeCommands(commands);\n * renderer.setTime(1.5); // seconds\n * renderer.render();\n */\nclass GradualRenderer {\n /**\n * Creates a new GradualRenderer instance\n *\n * @param {HTMLCanvasElement} canvas - Canvas element for rendering\n * @param {Object} pdfDimensions - PDF page dimensions\n * @param {number} pdfDimensions.width - Page width in pixels\n * @param {number} pdfDimensions.height - Page height in pixels\n */\n constructor(canvas, pdfDimensions) {\n this.canvas = canvas;\n this.dimensions = { ...pdfDimensions };\n this.ctx = null;\n this.strokeDrawer = null;\n this.strokeCommands = [];\n this.currentTime = 0; // seconds\n this.isDestroyed = false;\n\n this._setupCanvas();\n }\n\n /**\n * Configures canvas for high-DPI rendering\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n const { width, height } = this.dimensions;\n\n // Set canvas buffer resolution (high-res)\n this.canvas.width = Math.round(width * dpr);\n this.canvas.height = Math.round(height * dpr);\n\n // Set canvas display size (CSS)\n this.canvas.style.width = `${width}px`;\n this.canvas.style.height = `${height}px`;\n\n // Get context and scale for DPR\n this.ctx = this.canvas.getContext('2d');\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n // Create stroke drawer\n this.strokeDrawer = new StrokeDrawer(this.ctx, this.dimensions);\n }\n\n /**\n * Sets the stroke commands to render\n *\n * @param {Array} commands - Array of stroke command objects\n * @param {string} commands[].id - Unique stroke identifier\n * @param {Array} commands[].points - [[x, y], ...] normalized coordinates\n * @param {string} commands[].color - Stroke color\n * @param {number} commands[].width - Stroke width in pixels\n * @param {number} commands[].start - Start time in seconds\n * @param {number} commands[].end - End time in seconds\n */\n setStrokeCommands(commands) {\n if (this.isDestroyed) return;\n\n this.strokeCommands = commands || [];\n\n // Sort by start time for efficient rendering\n this.strokeCommands.sort((a, b) => {\n const startA = a.start ?? 0;\n const startB = b.start ?? 0;\n return startA - startB;\n });\n }\n\n /**\n * Sets the current timeline position\n *\n * @param {number} time - Current time in seconds\n */\n setTime(time) {\n if (this.isDestroyed) return;\n this.currentTime = time;\n }\n\n /**\n * Updates dimensions when viewport changes\n *\n * @param {Object} dimensions - New dimensions\n * @param {number} dimensions.width - Width in pixels\n * @param {number} dimensions.height - Height in pixels\n */\n setDimensions(dimensions) {\n if (this.isDestroyed) return;\n\n this.dimensions = { ...dimensions };\n this._setupCanvas();\n }\n\n /**\n * Renders all visible strokes at current timeline position\n *\n * Called once per timeline update. Clears canvas and redraws\n * all strokes with appropriate progress.\n */\n render() {\n if (this.isDestroyed || !this.ctx) return;\n\n // Clear canvas\n this.strokeDrawer.clear();\n\n // Draw each stroke based on timing\n for (const stroke of this.strokeCommands) {\n const start = stroke.start ?? 0;\n const end = stroke.end ?? start + 1;\n\n // Skip strokes that haven't started\n if (this.currentTime < start) {\n continue;\n }\n\n // Calculate progress\n const progress = this._calculateProgress(start, end);\n\n // Draw stroke with progress\n this.strokeDrawer.drawStroke(stroke, progress);\n }\n }\n\n /**\n * Calculates stroke progress based on timing\n *\n * @private\n * @param {number} start - Stroke start time in seconds\n * @param {number} end - Stroke end time in seconds\n * @returns {number} Progress from 0 to 1\n */\n _calculateProgress(start, end) {\n if (this.currentTime >= end) {\n return 1.0; // Fully visible\n }\n\n const duration = end - start;\n if (duration <= 0) return 1.0;\n\n const elapsed = this.currentTime - start;\n return Math.max(0, Math.min(1, elapsed / duration));\n }\n\n /**\n * Clears the canvas\n */\n clear() {\n if (this.isDestroyed || !this.strokeDrawer) return;\n this.strokeDrawer.clear();\n }\n\n /**\n * Gets visible stroke count at current time\n *\n * @returns {number} Number of visible strokes\n */\n getVisibleStrokeCount() {\n let count = 0;\n for (const stroke of this.strokeCommands) {\n const start = stroke.start ?? 0;\n if (this.currentTime >= start) {\n count++;\n }\n }\n return count;\n }\n\n /**\n * Destroys the renderer and releases resources\n */\n destroy() {\n if (this.isDestroyed) return;\n\n this.strokeCommands = [];\n this.strokeDrawer = null;\n this.ctx = null;\n this.canvas = null;\n this.isDestroyed = true;\n }\n}\n\nexport default GradualRenderer;\n"],"names":["GradualRenderer","canvas","pdfDimensions","dpr","width","height","StrokeDrawer","commands","a","b","startA","startB","time","dimensions","stroke","start","end","progress","duration","elapsed","count"],"mappings":"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"}
1
+ {"version":3,"file":"index19.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 * Color/width fall back to the resolved `style` (which itself draws from\n * `DEFAULT_CONFIG.ink` in `config/defaults.js`); per-substroke `sub.color`\n * and `sub.width` may override on a stroke-by-stroke basis.\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,\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":"AA4BO,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;AAAA,IAC1B,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");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;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./index3.cjs"),a=require("./index4.cjs"),u=require("./index5.cjs"),r=i=>({success:!1,error:i}),s=i=>({success:!0,...i||{}}),n="AnnotationRenderer has been destroyed";class c{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 o.PDFRenderer,this.strokeCanvas=this._createStrokeCanvas(),this.strokeRenderer=new u.StrokeRenderer(this.strokeCanvas,e.strokeConfig||{}),this.timelineSync=new a.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).then(t=>{t.success||console.error("AnnotationRenderer: Failed to auto-load PDF:",t.error)})}_isDestroyed(){return!this.strokeRenderer||!this.timelineSync||!this.pdfRenderer}_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}_renderCurrentFrame(){this.strokeRenderer.render(this.timelineSync.getCurrentTime())}async loadPDF(e){try{if(this._isDestroyed())return r(n);if(!e||typeof e!="string")return r("Invalid PDF URL provided");const t=await this.pdfRenderer.loadDocument(e);return t.success?(this.pdfUrl=e,this.pageCount=t.pageCount,s({pageCount:t.pageCount})):t}catch(t){return console.error("AnnotationRenderer.loadPDF: Error loading PDF:",t),r(`Failed to load PDF: ${t.message}`)}}async setPage(e){try{if(this._isDestroyed())return r(n);if(typeof e!="number"||e<1)return r("Invalid page number");if(this.pageCount>0&&e>this.pageCount)return r(`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.strokeRenderer.setViewport(t.viewport.width,t.viewport.height),this._renderCurrentFrame(),s({viewport:t.viewport})):t}catch(t){return console.error("AnnotationRenderer.setPage: Error rendering page:",t),r(`Failed to render page: ${t.message}`)}}async setScale(e){try{return this._isDestroyed()?r(n):typeof e!="number"||e<=0?r("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),r(`Failed to change scale: ${t.message}`)}}setAnnotations(e){return this._isDestroyed()?r(n):Array.isArray(e)?(this.annotations=e,this.strokeRenderer.setAnnotations(e,this.currentPage),this._renderCurrentFrame(),s()):r("annotations must be an array")}setStrokes(e){return this._isDestroyed()?r(n):Array.isArray(e)?(this.strokeRenderer.setStrokes(e),this._renderCurrentFrame(),s()):r("strokes must be an array")}setTime(e){return this._isDestroyed()?r(n):typeof e!="number"?r("timestamp must be a number"):(this.timelineSync.setTime(e),s())}startContinuousSync(e){this._isDestroyed()||this.timelineSync.startContinuousSync(e)}stopContinuousSync(){this._isDestroyed()||this.timelineSync.stopContinuousSync()}isContinuousSyncActive(){return this._isDestroyed()?!1:this.timelineSync.isRunning}updateStrokeConfig(e){return this._isDestroyed()?r(n):!e||typeof e!="object"?r("newConfig must be an object"):(this.strokeRenderer.setConfig(e),this.strokeRenderer.setAnnotations(this.annotations,this.currentPage),this._renderCurrentFrame(),s())}getState(){return this._isDestroyed()?null:{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=c;
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';\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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"}
1
+ {"version":3,"file":"index2.cjs","sources":["../src/core/AnnotationRenderer.js"],"sourcesContent":["/**\n * AnnotationRenderer - Main facade for the PDF annotation rendering engine.\n *\n * Orchestrates PDFRenderer, StrokeRenderer, and TimelineSync. Framework-\n * agnostic core that React/Vue/Svelte adapters wrap.\n *\n * Error-handling contract (v0.7.0): every public method returns\n * `{ success: boolean, error?: string, ...payload }`\n * The constructor is the only entry point that throws.\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/** Standard failure shape for public methods. */\nconst fail = (error) => ({ success: false, error });\n/** Standard success shape (with optional payload merged in). */\nconst ok = (payload) => ({ success: true, ...(payload || {}) });\n\n/** Sentinel error returned by every public method invoked after `destroy()`. */\nconst DESTROYED_ERROR = 'AnnotationRenderer has been destroyed';\n\nexport class AnnotationRenderer {\n /**\n * Create AnnotationRenderer instance.\n *\n * @param {Object} config\n * @param {HTMLElement} config.container DOM element for the stroke canvas\n * @param {HTMLCanvasElement} config.canvasElement Canvas for PDF page rendering\n * @param {string} [config.pdfUrl] PDF URL to auto-load\n * @param {number} [config.initialPage=1]\n * @param {number} [config.initialScale=1.0]\n * @param {Array} [config.annotations=[]]\n * @param {Object} [config.strokeConfig]\n * @throws {Error} when config is missing required DOM elements\n */\n constructor(config) {\n if (!config || typeof config !== 'object') {\n throw new Error('AnnotationRenderer: config object is required');\n }\n if (!config.container || !(config.container instanceof HTMLElement)) {\n throw new Error('AnnotationRenderer: config.container must be a valid DOM element');\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 this.pdfRenderer = new PDFRenderer();\n this.strokeCanvas = this._createStrokeCanvas();\n this.strokeRenderer = new StrokeRenderer(this.strokeCanvas, config.strokeConfig || {});\n this.timelineSync = new TimelineSync();\n\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 timeline ticks → renderer.render\n this.timelineSync.subscribe((time) => {\n this.strokeRenderer.render(time);\n });\n\n // Auto-load PDF if provided. Errors are surfaced via console; callers\n // who want explicit error handling should call loadPDF themselves.\n if (config.pdfUrl) {\n this.loadPDF(config.pdfUrl).then((result) => {\n if (!result.success) {\n console.error('AnnotationRenderer: Failed to auto-load PDF:', result.error);\n }\n });\n }\n }\n\n /**\n * Whether the renderer has been torn down via `destroy()`. After destroy,\n * the subsystem references are nulled — every public method consults this\n * predicate first and returns a Result-shaped error instead of throwing\n * a TypeError on null deref. (T17b — DA H1)\n *\n * @private\n * @returns {boolean}\n */\n _isDestroyed() {\n return (\n !this.strokeRenderer || !this.timelineSync || !this.pdfRenderer\n );\n }\n\n /**\n * Create the absolute-positioned overlay canvas used for stroke rendering.\n * @private\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 * Re-render the current frame after a state mutation.\n * @private\n */\n _renderCurrentFrame() {\n this.strokeRenderer.render(this.timelineSync.getCurrentTime());\n }\n\n /**\n * Load a PDF document.\n *\n * @param {string} url\n * @returns {Promise<{success: boolean, pageCount?: number, error?: string}>}\n */\n async loadPDF(url) {\n try {\n if (this._isDestroyed()) return fail(DESTROYED_ERROR);\n if (!url || typeof url !== 'string') return fail('Invalid PDF URL provided');\n\n const result = await this.pdfRenderer.loadDocument(url);\n if (!result.success) return result;\n\n this.pdfUrl = url;\n this.pageCount = result.pageCount;\n return ok({ pageCount: result.pageCount });\n } catch (err) {\n console.error('AnnotationRenderer.loadPDF: Error loading PDF:', err);\n return fail(`Failed to load PDF: ${err.message}`);\n }\n }\n\n /**\n * Render a specific page on the PDF canvas and resize the stroke canvas to\n * match the new viewport. Per v0.7.0 (R18) this method NO LONGER touches\n * stroke annotations — adapters must call `setAnnotations` afterwards if\n * the annotation set should be re-applied for the new page.\n *\n * @param {number} pageNum 1-indexed page number\n * @returns {Promise<{success: boolean, viewport?: Object, error?: string}>}\n */\n async setPage(pageNum) {\n try {\n if (this._isDestroyed()) return fail(DESTROYED_ERROR);\n if (typeof pageNum !== 'number' || pageNum < 1) return fail('Invalid page number');\n if (this.pageCount > 0 && pageNum > this.pageCount) {\n return fail(`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 if (!result.success) return result;\n\n this.currentPage = pageNum;\n this.currentViewport = result.viewport;\n this.strokeRenderer.setViewport(result.viewport.width, result.viewport.height);\n\n // Note: we deliberately do NOT call setAnnotations here. Adapters are\n // responsible for re-binding annotations after a page change so that\n // they can pick the right page filter / validation options.\n this._renderCurrentFrame();\n\n return ok({ viewport: result.viewport });\n } catch (err) {\n console.error('AnnotationRenderer.setPage: Error rendering page:', err);\n return fail(`Failed to render page: ${err.message}`);\n }\n }\n\n /**\n * Change the zoom scale and re-render the current page.\n *\n * @param {number} scale Positive scale factor\n * @returns {Promise<{success: boolean, viewport?: Object, error?: string}>}\n */\n async setScale(scale) {\n try {\n if (this._isDestroyed()) return fail(DESTROYED_ERROR);\n if (typeof scale !== 'number' || scale <= 0) {\n return fail('Invalid scale value (must be positive number)');\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 fail(`Failed to change scale: ${err.message}`);\n }\n }\n\n /**\n * Replace the annotation set and re-render at the current time.\n *\n * @param {Array} annotations\n * @returns {{success: boolean, error?: string}}\n */\n setAnnotations(annotations) {\n if (this._isDestroyed()) return fail(DESTROYED_ERROR);\n if (!Array.isArray(annotations)) {\n return fail('annotations must be an array');\n }\n this.annotations = annotations;\n this.strokeRenderer.setAnnotations(annotations, this.currentPage);\n this._renderCurrentFrame();\n return ok();\n }\n\n /**\n * Inject pre-converted strokes (skips annotation conversion).\n *\n * @param {Array} strokes\n * @returns {{success: boolean, error?: string}}\n */\n setStrokes(strokes) {\n if (this._isDestroyed()) return fail(DESTROYED_ERROR);\n if (!Array.isArray(strokes)) return fail('strokes must be an array');\n this.strokeRenderer.setStrokes(strokes);\n this._renderCurrentFrame();\n return ok();\n }\n\n /**\n * Manually set the current timeline position.\n *\n * @param {number} timestamp Seconds\n * @returns {{success: boolean, error?: string}}\n */\n setTime(timestamp) {\n if (this._isDestroyed()) return fail(DESTROYED_ERROR);\n if (typeof timestamp !== 'number') return fail('timestamp must be a number');\n this.timelineSync.setTime(timestamp);\n return ok();\n }\n\n /**\n * Start RAF-driven continuous timeline sync. Use this for audio/video\n * playback; the supplied function is polled at ~60fps.\n *\n * Silently no-ops if the renderer has been destroyed.\n *\n * @param {() => number} getTimeFunction\n */\n startContinuousSync(getTimeFunction) {\n if (this._isDestroyed()) return;\n this.timelineSync.startContinuousSync(getTimeFunction);\n }\n\n /**\n * Stop the RAF-driven sync started by `startContinuousSync`.\n *\n * Silently no-ops if the renderer has been destroyed.\n */\n stopContinuousSync() {\n if (this._isDestroyed()) return;\n this.timelineSync.stopContinuousSync();\n }\n\n /** @returns {boolean} whether continuous sync is currently running (false if destroyed) */\n isContinuousSyncActive() {\n if (this._isDestroyed()) return false;\n return this.timelineSync.isRunning;\n }\n\n /**\n * Update stroke rendering configuration at runtime and re-convert\n * annotations with the new style.\n *\n * @param {Object} newConfig\n * @returns {{success: boolean, error?: string}}\n */\n updateStrokeConfig(newConfig) {\n if (this._isDestroyed()) return fail(DESTROYED_ERROR);\n if (!newConfig || typeof newConfig !== 'object') {\n return fail('newConfig must be an object');\n }\n this.strokeRenderer.setConfig(newConfig);\n this.strokeRenderer.setAnnotations(this.annotations, this.currentPage);\n this._renderCurrentFrame();\n return ok();\n }\n\n /**\n * Snapshot of the current engine state — useful for debug overlays.\n *\n * @returns {Object|null} state snapshot, or `null` if the renderer has\n * been destroyed.\n */\n getState() {\n if (this._isDestroyed()) return null;\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 /** Tear down all subsystems and release references. */\n destroy() {\n if (this.pdfRenderer) this.pdfRenderer.destroy();\n if (this.strokeRenderer) this.strokeRenderer.destroy();\n if (this.timelineSync) this.timelineSync.destroy();\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":["fail","error","ok","payload","DESTROYED_ERROR","AnnotationRenderer","config","PDFRenderer","StrokeRenderer","TimelineSync","time","result","canvas","url","err","pageNum","scale","annotations","strokes","timestamp","getTimeFunction","newConfig"],"mappings":"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"}