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
package/dist/index6.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class t{constructor(e,r){if(this._validateContainer(e),this._validateViewport(r),this.container=e,this.viewport={...r},this.annotations=[],this.currentTime=0,this.isDestroyed=!1,new.target===t)throw new Error("BaseLayer is an abstract class and cannot be instantiated directly. Extend it with a concrete implementation.")}setAnnotations(e){this._checkDestroyed("setAnnotations"),this.annotations=e||[]}setViewport(e){this._checkDestroyed("setViewport"),this._validateViewport(e),this.viewport={...e}}updateTime(e){this._checkDestroyed("updateTime"),this.currentTime=e}destroy(){this.isDestroyed||(this.annotations=null,this.viewport=null,this.container=null,this.isDestroyed=!0)}render(){throw new Error("render() must be implemented by subclass")}update(){throw new Error("update() must be implemented by subclass")}_validateContainer(e){if(!e||!(e instanceof HTMLElement))throw new Error("BaseLayer: container must be a valid HTMLElement")}_validateViewport(e){if(!e||typeof e!="object")throw new Error("BaseLayer: viewport must be an object");if(typeof e.width!="number"||e.width<=0)throw new Error("BaseLayer: viewport.width must be a positive number");if(typeof e.height!="number"||e.height<=0)throw new Error("BaseLayer: viewport.height must be a positive number");if(typeof e.scale!="number"||e.scale<=0)throw new Error("BaseLayer: viewport.scale must be a positive number")}_checkDestroyed(e){if(this.isDestroyed)throw new Error(`BaseLayer: Cannot call ${e}() on destroyed layer`)}}exports.default=t;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function h(e){if(e==null)return Math.random;let r=typeof e=="string"?e.split("").reduce((t,n)=>t+n.charCodeAt(0),0):e;return function(){r|=0,r=r+1831565813|0;let t=Math.imul(r^r>>>15,1|r);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296}}function b(e,r,t=null){const{amplitude:n=0}=r||{};if(n===0||!e||e.length===0)return e;const l=h(t);return e.map(([u,a])=>[u+(l()-.5)*n,a+(l()-.5)*n])}function M(e,r){const{taperIn:t=0,taperOut:n=0}=r||{};if(!e||e.length===0)return[];if(t===0&&n===0)return e.map(()=>1);const l=e.length;return e.map((u,a)=>{const f=l>1?a/(l-1):0;return t>0&&f<t?f/t:n>0&&f>1-n?(1-f)/n:1})}function A(e,r){const{amplitude:t=0,frequency:n=.05}=r||{};return t===0||!e||e.length<2?e:e.map(([l,u],a)=>{const f=a/(e.length-1),y=Math.sin(f*Math.PI*2*n*e.length)*t;let d=0,p=1;if(a<e.length-1){const[m,g]=e[a+1],c=m-l,o=g-u,i=Math.sqrt(c*c+o*o);i>1e-4&&(d=-o/i,p=c/i)}return[l+d*y,u+p*y]})}function s(e,r){if(!r)return{...e};if(!e)return{...r};const t={...e};for(const n of Object.keys(r)){const l=r[n],u=e[n];l!==null&&typeof l=="object"&&!Array.isArray(l)&&u!==null&&typeof u=="object"&&!Array.isArray(u)?t[n]=s(u,l):l!==void 0&&(t[n]=l)}return t}exports.applyJitter=b;exports.applyPressure=M;exports.applyWobble=A;exports.deepMerge=s;exports.seededRandom=h;
2
2
  //# sourceMappingURL=index6.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index6.cjs","sources":["../src/layers/BaseLayer.js"],"sourcesContent":["/**\n * BaseLayer - Abstract base class for annotation layers\n *\n * Provides common interface and lifecycle management for all annotation layer types.\n * Subclasses must implement render() and update() abstract methods.\n *\n * @abstract\n */\nclass BaseLayer {\n /**\n * Creates a new BaseLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @throws {Error} If container is not a valid HTMLElement\n * @throws {Error} If viewport is missing required properties\n * @throws {Error} If instantiated directly (abstract class)\n */\n constructor(container, viewport) {\n // Validate parameters\n this._validateContainer(container);\n this._validateViewport(viewport);\n\n // Initialize core properties\n this.container = container;\n this.viewport = { ...viewport };\n this.annotations = [];\n this.currentTime = 0;\n this.isDestroyed = false;\n\n // Prevent direct instantiation\n if (new.target === BaseLayer) {\n throw new Error('BaseLayer is an abstract class and cannot be instantiated directly. Extend it with a concrete implementation.');\n }\n }\n\n /**\n * Sets the annotation data for this layer\n *\n * @param {Array} annotations - Array of annotation objects\n * @throws {Error} If called after layer is destroyed\n */\n setAnnotations(annotations) {\n this._checkDestroyed('setAnnotations');\n this.annotations = annotations || [];\n }\n\n /**\n * Updates the viewport dimensions\n *\n * @param {Object} viewport - New viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @throws {Error} If viewport is missing required properties\n * @throws {Error} If called after layer is destroyed\n */\n setViewport(viewport) {\n this._checkDestroyed('setViewport');\n this._validateViewport(viewport);\n this.viewport = { ...viewport };\n }\n\n /**\n * Updates the current timeline position\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n */\n updateTime(nowSec) {\n this._checkDestroyed('updateTime');\n this.currentTime = nowSec;\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Safe to call multiple times (idempotent).\n * Subclasses must call super.destroy() after their own cleanup.\n */\n destroy() {\n if (this.isDestroyed) {\n return;\n }\n\n this.annotations = null;\n this.viewport = null;\n this.container = null;\n this.isDestroyed = true;\n }\n\n /**\n * Renders the layer content\n *\n * @abstract\n * @throws {Error} If not implemented by subclass\n */\n render() {\n throw new Error('render() must be implemented by subclass');\n }\n\n /**\n * Updates the visual state of the layer\n *\n * @abstract\n * @throws {Error} If not implemented by subclass\n */\n update() {\n throw new Error('update() must be implemented by subclass');\n }\n\n /**\n * Validates that container is a valid HTMLElement\n *\n * @private\n * @param {*} container - Value to validate\n * @throws {Error} If container is not a valid HTMLElement\n */\n _validateContainer(container) {\n if (!container || !(container instanceof HTMLElement)) {\n throw new Error('BaseLayer: container must be a valid HTMLElement');\n }\n }\n\n /**\n * Validates that viewport has required properties\n *\n * @private\n * @param {*} viewport - Value to validate\n * @throws {Error} If viewport is missing required properties\n */\n _validateViewport(viewport) {\n if (!viewport || typeof viewport !== 'object') {\n throw new Error('BaseLayer: viewport must be an object');\n }\n\n if (typeof viewport.width !== 'number' || viewport.width <= 0) {\n throw new Error('BaseLayer: viewport.width must be a positive number');\n }\n\n if (typeof viewport.height !== 'number' || viewport.height <= 0) {\n throw new Error('BaseLayer: viewport.height must be a positive number');\n }\n\n if (typeof viewport.scale !== 'number' || viewport.scale <= 0) {\n throw new Error('BaseLayer: viewport.scale must be a positive number');\n }\n }\n\n /**\n * Checks if layer is destroyed and throws error if so\n *\n * @private\n * @param {string} methodName - Name of method being called\n * @throws {Error} If layer is destroyed\n */\n _checkDestroyed(methodName) {\n if (this.isDestroyed) {\n throw new Error(`BaseLayer: Cannot call ${methodName}() on destroyed layer`);\n }\n }\n}\n\nexport default BaseLayer;\n"],"names":["BaseLayer","container","viewport","annotations","nowSec","methodName"],"mappings":"4GAQA,MAAMA,CAAU,CAad,YAAYC,EAAWC,EAAU,CAa/B,GAXA,KAAK,mBAAmBD,CAAS,EACjC,KAAK,kBAAkBC,CAAQ,EAG/B,KAAK,UAAYD,EACjB,KAAK,SAAW,CAAE,GAAGC,CAAQ,EAC7B,KAAK,YAAc,CAAA,EACnB,KAAK,YAAc,EACnB,KAAK,YAAc,GAGf,aAAeF,EACjB,MAAM,IAAI,MAAM,+GAA+G,CAEnI,CAQA,eAAeG,EAAa,CAC1B,KAAK,gBAAgB,gBAAgB,EACrC,KAAK,YAAcA,GAAe,CAAA,CACpC,CAYA,YAAYD,EAAU,CACpB,KAAK,gBAAgB,aAAa,EAClC,KAAK,kBAAkBA,CAAQ,EAC/B,KAAK,SAAW,CAAE,GAAGA,CAAQ,CAC/B,CAQA,WAAWE,EAAQ,CACjB,KAAK,gBAAgB,YAAY,EACjC,KAAK,YAAcA,CACrB,CAQA,SAAU,CACJ,KAAK,cAIT,KAAK,YAAc,KACnB,KAAK,SAAW,KAChB,KAAK,UAAY,KACjB,KAAK,YAAc,GACrB,CAQA,QAAS,CACP,MAAM,IAAI,MAAM,0CAA0C,CAC5D,CAQA,QAAS,CACP,MAAM,IAAI,MAAM,0CAA0C,CAC5D,CASA,mBAAmBH,EAAW,CAC5B,GAAI,CAACA,GAAa,EAAEA,aAAqB,aACvC,MAAM,IAAI,MAAM,kDAAkD,CAEtE,CASA,kBAAkBC,EAAU,CAC1B,GAAI,CAACA,GAAY,OAAOA,GAAa,SACnC,MAAM,IAAI,MAAM,uCAAuC,EAGzD,GAAI,OAAOA,EAAS,OAAU,UAAYA,EAAS,OAAS,EAC1D,MAAM,IAAI,MAAM,qDAAqD,EAGvE,GAAI,OAAOA,EAAS,QAAW,UAAYA,EAAS,QAAU,EAC5D,MAAM,IAAI,MAAM,sDAAsD,EAGxE,GAAI,OAAOA,EAAS,OAAU,UAAYA,EAAS,OAAS,EAC1D,MAAM,IAAI,MAAM,qDAAqD,CAEzE,CASA,gBAAgBG,EAAY,CAC1B,GAAI,KAAK,YACP,MAAM,IAAI,MAAM,0BAA0BA,CAAU,uBAAuB,CAE/E,CACF"}
1
+ {"version":3,"file":"index6.cjs","sources":["../src/pen/effects.js"],"sourcesContent":["/**\n * Pen Effects - Utility functions for hand-drawn feel\n *\n * Provides jitter, pressure, and wobble effects for stroke paths.\n * Pure functions that transform point arrays without side effects.\n *\n * @module pen/effects\n */\n\n/**\n * Creates a seeded random number generator\n *\n * Uses mulberry32 algorithm for deterministic randomness.\n * Same seed produces same sequence of random numbers.\n *\n * @param {string|number|null} seed - Seed value (null uses Math.random)\n * @returns {Function} Function that returns random numbers 0-1\n */\nexport function seededRandom(seed) {\n if (seed === null || seed === undefined) {\n return Math.random;\n }\n\n // Convert string seed to number\n let numSeed = typeof seed === 'string'\n ? seed.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)\n : seed;\n\n // Mulberry32 algorithm\n return function() {\n numSeed |= 0;\n numSeed = (numSeed + 0x6D2B79F5) | 0;\n let t = Math.imul(numSeed ^ (numSeed >>> 15), 1 | numSeed);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * Applies random jitter offset to points\n *\n * Adds small random displacement to each point for hand-drawn imperfection.\n * Returns new array, does not mutate input.\n *\n * @param {Array<[number, number]>} points - Array of [x, y] coordinates\n * @param {Object} config - Jitter configuration\n * @param {number} config.amplitude - Max offset in normalized units (0 = disabled)\n * @param {number} [config.frequency=1] - Not currently used, reserved for future\n * @param {string|number|null} [seed=null] - Seed for reproducible randomness\n * @returns {Array<[number, number]>} New array with jittered points\n */\nexport function applyJitter(points, config, seed = null) {\n const { amplitude = 0 } = config || {};\n\n if (amplitude === 0 || !points || points.length === 0) {\n return points;\n }\n\n const rng = seededRandom(seed);\n\n return points.map(([x, y]) => [\n x + (rng() - 0.5) * amplitude,\n y + (rng() - 0.5) * amplitude\n ]);\n}\n\n/**\n * Calculates pressure values for variable stroke width\n *\n * Simulates pen pressure with taper at start and end of stroke.\n * Returns pressure multipliers (0-1) for each point.\n *\n * @param {Array<[number, number]>} points - Array of [x, y] coordinates\n * @param {Object} config - Pressure configuration\n * @param {number} [config.taperIn=0] - Start taper length (0-1, fraction of stroke)\n * @param {number} [config.taperOut=0] - End taper length (0-1, fraction of stroke)\n * @returns {Array<number>} Pressure values (0-1) per point\n */\nexport function applyPressure(points, config) {\n const { taperIn = 0, taperOut = 0 } = config || {};\n\n if (!points || points.length === 0) {\n return [];\n }\n\n if (taperIn === 0 && taperOut === 0) {\n return points.map(() => 1.0);\n }\n\n const len = points.length;\n\n return points.map((_, i) => {\n const t = len > 1 ? i / (len - 1) : 0;\n\n // Taper in at start\n if (taperIn > 0 && t < taperIn) {\n return t / taperIn;\n }\n\n // Taper out at end\n if (taperOut > 0 && t > 1 - taperOut) {\n return (1 - t) / taperOut;\n }\n\n // Full pressure in middle\n return 1.0;\n });\n}\n\n/**\n * Applies low-frequency wobble perpendicular to stroke direction\n *\n * Adds gentle wave effect to simulate natural hand movement.\n * Returns new array, does not mutate input.\n *\n * @param {Array<[number, number]>} points - Array of [x, y] coordinates\n * @param {Object} config - Wobble configuration\n * @param {number} config.amplitude - Wave height in normalized units (0 = disabled)\n * @param {number} [config.frequency=0.05] - Wave frequency\n * @returns {Array<[number, number]>} New array with wobbled points\n */\nexport function applyWobble(points, config) {\n const { amplitude = 0, frequency = 0.05 } = config || {};\n\n if (amplitude === 0 || !points || points.length < 2) {\n return points;\n }\n\n return points.map(([x, y], i) => {\n // Calculate perpendicular direction based on position in stroke\n // Use simple sine wave for now\n const t = i / (points.length - 1);\n const offset = Math.sin(t * Math.PI * 2 * frequency * points.length) * amplitude;\n\n // Calculate perpendicular direction from neighbors\n let perpX = 0;\n let perpY = 1;\n\n if (i < points.length - 1) {\n const [nx, ny] = points[i + 1];\n const dx = nx - x;\n const dy = ny - y;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len > 0.0001) {\n // Perpendicular is (-dy, dx) normalized\n perpX = -dy / len;\n perpY = dx / len;\n }\n }\n\n return [\n x + perpX * offset,\n y + perpY * offset\n ];\n });\n}\n\n/**\n * Deep merges configuration objects\n *\n * Merges source into target, handling nested objects.\n * Returns new object, does not mutate inputs.\n *\n * @param {Object} target - Target object\n * @param {Object} source - Source object to merge\n * @returns {Object} Merged object\n */\nexport function deepMerge(target, source) {\n if (!source) return { ...target };\n if (!target) return { ...source };\n\n const result = { ...target };\n\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = target[key];\n\n if (\n sourceVal !== null &&\n typeof sourceVal === 'object' &&\n !Array.isArray(sourceVal) &&\n targetVal !== null &&\n typeof targetVal === 'object' &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(targetVal, sourceVal);\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal;\n }\n }\n\n return result;\n}\n"],"names":["seededRandom","seed","numSeed","acc","char","applyJitter","points","config","amplitude","rng","x","y","applyPressure","taperIn","taperOut","len","_","i","t","applyWobble","frequency","offset","perpX","perpY","nx","ny","dx","dy","deepMerge","target","source","result","key","sourceVal","targetVal"],"mappings":"gFAkBO,SAASA,EAAaC,EAAM,CACjC,GAAIA,GAAS,KACX,OAAO,KAAK,OAId,IAAIC,EAAU,OAAOD,GAAS,SAC1BA,EAAK,MAAM,EAAE,EAAE,OAAO,CAACE,EAAKC,IAASD,EAAMC,EAAK,WAAW,CAAC,EAAG,CAAC,EAChEH,EAGJ,OAAO,UAAW,CAChBC,GAAW,EACXA,EAAWA,EAAU,WAAc,EACnC,IAAI,EAAI,KAAK,KAAKA,EAAWA,IAAY,GAAK,EAAIA,CAAO,EACzD,SAAK,EAAI,KAAK,KAAK,EAAK,IAAM,EAAI,GAAK,CAAC,EAAK,IACpC,EAAK,IAAM,MAAS,GAAK,UACpC,CACF,CAeO,SAASG,EAAYC,EAAQC,EAAQN,EAAO,KAAM,CACvD,KAAM,CAAE,UAAAO,EAAY,CAAC,EAAKD,GAAU,CAAA,EAEpC,GAAIC,IAAc,GAAK,CAACF,GAAUA,EAAO,SAAW,EAClD,OAAOA,EAGT,MAAMG,EAAMT,EAAaC,CAAI,EAE7B,OAAOK,EAAO,IAAI,CAAC,CAACI,EAAGC,CAAC,IAAM,CAC5BD,GAAKD,IAAQ,IAAOD,EACpBG,GAAKF,EAAG,EAAK,IAAOD,CACxB,CAAG,CACH,CAcO,SAASI,EAAcN,EAAQC,EAAQ,CAC5C,KAAM,CAAE,QAAAM,EAAU,EAAG,SAAAC,EAAW,CAAC,EAAKP,GAAU,CAAA,EAEhD,GAAI,CAACD,GAAUA,EAAO,SAAW,EAC/B,MAAO,CAAA,EAGT,GAAIO,IAAY,GAAKC,IAAa,EAChC,OAAOR,EAAO,IAAI,IAAM,CAAG,EAG7B,MAAMS,EAAMT,EAAO,OAEnB,OAAOA,EAAO,IAAI,CAACU,EAAGC,IAAM,CAC1B,MAAMC,EAAIH,EAAM,EAAIE,GAAKF,EAAM,GAAK,EAGpC,OAAIF,EAAU,GAAKK,EAAIL,EACdK,EAAIL,EAITC,EAAW,GAAKI,EAAI,EAAIJ,GAClB,EAAII,GAAKJ,EAIZ,CACT,CAAC,CACH,CAcO,SAASK,EAAYb,EAAQC,EAAQ,CAC1C,KAAM,CAAE,UAAAC,EAAY,EAAG,UAAAY,EAAY,GAAI,EAAKb,GAAU,CAAA,EAEtD,OAAIC,IAAc,GAAK,CAACF,GAAUA,EAAO,OAAS,EACzCA,EAGFA,EAAO,IAAI,CAAC,CAACI,EAAGC,CAAC,EAAGM,IAAM,CAG/B,MAAMC,EAAID,GAAKX,EAAO,OAAS,GACzBe,EAAS,KAAK,IAAIH,EAAI,KAAK,GAAK,EAAIE,EAAYd,EAAO,MAAM,EAAIE,EAGvE,IAAIc,EAAQ,EACRC,EAAQ,EAEZ,GAAIN,EAAIX,EAAO,OAAS,EAAG,CACzB,KAAM,CAACkB,EAAIC,CAAE,EAAInB,EAAOW,EAAI,CAAC,EACvBS,EAAKF,EAAKd,EACViB,EAAKF,EAAKd,EACVI,EAAM,KAAK,KAAKW,EAAKA,EAAKC,EAAKA,CAAE,EAEnCZ,EAAM,OAERO,EAAQ,CAACK,EAAKZ,EACdQ,EAAQG,EAAKX,EAEjB,CAEA,MAAO,CACLL,EAAIY,EAAQD,EACZV,EAAIY,EAAQF,CAClB,CACE,CAAC,CACH,CAYO,SAASO,EAAUC,EAAQC,EAAQ,CACxC,GAAI,CAACA,EAAQ,MAAO,CAAE,GAAGD,CAAM,EAC/B,GAAI,CAACA,EAAQ,MAAO,CAAE,GAAGC,CAAM,EAE/B,MAAMC,EAAS,CAAE,GAAGF,CAAM,EAE1B,UAAWG,KAAO,OAAO,KAAKF,CAAM,EAAG,CACrC,MAAMG,EAAYH,EAAOE,CAAG,EACtBE,EAAYL,EAAOG,CAAG,EAG1BC,IAAc,MACd,OAAOA,GAAc,UACrB,CAAC,MAAM,QAAQA,CAAS,GACxBC,IAAc,MACd,OAAOA,GAAc,UACrB,CAAC,MAAM,QAAQA,CAAS,EAExBH,EAAOC,CAAG,EAAIJ,EAAUM,EAAWD,CAAS,EACnCA,IAAc,SACvBF,EAAOC,CAAG,EAAIC,EAElB,CAEA,OAAOF,CACT"}
package/dist/index6.js CHANGED
@@ -1,119 +1,65 @@
1
- class r {
2
- /**
3
- * Creates a new BaseLayer instance
4
- *
5
- * @param {HTMLElement} container - Parent DOM element for layer content
6
- * @param {Object} viewport - Initial viewport dimensions
7
- * @param {number} viewport.width - Viewport width in pixels
8
- * @param {number} viewport.height - Viewport height in pixels
9
- * @param {number} viewport.scale - PDF scale/zoom level
10
- * @throws {Error} If container is not a valid HTMLElement
11
- * @throws {Error} If viewport is missing required properties
12
- * @throws {Error} If instantiated directly (abstract class)
13
- */
14
- constructor(e, t) {
15
- if (this._validateContainer(e), this._validateViewport(t), this.container = e, this.viewport = { ...t }, this.annotations = [], this.currentTime = 0, this.isDestroyed = !1, new.target === r)
16
- throw new Error("BaseLayer is an abstract class and cannot be instantiated directly. Extend it with a concrete implementation.");
17
- }
18
- /**
19
- * Sets the annotation data for this layer
20
- *
21
- * @param {Array} annotations - Array of annotation objects
22
- * @throws {Error} If called after layer is destroyed
23
- */
24
- setAnnotations(e) {
25
- this._checkDestroyed("setAnnotations"), this.annotations = e || [];
26
- }
27
- /**
28
- * Updates the viewport dimensions
29
- *
30
- * @param {Object} viewport - New viewport dimensions
31
- * @param {number} viewport.width - Viewport width in pixels
32
- * @param {number} viewport.height - Viewport height in pixels
33
- * @param {number} viewport.scale - PDF scale/zoom level
34
- * @throws {Error} If viewport is missing required properties
35
- * @throws {Error} If called after layer is destroyed
36
- */
37
- setViewport(e) {
38
- this._checkDestroyed("setViewport"), this._validateViewport(e), this.viewport = { ...e };
39
- }
40
- /**
41
- * Updates the current timeline position
42
- *
43
- * @param {number} nowSec - Current timeline position in seconds
44
- * @throws {Error} If called after layer is destroyed
45
- */
46
- updateTime(e) {
47
- this._checkDestroyed("updateTime"), this.currentTime = e;
48
- }
49
- /**
50
- * Destroys the layer and releases resources
51
- *
52
- * Safe to call multiple times (idempotent).
53
- * Subclasses must call super.destroy() after their own cleanup.
54
- */
55
- destroy() {
56
- this.isDestroyed || (this.annotations = null, this.viewport = null, this.container = null, this.isDestroyed = !0);
57
- }
58
- /**
59
- * Renders the layer content
60
- *
61
- * @abstract
62
- * @throws {Error} If not implemented by subclass
63
- */
64
- render() {
65
- throw new Error("render() must be implemented by subclass");
66
- }
67
- /**
68
- * Updates the visual state of the layer
69
- *
70
- * @abstract
71
- * @throws {Error} If not implemented by subclass
72
- */
73
- update() {
74
- throw new Error("update() must be implemented by subclass");
75
- }
76
- /**
77
- * Validates that container is a valid HTMLElement
78
- *
79
- * @private
80
- * @param {*} container - Value to validate
81
- * @throws {Error} If container is not a valid HTMLElement
82
- */
83
- _validateContainer(e) {
84
- if (!e || !(e instanceof HTMLElement))
85
- throw new Error("BaseLayer: container must be a valid HTMLElement");
86
- }
87
- /**
88
- * Validates that viewport has required properties
89
- *
90
- * @private
91
- * @param {*} viewport - Value to validate
92
- * @throws {Error} If viewport is missing required properties
93
- */
94
- _validateViewport(e) {
95
- if (!e || typeof e != "object")
96
- throw new Error("BaseLayer: viewport must be an object");
97
- if (typeof e.width != "number" || e.width <= 0)
98
- throw new Error("BaseLayer: viewport.width must be a positive number");
99
- if (typeof e.height != "number" || e.height <= 0)
100
- throw new Error("BaseLayer: viewport.height must be a positive number");
101
- if (typeof e.scale != "number" || e.scale <= 0)
102
- throw new Error("BaseLayer: viewport.scale must be a positive number");
103
- }
104
- /**
105
- * Checks if layer is destroyed and throws error if so
106
- *
107
- * @private
108
- * @param {string} methodName - Name of method being called
109
- * @throws {Error} If layer is destroyed
110
- */
111
- _checkDestroyed(e) {
112
- if (this.isDestroyed)
113
- throw new Error(`BaseLayer: Cannot call ${e}() on destroyed layer`);
1
+ function s(t) {
2
+ if (t == null)
3
+ return Math.random;
4
+ let n = typeof t == "string" ? t.split("").reduce((e, r) => e + r.charCodeAt(0), 0) : t;
5
+ return function() {
6
+ n |= 0, n = n + 1831565813 | 0;
7
+ let e = Math.imul(n ^ n >>> 15, 1 | n);
8
+ return e = e + Math.imul(e ^ e >>> 7, 61 | e) ^ e, ((e ^ e >>> 14) >>> 0) / 4294967296;
9
+ };
10
+ }
11
+ function M(t, n, e = null) {
12
+ const { amplitude: r = 0 } = n || {};
13
+ if (r === 0 || !t || t.length === 0)
14
+ return t;
15
+ const u = s(e);
16
+ return t.map(([l, f]) => [
17
+ l + (u() - 0.5) * r,
18
+ f + (u() - 0.5) * r
19
+ ]);
20
+ }
21
+ function b(t, n) {
22
+ const { taperIn: e = 0, taperOut: r = 0 } = n || {};
23
+ if (!t || t.length === 0)
24
+ return [];
25
+ if (e === 0 && r === 0)
26
+ return t.map(() => 1);
27
+ const u = t.length;
28
+ return t.map((l, f) => {
29
+ const c = u > 1 ? f / (u - 1) : 0;
30
+ return e > 0 && c < e ? c / e : r > 0 && c > 1 - r ? (1 - c) / r : 1;
31
+ });
32
+ }
33
+ function A(t, n) {
34
+ const { amplitude: e = 0, frequency: r = 0.05 } = n || {};
35
+ return e === 0 || !t || t.length < 2 ? t : t.map(([u, l], f) => {
36
+ const c = f / (t.length - 1), h = Math.sin(c * Math.PI * 2 * r * t.length) * e;
37
+ let y = 0, d = 1;
38
+ if (f < t.length - 1) {
39
+ const [m, p] = t[f + 1], a = m - u, o = p - l, i = Math.sqrt(a * a + o * o);
40
+ i > 1e-4 && (y = -o / i, d = a / i);
41
+ }
42
+ return [
43
+ u + y * h,
44
+ l + d * h
45
+ ];
46
+ });
47
+ }
48
+ function g(t, n) {
49
+ if (!n) return { ...t };
50
+ if (!t) return { ...n };
51
+ const e = { ...t };
52
+ for (const r of Object.keys(n)) {
53
+ const u = n[r], l = t[r];
54
+ u !== null && typeof u == "object" && !Array.isArray(u) && l !== null && typeof l == "object" && !Array.isArray(l) ? e[r] = g(l, u) : u !== void 0 && (e[r] = u);
114
55
  }
56
+ return e;
115
57
  }
116
58
  export {
117
- r as default
59
+ M as applyJitter,
60
+ b as applyPressure,
61
+ A as applyWobble,
62
+ g as deepMerge,
63
+ s as seededRandom
118
64
  };
119
65
  //# sourceMappingURL=index6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index6.js","sources":["../src/layers/BaseLayer.js"],"sourcesContent":["/**\n * BaseLayer - Abstract base class for annotation layers\n *\n * Provides common interface and lifecycle management for all annotation layer types.\n * Subclasses must implement render() and update() abstract methods.\n *\n * @abstract\n */\nclass BaseLayer {\n /**\n * Creates a new BaseLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @throws {Error} If container is not a valid HTMLElement\n * @throws {Error} If viewport is missing required properties\n * @throws {Error} If instantiated directly (abstract class)\n */\n constructor(container, viewport) {\n // Validate parameters\n this._validateContainer(container);\n this._validateViewport(viewport);\n\n // Initialize core properties\n this.container = container;\n this.viewport = { ...viewport };\n this.annotations = [];\n this.currentTime = 0;\n this.isDestroyed = false;\n\n // Prevent direct instantiation\n if (new.target === BaseLayer) {\n throw new Error('BaseLayer is an abstract class and cannot be instantiated directly. Extend it with a concrete implementation.');\n }\n }\n\n /**\n * Sets the annotation data for this layer\n *\n * @param {Array} annotations - Array of annotation objects\n * @throws {Error} If called after layer is destroyed\n */\n setAnnotations(annotations) {\n this._checkDestroyed('setAnnotations');\n this.annotations = annotations || [];\n }\n\n /**\n * Updates the viewport dimensions\n *\n * @param {Object} viewport - New viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n * @throws {Error} If viewport is missing required properties\n * @throws {Error} If called after layer is destroyed\n */\n setViewport(viewport) {\n this._checkDestroyed('setViewport');\n this._validateViewport(viewport);\n this.viewport = { ...viewport };\n }\n\n /**\n * Updates the current timeline position\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n */\n updateTime(nowSec) {\n this._checkDestroyed('updateTime');\n this.currentTime = nowSec;\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Safe to call multiple times (idempotent).\n * Subclasses must call super.destroy() after their own cleanup.\n */\n destroy() {\n if (this.isDestroyed) {\n return;\n }\n\n this.annotations = null;\n this.viewport = null;\n this.container = null;\n this.isDestroyed = true;\n }\n\n /**\n * Renders the layer content\n *\n * @abstract\n * @throws {Error} If not implemented by subclass\n */\n render() {\n throw new Error('render() must be implemented by subclass');\n }\n\n /**\n * Updates the visual state of the layer\n *\n * @abstract\n * @throws {Error} If not implemented by subclass\n */\n update() {\n throw new Error('update() must be implemented by subclass');\n }\n\n /**\n * Validates that container is a valid HTMLElement\n *\n * @private\n * @param {*} container - Value to validate\n * @throws {Error} If container is not a valid HTMLElement\n */\n _validateContainer(container) {\n if (!container || !(container instanceof HTMLElement)) {\n throw new Error('BaseLayer: container must be a valid HTMLElement');\n }\n }\n\n /**\n * Validates that viewport has required properties\n *\n * @private\n * @param {*} viewport - Value to validate\n * @throws {Error} If viewport is missing required properties\n */\n _validateViewport(viewport) {\n if (!viewport || typeof viewport !== 'object') {\n throw new Error('BaseLayer: viewport must be an object');\n }\n\n if (typeof viewport.width !== 'number' || viewport.width <= 0) {\n throw new Error('BaseLayer: viewport.width must be a positive number');\n }\n\n if (typeof viewport.height !== 'number' || viewport.height <= 0) {\n throw new Error('BaseLayer: viewport.height must be a positive number');\n }\n\n if (typeof viewport.scale !== 'number' || viewport.scale <= 0) {\n throw new Error('BaseLayer: viewport.scale must be a positive number');\n }\n }\n\n /**\n * Checks if layer is destroyed and throws error if so\n *\n * @private\n * @param {string} methodName - Name of method being called\n * @throws {Error} If layer is destroyed\n */\n _checkDestroyed(methodName) {\n if (this.isDestroyed) {\n throw new Error(`BaseLayer: Cannot call ${methodName}() on destroyed layer`);\n }\n }\n}\n\nexport default BaseLayer;\n"],"names":["BaseLayer","container","viewport","annotations","nowSec","methodName"],"mappings":"AAQA,MAAMA,EAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAad,YAAYC,GAAWC,GAAU;AAa/B,QAXA,KAAK,mBAAmBD,CAAS,GACjC,KAAK,kBAAkBC,CAAQ,GAG/B,KAAK,YAAYD,GACjB,KAAK,WAAW,EAAE,GAAGC,EAAQ,GAC7B,KAAK,cAAc,CAAA,GACnB,KAAK,cAAc,GACnB,KAAK,cAAc,IAGf,eAAeF;AACjB,YAAM,IAAI,MAAM,+GAA+G;AAAA,EAEnI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAeG,GAAa;AAC1B,SAAK,gBAAgB,gBAAgB,GACrC,KAAK,cAAcA,KAAe,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,YAAYD,GAAU;AACpB,SAAK,gBAAgB,aAAa,GAClC,KAAK,kBAAkBA,CAAQ,GAC/B,KAAK,WAAW,EAAE,GAAGA,EAAQ;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAWE,GAAQ;AACjB,SAAK,gBAAgB,YAAY,GACjC,KAAK,cAAcA;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU;AACR,IAAI,KAAK,gBAIT,KAAK,cAAc,MACnB,KAAK,WAAW,MAChB,KAAK,YAAY,MACjB,KAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS;AACP,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS;AACP,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAmBH,GAAW;AAC5B,QAAI,CAACA,KAAa,EAAEA,aAAqB;AACvC,YAAM,IAAI,MAAM,kDAAkD;AAAA,EAEtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,kBAAkBC,GAAU;AAC1B,QAAI,CAACA,KAAY,OAAOA,KAAa;AACnC,YAAM,IAAI,MAAM,uCAAuC;AAGzD,QAAI,OAAOA,EAAS,SAAU,YAAYA,EAAS,SAAS;AAC1D,YAAM,IAAI,MAAM,qDAAqD;AAGvE,QAAI,OAAOA,EAAS,UAAW,YAAYA,EAAS,UAAU;AAC5D,YAAM,IAAI,MAAM,sDAAsD;AAGxE,QAAI,OAAOA,EAAS,SAAU,YAAYA,EAAS,SAAS;AAC1D,YAAM,IAAI,MAAM,qDAAqD;AAAA,EAEzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,gBAAgBG,GAAY;AAC1B,QAAI,KAAK;AACP,YAAM,IAAI,MAAM,0BAA0BA,CAAU,uBAAuB;AAAA,EAE/E;AACF;"}
1
+ {"version":3,"file":"index6.js","sources":["../src/pen/effects.js"],"sourcesContent":["/**\n * Pen Effects - Utility functions for hand-drawn feel\n *\n * Provides jitter, pressure, and wobble effects for stroke paths.\n * Pure functions that transform point arrays without side effects.\n *\n * @module pen/effects\n */\n\n/**\n * Creates a seeded random number generator\n *\n * Uses mulberry32 algorithm for deterministic randomness.\n * Same seed produces same sequence of random numbers.\n *\n * @param {string|number|null} seed - Seed value (null uses Math.random)\n * @returns {Function} Function that returns random numbers 0-1\n */\nexport function seededRandom(seed) {\n if (seed === null || seed === undefined) {\n return Math.random;\n }\n\n // Convert string seed to number\n let numSeed = typeof seed === 'string'\n ? seed.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)\n : seed;\n\n // Mulberry32 algorithm\n return function() {\n numSeed |= 0;\n numSeed = (numSeed + 0x6D2B79F5) | 0;\n let t = Math.imul(numSeed ^ (numSeed >>> 15), 1 | numSeed);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/**\n * Applies random jitter offset to points\n *\n * Adds small random displacement to each point for hand-drawn imperfection.\n * Returns new array, does not mutate input.\n *\n * @param {Array<[number, number]>} points - Array of [x, y] coordinates\n * @param {Object} config - Jitter configuration\n * @param {number} config.amplitude - Max offset in normalized units (0 = disabled)\n * @param {number} [config.frequency=1] - Not currently used, reserved for future\n * @param {string|number|null} [seed=null] - Seed for reproducible randomness\n * @returns {Array<[number, number]>} New array with jittered points\n */\nexport function applyJitter(points, config, seed = null) {\n const { amplitude = 0 } = config || {};\n\n if (amplitude === 0 || !points || points.length === 0) {\n return points;\n }\n\n const rng = seededRandom(seed);\n\n return points.map(([x, y]) => [\n x + (rng() - 0.5) * amplitude,\n y + (rng() - 0.5) * amplitude\n ]);\n}\n\n/**\n * Calculates pressure values for variable stroke width\n *\n * Simulates pen pressure with taper at start and end of stroke.\n * Returns pressure multipliers (0-1) for each point.\n *\n * @param {Array<[number, number]>} points - Array of [x, y] coordinates\n * @param {Object} config - Pressure configuration\n * @param {number} [config.taperIn=0] - Start taper length (0-1, fraction of stroke)\n * @param {number} [config.taperOut=0] - End taper length (0-1, fraction of stroke)\n * @returns {Array<number>} Pressure values (0-1) per point\n */\nexport function applyPressure(points, config) {\n const { taperIn = 0, taperOut = 0 } = config || {};\n\n if (!points || points.length === 0) {\n return [];\n }\n\n if (taperIn === 0 && taperOut === 0) {\n return points.map(() => 1.0);\n }\n\n const len = points.length;\n\n return points.map((_, i) => {\n const t = len > 1 ? i / (len - 1) : 0;\n\n // Taper in at start\n if (taperIn > 0 && t < taperIn) {\n return t / taperIn;\n }\n\n // Taper out at end\n if (taperOut > 0 && t > 1 - taperOut) {\n return (1 - t) / taperOut;\n }\n\n // Full pressure in middle\n return 1.0;\n });\n}\n\n/**\n * Applies low-frequency wobble perpendicular to stroke direction\n *\n * Adds gentle wave effect to simulate natural hand movement.\n * Returns new array, does not mutate input.\n *\n * @param {Array<[number, number]>} points - Array of [x, y] coordinates\n * @param {Object} config - Wobble configuration\n * @param {number} config.amplitude - Wave height in normalized units (0 = disabled)\n * @param {number} [config.frequency=0.05] - Wave frequency\n * @returns {Array<[number, number]>} New array with wobbled points\n */\nexport function applyWobble(points, config) {\n const { amplitude = 0, frequency = 0.05 } = config || {};\n\n if (amplitude === 0 || !points || points.length < 2) {\n return points;\n }\n\n return points.map(([x, y], i) => {\n // Calculate perpendicular direction based on position in stroke\n // Use simple sine wave for now\n const t = i / (points.length - 1);\n const offset = Math.sin(t * Math.PI * 2 * frequency * points.length) * amplitude;\n\n // Calculate perpendicular direction from neighbors\n let perpX = 0;\n let perpY = 1;\n\n if (i < points.length - 1) {\n const [nx, ny] = points[i + 1];\n const dx = nx - x;\n const dy = ny - y;\n const len = Math.sqrt(dx * dx + dy * dy);\n\n if (len > 0.0001) {\n // Perpendicular is (-dy, dx) normalized\n perpX = -dy / len;\n perpY = dx / len;\n }\n }\n\n return [\n x + perpX * offset,\n y + perpY * offset\n ];\n });\n}\n\n/**\n * Deep merges configuration objects\n *\n * Merges source into target, handling nested objects.\n * Returns new object, does not mutate inputs.\n *\n * @param {Object} target - Target object\n * @param {Object} source - Source object to merge\n * @returns {Object} Merged object\n */\nexport function deepMerge(target, source) {\n if (!source) return { ...target };\n if (!target) return { ...source };\n\n const result = { ...target };\n\n for (const key of Object.keys(source)) {\n const sourceVal = source[key];\n const targetVal = target[key];\n\n if (\n sourceVal !== null &&\n typeof sourceVal === 'object' &&\n !Array.isArray(sourceVal) &&\n targetVal !== null &&\n typeof targetVal === 'object' &&\n !Array.isArray(targetVal)\n ) {\n result[key] = deepMerge(targetVal, sourceVal);\n } else if (sourceVal !== undefined) {\n result[key] = sourceVal;\n }\n }\n\n return result;\n}\n"],"names":["seededRandom","seed","numSeed","acc","char","t","applyJitter","points","config","amplitude","rng","x","y","applyPressure","taperIn","taperOut","len","_","i","applyWobble","frequency","offset","perpX","perpY","nx","ny","dx","dy","deepMerge","target","source","result","key","sourceVal","targetVal"],"mappings":"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"}
package/dist/index7.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const c=require("./index6.cjs"),u=require("./index10.cjs");class p extends c.default{constructor(e,a){super(e,a),this.layerElement=document.createElement("div"),this.layerElement.style.position="absolute",this.layerElement.style.inset="0",this.layerElement.style.pointerEvents="none",this.layerElement.style.zIndex="25",this.container.appendChild(this.layerElement),this.elements=new Map}render(){this.layerElement.innerHTML="",this.elements.clear(),this.annotations.forEach(e=>{if(e.mode!=="quads"||!e.quads?.length)return;const a=e.quads.reduce((r,s)=>r+s.w,0);e.quads.forEach((r,s)=>{const i=u.rectNormToAbs(r,this.viewport),n=e.quads.slice(0,s).reduce((y,m)=>y+m.w,0),h=n/a,d=(n+r.w)/a,t=document.createElement("div");t.style.position="absolute",t.style.left=`${i.left}px`,t.style.top=`${i.top}px`,t.style.width=`${i.width}px`,t.style.height=`${i.height}px`,t.style.overflow="hidden",t.style.borderRadius="2px";const l=document.createElement("div");l.style.width="100%",l.style.height="100%",l.style.background=e?.style?.color??"rgba(255,230,100,0.35)",l.style.outline="1px solid rgba(255,200,0,0.6)",l.style.transformOrigin="left center",l.style.transform="scaleX(0)",l.style.willChange="transform",t.appendChild(l),this.layerElement.appendChild(t);const o=`${e.id}-${s}`;this.elements.set(o,{element:l,wrapper:t,annotation:e,segStart:h,segEnd:d})})})}updateTime(e){super.updateTime(e),!this.isDestroyed&&this.elements.forEach(({element:a,wrapper:r,annotation:s,segStart:i,segEnd:n})=>{if(e<s.start)r.style.display="none";else{r.style.display="block";const h=Math.max(0,Math.min(1,(e-s.start)/Math.max(1e-6,s.end-s.start))),d=Math.max(0,Math.min(1,(h-i)/Math.max(1e-6,n-i)));a.style.transform=`scaleX(${d})`}})}update(){}destroy(){this.elements.clear(),this.elements=null,this.layerElement&&this.layerElement.parentNode&&this.layerElement.parentNode.removeChild(this.layerElement),this.layerElement=null,super.destroy()}}exports.default=p;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=(t,h)=>({left:t.x*h.width,top:t.y*h.height,width:(t.w??0)*h.width,height:(t.h??0)*h.height}),i=(t,h)=>({left:t.x*h.width,top:t.y*h.height,width:(t.w??0)*h.width,height:(t.h??0)*h.height});function o(t,h){return{x:t.x*h.width,y:t.y*h.height}}exports.NormSizeToPixel=i;exports.pointNormToAbs=o;exports.rectNormToAbs=e;
2
2
  //# sourceMappingURL=index7.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index7.cjs","sources":["../src/layers/HighlightLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\nimport { rectNormToAbs } from '../utils/coordinateUtils.js';\n\n/**\n * HighlightLayer - Renders highlight annotations with progressive reveal\n *\n * Extends BaseLayer to render rectangular highlight regions (quads) with\n * progressive left-to-right scaleX animation based on timeline position.\n * Supports multi-line highlights with per-quad timing segments.\n *\n * @extends BaseLayer\n */\nclass HighlightLayer extends BaseLayer {\n /**\n * Creates a new HighlightLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create layer container element\n this.layerElement = document.createElement('div');\n this.layerElement.style.position = 'absolute';\n this.layerElement.style.inset = '0';\n this.layerElement.style.pointerEvents = 'none';\n this.layerElement.style.zIndex = '25';\n\n this.container.appendChild(this.layerElement);\n\n // Initialize element storage\n this.elements = new Map();\n }\n\n /**\n * Renders highlight elements for all annotations\n *\n * Creates DOM structure for each quad in each annotation. Calculates\n * timing segments for progressive animation. Clears and recreates all\n * elements when called.\n */\n render() {\n // Clear existing elements\n this.layerElement.innerHTML = '';\n this.elements.clear();\n\n // Process each annotation\n this.annotations.forEach((annotation) => {\n // Skip if not quad mode or no quads\n if (annotation.mode !== 'quads' || !annotation.quads?.length) {\n return;\n }\n\n // Calculate total width across all quads\n const totalW = annotation.quads.reduce((sum, quad) => sum + quad.w, 0);\n\n // Process each quad\n annotation.quads.forEach((quad, idx) => {\n // Convert normalized coordinates to absolute pixels\n const abs = rectNormToAbs(quad, this.viewport);\n\n // Calculate timing segment for this quad\n const prevW = annotation.quads.slice(0, idx).reduce((sum, q) => sum + q.w, 0);\n const segStart = prevW / totalW;\n const segEnd = (prevW + quad.w) / totalW;\n\n // Create wrapper div\n const wrapper = document.createElement('div');\n wrapper.style.position = 'absolute';\n wrapper.style.left = `${abs.left}px`;\n wrapper.style.top = `${abs.top}px`;\n wrapper.style.width = `${abs.width}px`;\n wrapper.style.height = `${abs.height}px`;\n wrapper.style.overflow = 'hidden';\n wrapper.style.borderRadius = '2px';\n\n // Create highlight div\n const highlight = document.createElement('div');\n highlight.style.width = '100%';\n highlight.style.height = '100%';\n highlight.style.background = annotation?.style?.color ?? 'rgba(255,230,100,0.35)';\n highlight.style.outline = '1px solid rgba(255,200,0,0.6)';\n highlight.style.transformOrigin = 'left center';\n highlight.style.transform = 'scaleX(0)';\n highlight.style.willChange = 'transform';\n\n // Assemble DOM structure\n wrapper.appendChild(highlight);\n this.layerElement.appendChild(wrapper);\n\n // Store reference for animation\n const key = `${annotation.id}-${idx}`;\n this.elements.set(key, {\n element: highlight,\n wrapper: wrapper,\n annotation: annotation,\n segStart: segStart,\n segEnd: segEnd\n });\n });\n });\n }\n\n /**\n * Updates highlight animations based on current timeline position\n *\n * Updates scaleX transform for each highlight element based on timeline.\n * Calculates progress for each quad segment and updates visibility.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n if (this.isDestroyed) {\n return;\n }\n\n // Update each highlight element\n this.elements.forEach(({ element, wrapper, annotation, segStart, segEnd }) => {\n // Hide wrapper if time hasn't reached annotation start\n if (nowSec < annotation.start) {\n wrapper.style.display = 'none';\n } else {\n // Show wrapper\n wrapper.style.display = 'block';\n\n // Calculate global progress (0 to 1)\n const globalProgress = Math.max(\n 0,\n Math.min(\n 1,\n (nowSec - annotation.start) / Math.max(1e-6, annotation.end - annotation.start)\n )\n );\n\n // Calculate local progress for this quad segment (0 to 1)\n const localProgress = Math.max(\n 0,\n Math.min(\n 1,\n (globalProgress - segStart) / Math.max(1e-6, segEnd - segStart)\n )\n );\n\n // Apply scaleX transform\n element.style.transform = `scaleX(${localProgress})`;\n }\n });\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used by HighlightLayer - animation handled in updateTime()\n */\n update() {\n // Not used - updateTime handles animation directly\n }\n\n /**\n * Destroys the layer and releases all resources\n *\n * Clears element storage, removes DOM elements, and calls parent cleanup.\n */\n destroy() {\n // Clear element storage\n this.elements.clear();\n this.elements = null;\n\n // Remove layer element from DOM\n if (this.layerElement && this.layerElement.parentNode) {\n this.layerElement.parentNode.removeChild(this.layerElement);\n }\n this.layerElement = null;\n\n // Call parent destroy\n super.destroy();\n }\n}\n\nexport default HighlightLayer;\n"],"names":["HighlightLayer","BaseLayer","container","viewport","annotation","totalW","sum","quad","idx","abs","rectNormToAbs","prevW","q","segStart","segEnd","wrapper","highlight","key","nowSec","element","globalProgress","localProgress"],"mappings":"uKAYA,MAAMA,UAAuBC,EAAAA,OAAU,CAUrC,YAAYC,EAAWC,EAAU,CAC/B,MAAMD,EAAWC,CAAQ,EAGzB,KAAK,aAAe,SAAS,cAAc,KAAK,EAChD,KAAK,aAAa,MAAM,SAAW,WACnC,KAAK,aAAa,MAAM,MAAQ,IAChC,KAAK,aAAa,MAAM,cAAgB,OACxC,KAAK,aAAa,MAAM,OAAS,KAEjC,KAAK,UAAU,YAAY,KAAK,YAAY,EAG5C,KAAK,SAAW,IAAI,GACtB,CASA,QAAS,CAEP,KAAK,aAAa,UAAY,GAC9B,KAAK,SAAS,MAAK,EAGnB,KAAK,YAAY,QAASC,GAAe,CAEvC,GAAIA,EAAW,OAAS,SAAW,CAACA,EAAW,OAAO,OACpD,OAIF,MAAMC,EAASD,EAAW,MAAM,OAAO,CAACE,EAAKC,IAASD,EAAMC,EAAK,EAAG,CAAC,EAGrEH,EAAW,MAAM,QAAQ,CAACG,EAAMC,IAAQ,CAEtC,MAAMC,EAAMC,EAAAA,cAAcH,EAAM,KAAK,QAAQ,EAGvCI,EAAQP,EAAW,MAAM,MAAM,EAAGI,CAAG,EAAE,OAAO,CAACF,EAAKM,IAAMN,EAAMM,EAAE,EAAG,CAAC,EACtEC,EAAWF,EAAQN,EACnBS,GAAUH,EAAQJ,EAAK,GAAKF,EAG5BU,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,MAAM,SAAW,WACzBA,EAAQ,MAAM,KAAO,GAAGN,EAAI,IAAI,KAChCM,EAAQ,MAAM,IAAM,GAAGN,EAAI,GAAG,KAC9BM,EAAQ,MAAM,MAAQ,GAAGN,EAAI,KAAK,KAClCM,EAAQ,MAAM,OAAS,GAAGN,EAAI,MAAM,KACpCM,EAAQ,MAAM,SAAW,SACzBA,EAAQ,MAAM,aAAe,MAG7B,MAAMC,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,MAAM,MAAQ,OACxBA,EAAU,MAAM,OAAS,OACzBA,EAAU,MAAM,WAAaZ,GAAY,OAAO,OAAS,yBACzDY,EAAU,MAAM,QAAU,gCAC1BA,EAAU,MAAM,gBAAkB,cAClCA,EAAU,MAAM,UAAY,YAC5BA,EAAU,MAAM,WAAa,YAG7BD,EAAQ,YAAYC,CAAS,EAC7B,KAAK,aAAa,YAAYD,CAAO,EAGrC,MAAME,EAAM,GAAGb,EAAW,EAAE,IAAII,CAAG,GACnC,KAAK,SAAS,IAAIS,EAAK,CACrB,QAASD,EACT,QAASD,EACT,WAAYX,EACZ,SAAUS,EACV,OAAQC,CAClB,CAAS,CACH,CAAC,CACH,CAAC,CACH,CAWA,WAAWI,EAAQ,CACjB,MAAM,WAAWA,CAAM,EAEnB,MAAK,aAKT,KAAK,SAAS,QAAQ,CAAC,CAAE,QAAAC,EAAS,QAAAJ,EAAS,WAAAX,EAAY,SAAAS,EAAU,OAAAC,KAAa,CAE5E,GAAII,EAASd,EAAW,MACtBW,EAAQ,MAAM,QAAU,WACnB,CAELA,EAAQ,MAAM,QAAU,QAGxB,MAAMK,EAAiB,KAAK,IAC1B,EACA,KAAK,IACH,GACCF,EAASd,EAAW,OAAS,KAAK,IAAI,KAAMA,EAAW,IAAMA,EAAW,KAAK,CAC1F,CACA,EAGciB,EAAgB,KAAK,IACzB,EACA,KAAK,IACH,GACCD,EAAiBP,GAAY,KAAK,IAAI,KAAMC,EAASD,CAAQ,CAC1E,CACA,EAGQM,EAAQ,MAAM,UAAY,UAAUE,CAAa,GACnD,CACF,CAAC,CACH,CAOA,QAAS,CAET,CAOA,SAAU,CAER,KAAK,SAAS,MAAK,EACnB,KAAK,SAAW,KAGZ,KAAK,cAAgB,KAAK,aAAa,YACzC,KAAK,aAAa,WAAW,YAAY,KAAK,YAAY,EAE5D,KAAK,aAAe,KAGpB,MAAM,QAAO,CACf,CACF"}
1
+ {"version":3,"file":"index7.cjs","sources":["../src/utils/coordinateUtils.js"],"sourcesContent":["/**\n * Coordinate Utility Functions\n *\n * This module provides utility functions for coordinate transformations\n * between normalized (0-1) coordinates and absolute pixel coordinates.\n * Used by annotation layers to position elements on the PDF canvas.\n */\n\n/**\n * Convert normalized rectangle to absolute pixel coordinates\n *\n * Transforms a rectangle with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number, w: number, h: number}} rect - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n *\n * @example\n * const rect = { x: 0.1, y: 0.2, w: 0.5, h: 0.3 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = rectNormToAbs(rect, viewport);\n * // Returns: { left: 100, top: 280, width: 500, height: 420 }\n */\nexport const rectNormToAbs = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized size to pixel dimensions (Legacy)\n *\n * @deprecated Use rectNormToAbs instead. This function is kept for backward compatibility.\n *\n * Transforms normalized rectangle coordinates to absolute pixel coordinates.\n * This is an alias for rectNormToAbs maintained for backward compatibility.\n *\n * @param {{x: number, y: number, w: number, h: number}} r - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} vp - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n */\nexport const NormSizeToPixel = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized point to absolute pixel coordinates\n *\n * Transforms a point with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number}} point - Normalized point (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{x: number, y: number}} Absolute coordinates in pixels\n *\n * @example\n * const point = { x: 0.5, y: 0.5 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = pointNormToAbs(point, viewport);\n * // Returns: { x: 500, y: 700 }\n */\nexport function pointNormToAbs(point, viewport) {\n return {\n x: point.x * viewport.width,\n y: point.y * viewport.height\n };\n}\n"],"names":["rectNormToAbs","r","vp","NormSizeToPixel","pointNormToAbs","point","viewport"],"mappings":"gFAwBY,MAACA,EAAgB,CAACC,EAAGC,KAAQ,CACvC,KAAMD,EAAE,EAAIC,EAAG,MACf,IAAKD,EAAE,EAAIC,EAAG,OACd,OAAQD,EAAE,GAAK,GAAKC,EAAG,MACvB,QAASD,EAAE,GAAK,GAAKC,EAAG,MAC1B,GAcaC,EAAkB,CAACF,EAAGC,KAAQ,CACzC,KAAMD,EAAE,EAAIC,EAAG,MACf,IAAKD,EAAE,EAAIC,EAAG,OACd,OAAQD,EAAE,GAAK,GAAKC,EAAG,MACvB,QAASD,EAAE,GAAK,GAAKC,EAAG,MAC1B,GAkBO,SAASE,EAAeC,EAAOC,EAAU,CAC9C,MAAO,CACL,EAAGD,EAAM,EAAIC,EAAS,MACtB,EAAGD,EAAM,EAAIC,EAAS,MAC1B,CACA"}
package/dist/index7.js CHANGED
@@ -1,95 +1,23 @@
1
- import p from "./index6.js";
2
- import { rectNormToAbs as c } from "./index10.js";
3
- class f extends p {
4
- /**
5
- * Creates a new HighlightLayer instance
6
- *
7
- * @param {HTMLElement} container - Parent DOM element for layer content
8
- * @param {Object} viewport - Initial viewport dimensions
9
- * @param {number} viewport.width - Viewport width in pixels
10
- * @param {number} viewport.height - Viewport height in pixels
11
- * @param {number} viewport.scale - PDF scale/zoom level
12
- */
13
- constructor(e, a) {
14
- super(e, a), this.layerElement = document.createElement("div"), this.layerElement.style.position = "absolute", this.layerElement.style.inset = "0", this.layerElement.style.pointerEvents = "none", this.layerElement.style.zIndex = "25", this.container.appendChild(this.layerElement), this.elements = /* @__PURE__ */ new Map();
15
- }
16
- /**
17
- * Renders highlight elements for all annotations
18
- *
19
- * Creates DOM structure for each quad in each annotation. Calculates
20
- * timing segments for progressive animation. Clears and recreates all
21
- * elements when called.
22
- */
23
- render() {
24
- this.layerElement.innerHTML = "", this.elements.clear(), this.annotations.forEach((e) => {
25
- if (e.mode !== "quads" || !e.quads?.length)
26
- return;
27
- const a = e.quads.reduce((r, s) => r + s.w, 0);
28
- e.quads.forEach((r, s) => {
29
- const i = c(r, this.viewport), h = e.quads.slice(0, s).reduce((o, y) => o + y.w, 0), n = h / a, d = (h + r.w) / a, t = document.createElement("div");
30
- t.style.position = "absolute", t.style.left = `${i.left}px`, t.style.top = `${i.top}px`, t.style.width = `${i.width}px`, t.style.height = `${i.height}px`, t.style.overflow = "hidden", t.style.borderRadius = "2px";
31
- const l = document.createElement("div");
32
- l.style.width = "100%", l.style.height = "100%", l.style.background = e?.style?.color ?? "rgba(255,230,100,0.35)", l.style.outline = "1px solid rgba(255,200,0,0.6)", l.style.transformOrigin = "left center", l.style.transform = "scaleX(0)", l.style.willChange = "transform", t.appendChild(l), this.layerElement.appendChild(t);
33
- const m = `${e.id}-${s}`;
34
- this.elements.set(m, {
35
- element: l,
36
- wrapper: t,
37
- annotation: e,
38
- segStart: n,
39
- segEnd: d
40
- });
41
- });
42
- });
43
- }
44
- /**
45
- * Updates highlight animations based on current timeline position
46
- *
47
- * Updates scaleX transform for each highlight element based on timeline.
48
- * Calculates progress for each quad segment and updates visibility.
49
- * Renders once per call - no continuous loop.
50
- *
51
- * @param {number} nowSec - Current timeline position in seconds
52
- */
53
- updateTime(e) {
54
- super.updateTime(e), !this.isDestroyed && this.elements.forEach(({ element: a, wrapper: r, annotation: s, segStart: i, segEnd: h }) => {
55
- if (e < s.start)
56
- r.style.display = "none";
57
- else {
58
- r.style.display = "block";
59
- const n = Math.max(
60
- 0,
61
- Math.min(
62
- 1,
63
- (e - s.start) / Math.max(1e-6, s.end - s.start)
64
- )
65
- ), d = Math.max(
66
- 0,
67
- Math.min(
68
- 1,
69
- (n - i) / Math.max(1e-6, h - i)
70
- )
71
- );
72
- a.style.transform = `scaleX(${d})`;
73
- }
74
- });
75
- }
76
- /**
77
- * Updates the visual state of the layer
78
- *
79
- * Not used by HighlightLayer - animation handled in updateTime()
80
- */
81
- update() {
82
- }
83
- /**
84
- * Destroys the layer and releases all resources
85
- *
86
- * Clears element storage, removes DOM elements, and calls parent cleanup.
87
- */
88
- destroy() {
89
- this.elements.clear(), this.elements = null, this.layerElement && this.layerElement.parentNode && this.layerElement.parentNode.removeChild(this.layerElement), this.layerElement = null, super.destroy();
90
- }
1
+ const i = (h, t) => ({
2
+ left: h.x * t.width,
3
+ top: h.y * t.height,
4
+ width: (h.w ?? 0) * t.width,
5
+ height: (h.h ?? 0) * t.height
6
+ }), e = (h, t) => ({
7
+ left: h.x * t.width,
8
+ top: h.y * t.height,
9
+ width: (h.w ?? 0) * t.width,
10
+ height: (h.h ?? 0) * t.height
11
+ });
12
+ function o(h, t) {
13
+ return {
14
+ x: h.x * t.width,
15
+ y: h.y * t.height
16
+ };
91
17
  }
92
18
  export {
93
- f as default
19
+ e as NormSizeToPixel,
20
+ o as pointNormToAbs,
21
+ i as rectNormToAbs
94
22
  };
95
23
  //# sourceMappingURL=index7.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index7.js","sources":["../src/layers/HighlightLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\nimport { rectNormToAbs } from '../utils/coordinateUtils.js';\n\n/**\n * HighlightLayer - Renders highlight annotations with progressive reveal\n *\n * Extends BaseLayer to render rectangular highlight regions (quads) with\n * progressive left-to-right scaleX animation based on timeline position.\n * Supports multi-line highlights with per-quad timing segments.\n *\n * @extends BaseLayer\n */\nclass HighlightLayer extends BaseLayer {\n /**\n * Creates a new HighlightLayer instance\n *\n * @param {HTMLElement} container - Parent DOM element for layer content\n * @param {Object} viewport - Initial viewport dimensions\n * @param {number} viewport.width - Viewport width in pixels\n * @param {number} viewport.height - Viewport height in pixels\n * @param {number} viewport.scale - PDF scale/zoom level\n */\n constructor(container, viewport) {\n super(container, viewport);\n\n // Create layer container element\n this.layerElement = document.createElement('div');\n this.layerElement.style.position = 'absolute';\n this.layerElement.style.inset = '0';\n this.layerElement.style.pointerEvents = 'none';\n this.layerElement.style.zIndex = '25';\n\n this.container.appendChild(this.layerElement);\n\n // Initialize element storage\n this.elements = new Map();\n }\n\n /**\n * Renders highlight elements for all annotations\n *\n * Creates DOM structure for each quad in each annotation. Calculates\n * timing segments for progressive animation. Clears and recreates all\n * elements when called.\n */\n render() {\n // Clear existing elements\n this.layerElement.innerHTML = '';\n this.elements.clear();\n\n // Process each annotation\n this.annotations.forEach((annotation) => {\n // Skip if not quad mode or no quads\n if (annotation.mode !== 'quads' || !annotation.quads?.length) {\n return;\n }\n\n // Calculate total width across all quads\n const totalW = annotation.quads.reduce((sum, quad) => sum + quad.w, 0);\n\n // Process each quad\n annotation.quads.forEach((quad, idx) => {\n // Convert normalized coordinates to absolute pixels\n const abs = rectNormToAbs(quad, this.viewport);\n\n // Calculate timing segment for this quad\n const prevW = annotation.quads.slice(0, idx).reduce((sum, q) => sum + q.w, 0);\n const segStart = prevW / totalW;\n const segEnd = (prevW + quad.w) / totalW;\n\n // Create wrapper div\n const wrapper = document.createElement('div');\n wrapper.style.position = 'absolute';\n wrapper.style.left = `${abs.left}px`;\n wrapper.style.top = `${abs.top}px`;\n wrapper.style.width = `${abs.width}px`;\n wrapper.style.height = `${abs.height}px`;\n wrapper.style.overflow = 'hidden';\n wrapper.style.borderRadius = '2px';\n\n // Create highlight div\n const highlight = document.createElement('div');\n highlight.style.width = '100%';\n highlight.style.height = '100%';\n highlight.style.background = annotation?.style?.color ?? 'rgba(255,230,100,0.35)';\n highlight.style.outline = '1px solid rgba(255,200,0,0.6)';\n highlight.style.transformOrigin = 'left center';\n highlight.style.transform = 'scaleX(0)';\n highlight.style.willChange = 'transform';\n\n // Assemble DOM structure\n wrapper.appendChild(highlight);\n this.layerElement.appendChild(wrapper);\n\n // Store reference for animation\n const key = `${annotation.id}-${idx}`;\n this.elements.set(key, {\n element: highlight,\n wrapper: wrapper,\n annotation: annotation,\n segStart: segStart,\n segEnd: segEnd\n });\n });\n });\n }\n\n /**\n * Updates highlight animations based on current timeline position\n *\n * Updates scaleX transform for each highlight element based on timeline.\n * Calculates progress for each quad segment and updates visibility.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n if (this.isDestroyed) {\n return;\n }\n\n // Update each highlight element\n this.elements.forEach(({ element, wrapper, annotation, segStart, segEnd }) => {\n // Hide wrapper if time hasn't reached annotation start\n if (nowSec < annotation.start) {\n wrapper.style.display = 'none';\n } else {\n // Show wrapper\n wrapper.style.display = 'block';\n\n // Calculate global progress (0 to 1)\n const globalProgress = Math.max(\n 0,\n Math.min(\n 1,\n (nowSec - annotation.start) / Math.max(1e-6, annotation.end - annotation.start)\n )\n );\n\n // Calculate local progress for this quad segment (0 to 1)\n const localProgress = Math.max(\n 0,\n Math.min(\n 1,\n (globalProgress - segStart) / Math.max(1e-6, segEnd - segStart)\n )\n );\n\n // Apply scaleX transform\n element.style.transform = `scaleX(${localProgress})`;\n }\n });\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used by HighlightLayer - animation handled in updateTime()\n */\n update() {\n // Not used - updateTime handles animation directly\n }\n\n /**\n * Destroys the layer and releases all resources\n *\n * Clears element storage, removes DOM elements, and calls parent cleanup.\n */\n destroy() {\n // Clear element storage\n this.elements.clear();\n this.elements = null;\n\n // Remove layer element from DOM\n if (this.layerElement && this.layerElement.parentNode) {\n this.layerElement.parentNode.removeChild(this.layerElement);\n }\n this.layerElement = null;\n\n // Call parent destroy\n super.destroy();\n }\n}\n\nexport default HighlightLayer;\n"],"names":["HighlightLayer","BaseLayer","container","viewport","annotation","totalW","sum","quad","idx","abs","rectNormToAbs","prevW","q","segStart","segEnd","wrapper","highlight","key","nowSec","element","globalProgress","localProgress"],"mappings":"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"}
1
+ {"version":3,"file":"index7.js","sources":["../src/utils/coordinateUtils.js"],"sourcesContent":["/**\n * Coordinate Utility Functions\n *\n * This module provides utility functions for coordinate transformations\n * between normalized (0-1) coordinates and absolute pixel coordinates.\n * Used by annotation layers to position elements on the PDF canvas.\n */\n\n/**\n * Convert normalized rectangle to absolute pixel coordinates\n *\n * Transforms a rectangle with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number, w: number, h: number}} rect - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n *\n * @example\n * const rect = { x: 0.1, y: 0.2, w: 0.5, h: 0.3 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = rectNormToAbs(rect, viewport);\n * // Returns: { left: 100, top: 280, width: 500, height: 420 }\n */\nexport const rectNormToAbs = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized size to pixel dimensions (Legacy)\n *\n * @deprecated Use rectNormToAbs instead. This function is kept for backward compatibility.\n *\n * Transforms normalized rectangle coordinates to absolute pixel coordinates.\n * This is an alias for rectNormToAbs maintained for backward compatibility.\n *\n * @param {{x: number, y: number, w: number, h: number}} r - Normalized rectangle (0-1)\n * @param {{width: number, height: number}} vp - Viewport dimensions in pixels\n * @returns {{left: number, top: number, width: number, height: number}} Absolute coordinates in pixels\n */\nexport const NormSizeToPixel = (r, vp) => ({\n left: r.x * vp.width,\n top: r.y * vp.height,\n width: (r.w ?? 0) * vp.width,\n height: (r.h ?? 0) * vp.height,\n});\n\n/**\n * Convert normalized point to absolute pixel coordinates\n *\n * Transforms a point with normalized coordinates (0-1 range) to\n * absolute pixel coordinates based on viewport dimensions.\n *\n * @param {{x: number, y: number}} point - Normalized point (0-1)\n * @param {{width: number, height: number}} viewport - Viewport dimensions in pixels\n * @returns {{x: number, y: number}} Absolute coordinates in pixels\n *\n * @example\n * const point = { x: 0.5, y: 0.5 };\n * const viewport = { width: 1000, height: 1400 };\n * const absolute = pointNormToAbs(point, viewport);\n * // Returns: { x: 500, y: 700 }\n */\nexport function pointNormToAbs(point, viewport) {\n return {\n x: point.x * viewport.width,\n y: point.y * viewport.height\n };\n}\n"],"names":["rectNormToAbs","r","vp","NormSizeToPixel","pointNormToAbs","point","viewport"],"mappings":"AAwBY,MAACA,IAAgB,CAACC,GAAGC,OAAQ;AAAA,EACvC,MAAMD,EAAE,IAAIC,EAAG;AAAA,EACf,KAAKD,EAAE,IAAIC,EAAG;AAAA,EACd,QAAQD,EAAE,KAAK,KAAKC,EAAG;AAAA,EACvB,SAASD,EAAE,KAAK,KAAKC,EAAG;AAC1B,IAcaC,IAAkB,CAACF,GAAGC,OAAQ;AAAA,EACzC,MAAMD,EAAE,IAAIC,EAAG;AAAA,EACf,KAAKD,EAAE,IAAIC,EAAG;AAAA,EACd,QAAQD,EAAE,KAAK,KAAKC,EAAG;AAAA,EACvB,SAASD,EAAE,KAAK,KAAKC,EAAG;AAC1B;AAkBO,SAASE,EAAeC,GAAOC,GAAU;AAC9C,SAAO;AAAA,IACL,GAAGD,EAAM,IAAIC,EAAS;AAAA,IACtB,GAAGD,EAAM,IAAIC,EAAS;AAAA,EAC1B;AACA;"}
package/dist/index8.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const h=require("./index6.cjs"),p=require("./index10.cjs");class u extends h.default{constructor(t,s){super(t,s),this.layerElement=document.createElement("div"),this.layerElement.style.position="absolute",this.layerElement.style.inset="0",this.layerElement.style.pointerEvents="none",this.layerElement.style.zIndex="30",this.container.appendChild(this.layerElement),this.textElements=new Map}render(){this.layerElement.innerHTML="",this.textElements.clear(),this.annotations.forEach(t=>{const s=p.rectNormToAbs(t,this.viewport),e=document.createElement("div");e.style.position="absolute",e.style.left=`${s.left}px`,e.style.top=`${s.top}px`,e.style.width=`${s.width}px`,e.style.height=`${s.height}px`,e.style.backgroundColor=t.style?.bg||"rgba(255,255,255,0.9)",e.style.borderRadius="4px",e.style.padding="8px",e.style.fontSize="14px",e.style.lineHeight="1.4",e.style.color=t.style?.color||"#1f2937",e.style.fontFamily="system-ui, -apple-system, sans-serif",e.style.display="flex",e.style.alignItems="center",e.style.justifyContent="flex-start",e.style.overflow="hidden",e.style.wordWrap="break-word",e.style.display="none",this.layerElement.appendChild(e),this.textElements.set(t.id,{element:e,annotation:t})})}updateTime(t){super.updateTime(t),this.textElements.forEach(({element:s,annotation:e})=>{if(t<e.start)s.style.display="none";else{s.style.display="flex";const l=this._getVisibleText(e.content,e.start,e.end,t);s.textContent=l}})}_getVisibleText(t,s,e,l){if(l<s)return"";if(l>=e)return t;const n=(l-s)/(e-s),r=t.split(" "),i=Math.floor(n*r.length);if(i===0)return"";const o=r.slice(0,i);if(i<r.length){const d=n*r.length-i,y=r[i],a=Math.floor(d*y.length);a>0&&o.push(y.slice(0,a))}return o.join(" ")}update(){}destroy(){this.textElements.clear(),this.textElements=null,this.layerElement&&this.layerElement.parentNode&&this.layerElement.parentNode.removeChild(this.layerElement),this.layerElement=null,super.destroy()}}exports.default=u;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function n(e,t){if(!e)throw new Error("Page object is required");return e.getViewport({scale:t})}function r(e){return e?{width:e.width,height:e.height}:{width:0,height:0}}function o(e,t,i){return{width:e*i,height:t*i}}exports.calculateScaledDimensions=o;exports.calculateViewport=n;exports.getViewportDimensions=r;
2
2
  //# sourceMappingURL=index8.cjs.map