web-annotation-renderer 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index14.cjs +1 -1
- package/dist/index14.cjs.map +1 -1
- package/dist/index14.js +32 -32
- package/dist/index14.js.map +1 -1
- package/dist/index7.cjs +1 -1
- package/dist/index7.cjs.map +1 -1
- package/dist/index7.js +38 -43
- package/dist/index7.js.map +1 -1
- package/dist/index9.cjs +1 -1
- package/dist/index9.cjs.map +1 -1
- package/dist/index9.js +27 -32
- package/dist/index9.js.map +1 -1
- package/package.json +1 -1
package/dist/index14.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const d=require("react/jsx-runtime"),n=require("react"),j=require("./index2.cjs");function m({pdfUrl:l,page:c=1,scale:u=1.5,annotations:y=[],currentTime:i=0,onLoad:P,onError:t,onPageChange:A,className:F,style:R,canvasStyle:p}){const f=n.useRef(null),a=n.useRef(null),r=n.useRef(null),h=n.useRef(Promise.resolve()),o=n.useCallback(e=>{h.current=h.current.then(e).catch(v=>{console.error("AnnotPdf: Queued operation failed:",v)})},[]);n.useEffect(()=>{if(!(!f.current||!a.current)){try{r.current=new j.AnnotationRenderer({canvasElement:f.current,container:a.current})}catch(e){console.error("AnnotPdf: Failed to initialize renderer:",e),t&&t(e)}return()=>{r.current&&(r.current.destroy(),r.current=null)}}},[]),n.useEffect(()=>{if(!r.current||!l)return;let e=!1;return o(async()=>{try{const s=await r.current.loadPDF(l);if(e)return;if(!s.success){console.error("AnnotPdf: Failed to load PDF:",s.error),t&&t(new Error(s.error));return}P&&P({pageCount:s.pageCount})}catch(s){if(e)return;console.error("AnnotPdf: Failed to load PDF:",s),t&&t(s)}}),()=>{e=!0}},[l,o]),n.useEffect(()=>{!r.current||!c||typeof c!="number"||o(async()=>{try{const e=await r.current.setPage(c);if(!e.success){console.error("AnnotPdf: Failed to set page:",e.error),t&&t(new Error(e.error));return}A&&A(c)}catch(e){console.error("AnnotPdf: Failed to set page:",e),t&&t(e)}})},[c,o]),n.useEffect(()=>{!r.current||!u||typeof u!="number"||o(async()=>{try{const e=await r.current.setScale(u);e.success||(console.error("AnnotPdf: Failed to set scale:",e.error),t&&t(new Error(e.error)))}catch(e){console.error("AnnotPdf: Failed to set scale:",e),t&&t(e)}})},[u,o]),n.useEffect(()=>{if(r.current)try{r.current.setAnnotations(y||[])}catch(e){console.error("AnnotPdf: Failed to set annotations:",e),t&&t(e)}},[y]),n.useEffect(()=>{if(!(!r.current||i===void 0||i===null))try{r.current.setTime(i)}catch(e){console.error("AnnotPdf: Failed to set time:",e),t&&t(e)}},[i]);const w={position:"relative",display:"inline-block",lineHeight:0,...R},b={position:"absolute",top:0,left:0,width:"100%",height:"100%",pointerEvents:"none",overflow:"hidden"},S={display:"block",...p};return d.jsxs("div",{className:F,style:w,children:[d.jsx("canvas",{ref:f,style:S}),d.jsx("div",{ref:a,style:b})]})}exports.default=m;
|
|
2
2
|
//# sourceMappingURL=index14.cjs.map
|
package/dist/index14.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index14.cjs","sources":["../src/adapters/AnnotPdf.jsx"],"sourcesContent":["// ============================================================================\n// SECTION 1: IMPORTS\n// ============================================================================\n\nimport { useRef, useEffect, useCallback } from 'react';\nimport { AnnotationRenderer } from '../core/AnnotationRenderer.js';\n\n// ============================================================================\n// SECTION 2: JSDOC DOCUMENTATION\n// ============================================================================\n\n/**\n * AnnotPdf - Declarative React component for PDF annotation rendering\n *\n * A React wrapper around the AnnotationRenderer core engine that provides\n * a declarative, props-based API for rendering PDF documents with\n * timeline-synchronized annotations.\n *\n * Features:\n * - Automatic lifecycle management (initialization and cleanup)\n * - Declarative prop-to-method synchronization\n * - PDF rendering with pdf.js\n * - Timeline-synchronized annotation display\n * - Support for highlight, text, and ink annotations\n * - Page navigation and zoom control\n *\n * @component\n * @example\n * // Basic usage\n * <AnnotPdf\n * pdfUrl=\"/document.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={[]}\n * currentTime={0}\n * />\n *\n * @example\n * // With audio synchronization\n * const [currentTime, setCurrentTime] = useState(0);\n *\n * <div>\n * <AnnotPdf\n * pdfUrl=\"/lecture.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={annotations}\n * currentTime={currentTime}\n * onLoad={({ pageCount }) => console.log('Loaded:', pageCount)}\n * />\n * <audio\n * src=\"/lecture.mp3\"\n * onTimeUpdate={(e) => setCurrentTime(e.target.currentTime)}\n * controls\n * />\n * </div>\n *\n * @param {Object} props - Component props\n * @param {string} props.pdfUrl - PDF document URL (required)\n * @param {number} [props.page=1] - Current page number (1-indexed)\n * @param {number} [props.scale=1.5] - Zoom scale factor\n * @param {Array} [props.annotations=[]] - Array of annotation objects\n * @param {number} [props.currentTime=0] - Timeline position in seconds\n * @param {Function} [props.onLoad] - Callback when PDF loads: ({pageCount}) => void\n * @param {Function} [props.onError] - Callback on error: (error) => void\n * @param {Function} [props.onPageChange] - Callback when page changes: (page) => void\n * @param {string} [props.className] - CSS class for container div\n * @param {Object} [props.style] - Inline styles for container div\n * @param {Object} [props.canvasStyle] - Inline styles for canvas element\n * @returns {JSX.Element} PDF viewer component with annotation layers\n */\n\n// ============================================================================\n// SECTION 3: COMPONENT DEFINITION\n// ============================================================================\n\nfunction AnnotPdf({\n // Required props\n pdfUrl,\n\n // Optional props with defaults\n page = 1,\n scale = 1.5,\n annotations = [],\n currentTime = 0,\n\n // Callbacks\n onLoad,\n onError,\n onPageChange,\n\n // Styling\n className,\n style,\n canvasStyle\n}) {\n\n // ==========================================================================\n // SECTION 4: REFS INITIALIZATION\n // ==========================================================================\n\n /**\n * Reference to the canvas element for PDF rendering\n * @type {React.RefObject<HTMLCanvasElement>}\n */\n const canvasRef = useRef(null);\n\n /**\n * Reference to the layer container div for annotation layers\n * @type {React.RefObject<HTMLDivElement>}\n */\n const layerContainerRef = useRef(null);\n\n /**\n * Reference to the AnnotationRenderer engine instance\n * Stored in ref to avoid triggering re-renders\n * @type {React.RefObject<AnnotationRenderer|null>}\n */\n const engineRef = useRef(null);\n\n /**\n * Reference to the render operation queue\n * Ensures sequential execution of async canvas operations\n * Prevents PDF.js race condition: \"Cannot use the same canvas during multiple render() operations\"\n * @type {React.RefObject<Promise<void>>}\n */\n const renderQueue = useRef(Promise.resolve());\n\n // ==========================================================================\n // SECTION 4.5: RENDER QUEUE HELPER\n // ==========================================================================\n\n /**\n * Queue a render operation to execute sequentially\n *\n * This helper ensures that async canvas operations (loadPDF, setPage, setScale)\n * execute one at a time, preventing concurrent access to the PDF.js canvas.\n * Uses Promise chaining to maintain operation order.\n *\n * @param {Function} operation - Async function returning a Promise\n * @returns {void}\n */\n const queueOperation = useCallback((operation) => {\n renderQueue.current = renderQueue.current\n .then(operation)\n .catch(error => {\n // Log errors but don't break the queue\n console.error('AnnotPdf: Queued operation failed:', error);\n });\n }, []);\n\n // ==========================================================================\n // SECTION 5: ENGINE INITIALIZATION AND CLEANUP\n // ==========================================================================\n\n /**\n * Initialize AnnotationRenderer on component mount\n * Cleanup on component unmount\n */\n useEffect(() => {\n // Guard: Wait for DOM elements to be ready\n if (!canvasRef.current || !layerContainerRef.current) {\n return;\n }\n\n // Initialize engine\n try {\n engineRef.current = new AnnotationRenderer({\n canvasElement: canvasRef.current,\n container: layerContainerRef.current\n });\n } catch (error) {\n console.error('AnnotPdf: Failed to initialize renderer:', error);\n if (onError) {\n onError(error);\n }\n }\n\n // Cleanup on unmount\n return () => {\n if (engineRef.current) {\n engineRef.current.destroy();\n engineRef.current = null;\n }\n };\n }, []); // Empty deps - run once on mount\n\n // ==========================================================================\n // SECTION 6: PDF LOADING SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Load PDF document when pdfUrl prop changes\n * Handles async operation with cancellation support\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and pdfUrl must be valid\n if (!engineRef.current || !pdfUrl) {\n return;\n }\n\n let cancelled = false;\n\n const loadPdf = async () => {\n try {\n const result = await engineRef.current.loadPDF(pdfUrl);\n\n // Check if component unmounted during async operation\n if (cancelled) return;\n\n // Check if load was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to load PDF:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Call onLoad callback with pageCount from result\n if (onLoad) {\n onLoad({ pageCount: result.pageCount });\n }\n } catch (error) {\n if (cancelled) return;\n\n console.error('AnnotPdf: Failed to load PDF:', error);\n if (onError) {\n onError(error);\n }\n }\n };\n\n // Queue the PDF loading operation to prevent race conditions\n queueOperation(loadPdf);\n\n // Cleanup: Prevent state updates if component unmounts during load\n return () => {\n cancelled = true;\n };\n }, [pdfUrl, onLoad, onError, queueOperation]);\n\n // ==========================================================================\n // SECTION 7: PAGE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync page prop to engine.setPage() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and page must be valid\n if (!engineRef.current || !page || typeof page !== 'number') {\n return;\n }\n\n // Queue the page change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setPage(page);\n\n // Check if page change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set page:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Optional: Notify parent of successful page change\n if (onPageChange) {\n onPageChange(page);\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set page:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [page, onPageChange, onError, queueOperation]);\n\n // ==========================================================================\n // SECTION 8: SCALE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync scale prop to engine.setScale() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and scale must be valid\n if (!engineRef.current || !scale || typeof scale !== 'number') {\n return;\n }\n\n // Queue the scale change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setScale(scale);\n\n // Check if scale change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set scale:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set scale:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [scale, onError, queueOperation]);\n\n // ==========================================================================\n // SECTION 9: ANNOTATIONS SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync annotations prop to engine.setAnnotations() method\n */\n useEffect(() => {\n // Guard: Engine must exist\n if (!engineRef.current) {\n return;\n }\n\n // Sync annotations to engine (default to empty array)\n try {\n engineRef.current.setAnnotations(annotations || []);\n } catch (error) {\n console.error('AnnotPdf: Failed to set annotations:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [annotations, onError]);\n\n // ==========================================================================\n // SECTION 10: TIMELINE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync currentTime prop to engine.setTime() method\n */\n useEffect(() => {\n // Guard: Engine must exist and currentTime must be defined\n if (!engineRef.current || currentTime === undefined || currentTime === null) {\n return;\n }\n\n // Sync timeline to engine\n try {\n engineRef.current.setTime(currentTime);\n } catch (error) {\n console.error('AnnotPdf: Failed to set time:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [currentTime, onError]);\n\n // ==========================================================================\n // SECTION 11: STYLING DEFINITIONS\n // ==========================================================================\n\n /**\n * Default container styles\n * Merged with user-provided styles (user styles override defaults)\n */\n const defaultContainerStyle = {\n position: 'relative',\n display: 'inline-block',\n lineHeight: 0, // Remove extra space below canvas\n ...style // User styles override defaults\n };\n\n /**\n * Default layer container styles\n * Positions layer div absolutely over canvas\n */\n const defaultLayerStyle = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none', // Allow clicks to pass through to canvas\n overflow: 'hidden'\n };\n\n /**\n * Default canvas styles\n * Merged with user-provided canvasStyle\n */\n const defaultCanvasStyle = {\n display: 'block',\n ...canvasStyle // User styles override defaults\n };\n\n // ==========================================================================\n // SECTION 12: JSX RETURN\n // ==========================================================================\n\n return (\n <div className={className} style={defaultContainerStyle}>\n <canvas ref={canvasRef} style={defaultCanvasStyle} />\n <div ref={layerContainerRef} style={defaultLayerStyle} />\n </div>\n );\n}\n\n// ============================================================================\n// SECTION 13: EXPORT\n// ============================================================================\n\nexport default AnnotPdf;\n"],"names":["AnnotPdf","pdfUrl","page","scale","annotations","currentTime","onLoad","onError","onPageChange","className","style","canvasStyle","canvasRef","useRef","layerContainerRef","engineRef","renderQueue","queueOperation","useCallback","operation","error","useEffect","AnnotationRenderer","cancelled","result","defaultContainerStyle","defaultLayerStyle","defaultCanvasStyle","jsxs","jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index14.cjs","sources":["../src/adapters/AnnotPdf.jsx"],"sourcesContent":["// ============================================================================\n// SECTION 1: IMPORTS\n// ============================================================================\n\nimport { useRef, useEffect, useCallback } from 'react';\nimport { AnnotationRenderer } from '../core/AnnotationRenderer.js';\n\n// ============================================================================\n// SECTION 2: JSDOC DOCUMENTATION\n// ============================================================================\n\n/**\n * AnnotPdf - Declarative React component for PDF annotation rendering\n *\n * A React wrapper around the AnnotationRenderer core engine that provides\n * a declarative, props-based API for rendering PDF documents with\n * timeline-synchronized annotations.\n *\n * Features:\n * - Automatic lifecycle management (initialization and cleanup)\n * - Declarative prop-to-method synchronization\n * - PDF rendering with pdf.js\n * - Timeline-synchronized annotation display\n * - Support for highlight, text, and ink annotations\n * - Page navigation and zoom control\n *\n * @component\n * @example\n * // Basic usage\n * <AnnotPdf\n * pdfUrl=\"/document.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={[]}\n * currentTime={0}\n * />\n *\n * @example\n * // With audio synchronization\n * const [currentTime, setCurrentTime] = useState(0);\n *\n * <div>\n * <AnnotPdf\n * pdfUrl=\"/lecture.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={annotations}\n * currentTime={currentTime}\n * onLoad={({ pageCount }) => console.log('Loaded:', pageCount)}\n * />\n * <audio\n * src=\"/lecture.mp3\"\n * onTimeUpdate={(e) => setCurrentTime(e.target.currentTime)}\n * controls\n * />\n * </div>\n *\n * @param {Object} props - Component props\n * @param {string} props.pdfUrl - PDF document URL (required)\n * @param {number} [props.page=1] - Current page number (1-indexed)\n * @param {number} [props.scale=1.5] - Zoom scale factor\n * @param {Array} [props.annotations=[]] - Array of annotation objects\n * @param {number} [props.currentTime=0] - Timeline position in seconds\n * @param {Function} [props.onLoad] - Callback when PDF loads: ({pageCount}) => void\n * @param {Function} [props.onError] - Callback on error: (error) => void\n * @param {Function} [props.onPageChange] - Callback when page changes: (page) => void\n * @param {string} [props.className] - CSS class for container div\n * @param {Object} [props.style] - Inline styles for container div\n * @param {Object} [props.canvasStyle] - Inline styles for canvas element\n * @returns {JSX.Element} PDF viewer component with annotation layers\n */\n\n// ============================================================================\n// SECTION 3: COMPONENT DEFINITION\n// ============================================================================\n\nfunction AnnotPdf({\n // Required props\n pdfUrl,\n\n // Optional props with defaults\n page = 1,\n scale = 1.5,\n annotations = [],\n currentTime = 0,\n\n // Callbacks\n onLoad,\n onError,\n onPageChange,\n\n // Styling\n className,\n style,\n canvasStyle\n}) {\n\n // ==========================================================================\n // SECTION 4: REFS INITIALIZATION\n // ==========================================================================\n\n /**\n * Reference to the canvas element for PDF rendering\n * @type {React.RefObject<HTMLCanvasElement>}\n */\n const canvasRef = useRef(null);\n\n /**\n * Reference to the layer container div for annotation layers\n * @type {React.RefObject<HTMLDivElement>}\n */\n const layerContainerRef = useRef(null);\n\n /**\n * Reference to the AnnotationRenderer engine instance\n * Stored in ref to avoid triggering re-renders\n * @type {React.RefObject<AnnotationRenderer|null>}\n */\n const engineRef = useRef(null);\n\n /**\n * Reference to the render operation queue\n * Ensures sequential execution of async canvas operations\n * Prevents PDF.js race condition: \"Cannot use the same canvas during multiple render() operations\"\n * @type {React.RefObject<Promise<void>>}\n */\n const renderQueue = useRef(Promise.resolve());\n\n // ==========================================================================\n // SECTION 4.5: RENDER QUEUE HELPER\n // ==========================================================================\n\n /**\n * Queue a render operation to execute sequentially\n *\n * This helper ensures that async canvas operations (loadPDF, setPage, setScale)\n * execute one at a time, preventing concurrent access to the PDF.js canvas.\n * Uses Promise chaining to maintain operation order.\n *\n * @param {Function} operation - Async function returning a Promise\n * @returns {void}\n */\n const queueOperation = useCallback((operation) => {\n renderQueue.current = renderQueue.current\n .then(operation)\n .catch(error => {\n // Log errors but don't break the queue\n console.error('AnnotPdf: Queued operation failed:', error);\n });\n }, []);\n\n // ==========================================================================\n // SECTION 5: ENGINE INITIALIZATION AND CLEANUP\n // ==========================================================================\n\n /**\n * Initialize AnnotationRenderer on component mount\n * Cleanup on component unmount\n */\n useEffect(() => {\n // Guard: Wait for DOM elements to be ready\n if (!canvasRef.current || !layerContainerRef.current) {\n return;\n }\n\n // Initialize engine\n try {\n engineRef.current = new AnnotationRenderer({\n canvasElement: canvasRef.current,\n container: layerContainerRef.current\n });\n } catch (error) {\n console.error('AnnotPdf: Failed to initialize renderer:', error);\n if (onError) {\n onError(error);\n }\n }\n\n // Cleanup on unmount\n return () => {\n if (engineRef.current) {\n engineRef.current.destroy();\n engineRef.current = null;\n }\n };\n }, []); // Empty deps - run once on mount\n\n // ==========================================================================\n // SECTION 6: PDF LOADING SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Load PDF document when pdfUrl prop changes\n * Handles async operation with cancellation support\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and pdfUrl must be valid\n if (!engineRef.current || !pdfUrl) {\n return;\n }\n\n let cancelled = false;\n\n const loadPdf = async () => {\n try {\n const result = await engineRef.current.loadPDF(pdfUrl);\n\n // Check if component unmounted during async operation\n if (cancelled) return;\n\n // Check if load was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to load PDF:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Call onLoad callback with pageCount from result\n if (onLoad) {\n onLoad({ pageCount: result.pageCount });\n }\n } catch (error) {\n if (cancelled) return;\n\n console.error('AnnotPdf: Failed to load PDF:', error);\n if (onError) {\n onError(error);\n }\n }\n };\n\n // Queue the PDF loading operation to prevent race conditions\n queueOperation(loadPdf);\n\n // Cleanup: Prevent state updates if component unmounts during load\n return () => {\n cancelled = true;\n };\n }, [pdfUrl, queueOperation]);\n\n // ==========================================================================\n // SECTION 7: PAGE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync page prop to engine.setPage() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and page must be valid\n if (!engineRef.current || !page || typeof page !== 'number') {\n return;\n }\n\n // Queue the page change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setPage(page);\n\n // Check if page change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set page:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Optional: Notify parent of successful page change\n if (onPageChange) {\n onPageChange(page);\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set page:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [page, queueOperation]);\n\n // ==========================================================================\n // SECTION 8: SCALE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync scale prop to engine.setScale() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and scale must be valid\n if (!engineRef.current || !scale || typeof scale !== 'number') {\n return;\n }\n\n // Queue the scale change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setScale(scale);\n\n // Check if scale change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set scale:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set scale:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [scale, queueOperation]);\n\n // ==========================================================================\n // SECTION 9: ANNOTATIONS SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync annotations prop to engine.setAnnotations() method\n */\n useEffect(() => {\n // Guard: Engine must exist\n if (!engineRef.current) {\n return;\n }\n\n // Sync annotations to engine (default to empty array)\n try {\n engineRef.current.setAnnotations(annotations || []);\n } catch (error) {\n console.error('AnnotPdf: Failed to set annotations:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [annotations]);\n\n // ==========================================================================\n // SECTION 10: TIMELINE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync currentTime prop to engine.setTime() method\n */\n useEffect(() => {\n // Guard: Engine must exist and currentTime must be defined\n if (!engineRef.current || currentTime === undefined || currentTime === null) {\n return;\n }\n\n // Sync timeline to engine\n try {\n engineRef.current.setTime(currentTime);\n } catch (error) {\n console.error('AnnotPdf: Failed to set time:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [currentTime]);\n\n // ==========================================================================\n // SECTION 11: STYLING DEFINITIONS\n // ==========================================================================\n\n /**\n * Default container styles\n * Merged with user-provided styles (user styles override defaults)\n */\n const defaultContainerStyle = {\n position: 'relative',\n display: 'inline-block',\n lineHeight: 0, // Remove extra space below canvas\n ...style // User styles override defaults\n };\n\n /**\n * Default layer container styles\n * Positions layer div absolutely over canvas\n */\n const defaultLayerStyle = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none', // Allow clicks to pass through to canvas\n overflow: 'hidden'\n };\n\n /**\n * Default canvas styles\n * Merged with user-provided canvasStyle\n */\n const defaultCanvasStyle = {\n display: 'block',\n ...canvasStyle // User styles override defaults\n };\n\n // ==========================================================================\n // SECTION 12: JSX RETURN\n // ==========================================================================\n\n return (\n <div className={className} style={defaultContainerStyle}>\n <canvas ref={canvasRef} style={defaultCanvasStyle} />\n <div ref={layerContainerRef} style={defaultLayerStyle} />\n </div>\n );\n}\n\n// ============================================================================\n// SECTION 13: EXPORT\n// ============================================================================\n\nexport default AnnotPdf;\n"],"names":["AnnotPdf","pdfUrl","page","scale","annotations","currentTime","onLoad","onError","onPageChange","className","style","canvasStyle","canvasRef","useRef","layerContainerRef","engineRef","renderQueue","queueOperation","useCallback","operation","error","useEffect","AnnotationRenderer","cancelled","result","defaultContainerStyle","defaultLayerStyle","defaultCanvasStyle","jsxs","jsx"],"mappings":"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"}
|
package/dist/index14.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
import { jsxs as S, jsx as F } from "react/jsx-runtime";
|
|
2
|
-
import { useRef as u, useCallback as k, useEffect as
|
|
2
|
+
import { useRef as u, useCallback as k, useEffect as c } from "react";
|
|
3
3
|
import { AnnotationRenderer as x } from "./index2.js";
|
|
4
|
-
function
|
|
4
|
+
function Q({
|
|
5
5
|
// Required props
|
|
6
6
|
pdfUrl: a,
|
|
7
7
|
// Optional props with defaults
|
|
8
|
-
page:
|
|
9
|
-
scale:
|
|
10
|
-
annotations:
|
|
8
|
+
page: i = 1,
|
|
9
|
+
scale: s = 1.5,
|
|
10
|
+
annotations: y = [],
|
|
11
11
|
currentTime: l = 0,
|
|
12
12
|
// Callbacks
|
|
13
|
-
onLoad:
|
|
13
|
+
onLoad: P,
|
|
14
14
|
onError: t,
|
|
15
|
-
onPageChange:
|
|
15
|
+
onPageChange: h,
|
|
16
16
|
// Styling
|
|
17
17
|
className: v,
|
|
18
18
|
style: m,
|
|
19
19
|
canvasStyle: w
|
|
20
20
|
}) {
|
|
21
|
-
const
|
|
22
|
-
|
|
21
|
+
const f = u(null), d = u(null), r = u(null), A = u(Promise.resolve()), o = k((e) => {
|
|
22
|
+
A.current = A.current.then(e).catch((p) => {
|
|
23
23
|
console.error("AnnotPdf: Queued operation failed:", p);
|
|
24
24
|
});
|
|
25
25
|
}, []);
|
|
26
|
-
|
|
27
|
-
if (!(!
|
|
26
|
+
c(() => {
|
|
27
|
+
if (!(!f.current || !d.current)) {
|
|
28
28
|
try {
|
|
29
29
|
r.current = new x({
|
|
30
|
-
canvasElement:
|
|
31
|
-
container:
|
|
30
|
+
canvasElement: f.current,
|
|
31
|
+
container: d.current
|
|
32
32
|
});
|
|
33
33
|
} catch (e) {
|
|
34
34
|
console.error("AnnotPdf: Failed to initialize renderer:", e), t && t(e);
|
|
@@ -37,11 +37,11 @@ function q({
|
|
|
37
37
|
r.current && (r.current.destroy(), r.current = null);
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
-
}, []),
|
|
40
|
+
}, []), c(() => {
|
|
41
41
|
if (!r.current || !a)
|
|
42
42
|
return;
|
|
43
43
|
let e = !1;
|
|
44
|
-
return
|
|
44
|
+
return o(async () => {
|
|
45
45
|
try {
|
|
46
46
|
const n = await r.current.loadPDF(a);
|
|
47
47
|
if (e) return;
|
|
@@ -49,7 +49,7 @@ function q({
|
|
|
49
49
|
console.error("AnnotPdf: Failed to load PDF:", n.error), t && t(new Error(n.error));
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
P && P({ pageCount: n.pageCount });
|
|
53
53
|
} catch (n) {
|
|
54
54
|
if (e) return;
|
|
55
55
|
console.error("AnnotPdf: Failed to load PDF:", n), t && t(n);
|
|
@@ -57,43 +57,43 @@ function q({
|
|
|
57
57
|
}), () => {
|
|
58
58
|
e = !0;
|
|
59
59
|
};
|
|
60
|
-
}, [a,
|
|
61
|
-
!r.current || !
|
|
60
|
+
}, [a, o]), c(() => {
|
|
61
|
+
!r.current || !i || typeof i != "number" || o(async () => {
|
|
62
62
|
try {
|
|
63
|
-
const e = await r.current.setPage(
|
|
63
|
+
const e = await r.current.setPage(i);
|
|
64
64
|
if (!e.success) {
|
|
65
65
|
console.error("AnnotPdf: Failed to set page:", e.error), t && t(new Error(e.error));
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
h && h(i);
|
|
69
69
|
} catch (e) {
|
|
70
70
|
console.error("AnnotPdf: Failed to set page:", e), t && t(e);
|
|
71
71
|
}
|
|
72
72
|
});
|
|
73
|
-
}, [
|
|
74
|
-
!r.current || !
|
|
73
|
+
}, [i, o]), c(() => {
|
|
74
|
+
!r.current || !s || typeof s != "number" || o(async () => {
|
|
75
75
|
try {
|
|
76
|
-
const e = await r.current.setScale(
|
|
76
|
+
const e = await r.current.setScale(s);
|
|
77
77
|
e.success || (console.error("AnnotPdf: Failed to set scale:", e.error), t && t(new Error(e.error)));
|
|
78
78
|
} catch (e) {
|
|
79
79
|
console.error("AnnotPdf: Failed to set scale:", e), t && t(e);
|
|
80
80
|
}
|
|
81
81
|
});
|
|
82
|
-
}, [
|
|
82
|
+
}, [s, o]), c(() => {
|
|
83
83
|
if (r.current)
|
|
84
84
|
try {
|
|
85
|
-
r.current.setAnnotations(
|
|
85
|
+
r.current.setAnnotations(y || []);
|
|
86
86
|
} catch (e) {
|
|
87
87
|
console.error("AnnotPdf: Failed to set annotations:", e), t && t(e);
|
|
88
88
|
}
|
|
89
|
-
}, [
|
|
89
|
+
}, [y]), c(() => {
|
|
90
90
|
if (!(!r.current || l === void 0 || l === null))
|
|
91
91
|
try {
|
|
92
92
|
r.current.setTime(l);
|
|
93
93
|
} catch (e) {
|
|
94
94
|
console.error("AnnotPdf: Failed to set time:", e), t && t(e);
|
|
95
95
|
}
|
|
96
|
-
}, [l
|
|
96
|
+
}, [l]);
|
|
97
97
|
const b = {
|
|
98
98
|
position: "relative",
|
|
99
99
|
display: "inline-block",
|
|
@@ -101,7 +101,7 @@ function q({
|
|
|
101
101
|
// Remove extra space below canvas
|
|
102
102
|
...m
|
|
103
103
|
// User styles override defaults
|
|
104
|
-
},
|
|
104
|
+
}, C = {
|
|
105
105
|
position: "absolute",
|
|
106
106
|
top: 0,
|
|
107
107
|
left: 0,
|
|
@@ -110,17 +110,17 @@ function q({
|
|
|
110
110
|
pointerEvents: "none",
|
|
111
111
|
// Allow clicks to pass through to canvas
|
|
112
112
|
overflow: "hidden"
|
|
113
|
-
},
|
|
113
|
+
}, R = {
|
|
114
114
|
display: "block",
|
|
115
115
|
...w
|
|
116
116
|
// User styles override defaults
|
|
117
117
|
};
|
|
118
118
|
return /* @__PURE__ */ S("div", { className: v, style: b, children: [
|
|
119
|
-
/* @__PURE__ */ F("canvas", { ref:
|
|
120
|
-
/* @__PURE__ */ F("div", { ref:
|
|
119
|
+
/* @__PURE__ */ F("canvas", { ref: f, style: R }),
|
|
120
|
+
/* @__PURE__ */ F("div", { ref: d, style: C })
|
|
121
121
|
] });
|
|
122
122
|
}
|
|
123
123
|
export {
|
|
124
|
-
|
|
124
|
+
Q as default
|
|
125
125
|
};
|
|
126
126
|
//# sourceMappingURL=index14.js.map
|
package/dist/index14.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index14.js","sources":["../src/adapters/AnnotPdf.jsx"],"sourcesContent":["// ============================================================================\n// SECTION 1: IMPORTS\n// ============================================================================\n\nimport { useRef, useEffect, useCallback } from 'react';\nimport { AnnotationRenderer } from '../core/AnnotationRenderer.js';\n\n// ============================================================================\n// SECTION 2: JSDOC DOCUMENTATION\n// ============================================================================\n\n/**\n * AnnotPdf - Declarative React component for PDF annotation rendering\n *\n * A React wrapper around the AnnotationRenderer core engine that provides\n * a declarative, props-based API for rendering PDF documents with\n * timeline-synchronized annotations.\n *\n * Features:\n * - Automatic lifecycle management (initialization and cleanup)\n * - Declarative prop-to-method synchronization\n * - PDF rendering with pdf.js\n * - Timeline-synchronized annotation display\n * - Support for highlight, text, and ink annotations\n * - Page navigation and zoom control\n *\n * @component\n * @example\n * // Basic usage\n * <AnnotPdf\n * pdfUrl=\"/document.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={[]}\n * currentTime={0}\n * />\n *\n * @example\n * // With audio synchronization\n * const [currentTime, setCurrentTime] = useState(0);\n *\n * <div>\n * <AnnotPdf\n * pdfUrl=\"/lecture.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={annotations}\n * currentTime={currentTime}\n * onLoad={({ pageCount }) => console.log('Loaded:', pageCount)}\n * />\n * <audio\n * src=\"/lecture.mp3\"\n * onTimeUpdate={(e) => setCurrentTime(e.target.currentTime)}\n * controls\n * />\n * </div>\n *\n * @param {Object} props - Component props\n * @param {string} props.pdfUrl - PDF document URL (required)\n * @param {number} [props.page=1] - Current page number (1-indexed)\n * @param {number} [props.scale=1.5] - Zoom scale factor\n * @param {Array} [props.annotations=[]] - Array of annotation objects\n * @param {number} [props.currentTime=0] - Timeline position in seconds\n * @param {Function} [props.onLoad] - Callback when PDF loads: ({pageCount}) => void\n * @param {Function} [props.onError] - Callback on error: (error) => void\n * @param {Function} [props.onPageChange] - Callback when page changes: (page) => void\n * @param {string} [props.className] - CSS class for container div\n * @param {Object} [props.style] - Inline styles for container div\n * @param {Object} [props.canvasStyle] - Inline styles for canvas element\n * @returns {JSX.Element} PDF viewer component with annotation layers\n */\n\n// ============================================================================\n// SECTION 3: COMPONENT DEFINITION\n// ============================================================================\n\nfunction AnnotPdf({\n // Required props\n pdfUrl,\n\n // Optional props with defaults\n page = 1,\n scale = 1.5,\n annotations = [],\n currentTime = 0,\n\n // Callbacks\n onLoad,\n onError,\n onPageChange,\n\n // Styling\n className,\n style,\n canvasStyle\n}) {\n\n // ==========================================================================\n // SECTION 4: REFS INITIALIZATION\n // ==========================================================================\n\n /**\n * Reference to the canvas element for PDF rendering\n * @type {React.RefObject<HTMLCanvasElement>}\n */\n const canvasRef = useRef(null);\n\n /**\n * Reference to the layer container div for annotation layers\n * @type {React.RefObject<HTMLDivElement>}\n */\n const layerContainerRef = useRef(null);\n\n /**\n * Reference to the AnnotationRenderer engine instance\n * Stored in ref to avoid triggering re-renders\n * @type {React.RefObject<AnnotationRenderer|null>}\n */\n const engineRef = useRef(null);\n\n /**\n * Reference to the render operation queue\n * Ensures sequential execution of async canvas operations\n * Prevents PDF.js race condition: \"Cannot use the same canvas during multiple render() operations\"\n * @type {React.RefObject<Promise<void>>}\n */\n const renderQueue = useRef(Promise.resolve());\n\n // ==========================================================================\n // SECTION 4.5: RENDER QUEUE HELPER\n // ==========================================================================\n\n /**\n * Queue a render operation to execute sequentially\n *\n * This helper ensures that async canvas operations (loadPDF, setPage, setScale)\n * execute one at a time, preventing concurrent access to the PDF.js canvas.\n * Uses Promise chaining to maintain operation order.\n *\n * @param {Function} operation - Async function returning a Promise\n * @returns {void}\n */\n const queueOperation = useCallback((operation) => {\n renderQueue.current = renderQueue.current\n .then(operation)\n .catch(error => {\n // Log errors but don't break the queue\n console.error('AnnotPdf: Queued operation failed:', error);\n });\n }, []);\n\n // ==========================================================================\n // SECTION 5: ENGINE INITIALIZATION AND CLEANUP\n // ==========================================================================\n\n /**\n * Initialize AnnotationRenderer on component mount\n * Cleanup on component unmount\n */\n useEffect(() => {\n // Guard: Wait for DOM elements to be ready\n if (!canvasRef.current || !layerContainerRef.current) {\n return;\n }\n\n // Initialize engine\n try {\n engineRef.current = new AnnotationRenderer({\n canvasElement: canvasRef.current,\n container: layerContainerRef.current\n });\n } catch (error) {\n console.error('AnnotPdf: Failed to initialize renderer:', error);\n if (onError) {\n onError(error);\n }\n }\n\n // Cleanup on unmount\n return () => {\n if (engineRef.current) {\n engineRef.current.destroy();\n engineRef.current = null;\n }\n };\n }, []); // Empty deps - run once on mount\n\n // ==========================================================================\n // SECTION 6: PDF LOADING SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Load PDF document when pdfUrl prop changes\n * Handles async operation with cancellation support\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and pdfUrl must be valid\n if (!engineRef.current || !pdfUrl) {\n return;\n }\n\n let cancelled = false;\n\n const loadPdf = async () => {\n try {\n const result = await engineRef.current.loadPDF(pdfUrl);\n\n // Check if component unmounted during async operation\n if (cancelled) return;\n\n // Check if load was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to load PDF:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Call onLoad callback with pageCount from result\n if (onLoad) {\n onLoad({ pageCount: result.pageCount });\n }\n } catch (error) {\n if (cancelled) return;\n\n console.error('AnnotPdf: Failed to load PDF:', error);\n if (onError) {\n onError(error);\n }\n }\n };\n\n // Queue the PDF loading operation to prevent race conditions\n queueOperation(loadPdf);\n\n // Cleanup: Prevent state updates if component unmounts during load\n return () => {\n cancelled = true;\n };\n }, [pdfUrl, onLoad, onError, queueOperation]);\n\n // ==========================================================================\n // SECTION 7: PAGE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync page prop to engine.setPage() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and page must be valid\n if (!engineRef.current || !page || typeof page !== 'number') {\n return;\n }\n\n // Queue the page change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setPage(page);\n\n // Check if page change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set page:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Optional: Notify parent of successful page change\n if (onPageChange) {\n onPageChange(page);\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set page:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [page, onPageChange, onError, queueOperation]);\n\n // ==========================================================================\n // SECTION 8: SCALE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync scale prop to engine.setScale() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and scale must be valid\n if (!engineRef.current || !scale || typeof scale !== 'number') {\n return;\n }\n\n // Queue the scale change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setScale(scale);\n\n // Check if scale change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set scale:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set scale:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [scale, onError, queueOperation]);\n\n // ==========================================================================\n // SECTION 9: ANNOTATIONS SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync annotations prop to engine.setAnnotations() method\n */\n useEffect(() => {\n // Guard: Engine must exist\n if (!engineRef.current) {\n return;\n }\n\n // Sync annotations to engine (default to empty array)\n try {\n engineRef.current.setAnnotations(annotations || []);\n } catch (error) {\n console.error('AnnotPdf: Failed to set annotations:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [annotations, onError]);\n\n // ==========================================================================\n // SECTION 10: TIMELINE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync currentTime prop to engine.setTime() method\n */\n useEffect(() => {\n // Guard: Engine must exist and currentTime must be defined\n if (!engineRef.current || currentTime === undefined || currentTime === null) {\n return;\n }\n\n // Sync timeline to engine\n try {\n engineRef.current.setTime(currentTime);\n } catch (error) {\n console.error('AnnotPdf: Failed to set time:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [currentTime, onError]);\n\n // ==========================================================================\n // SECTION 11: STYLING DEFINITIONS\n // ==========================================================================\n\n /**\n * Default container styles\n * Merged with user-provided styles (user styles override defaults)\n */\n const defaultContainerStyle = {\n position: 'relative',\n display: 'inline-block',\n lineHeight: 0, // Remove extra space below canvas\n ...style // User styles override defaults\n };\n\n /**\n * Default layer container styles\n * Positions layer div absolutely over canvas\n */\n const defaultLayerStyle = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none', // Allow clicks to pass through to canvas\n overflow: 'hidden'\n };\n\n /**\n * Default canvas styles\n * Merged with user-provided canvasStyle\n */\n const defaultCanvasStyle = {\n display: 'block',\n ...canvasStyle // User styles override defaults\n };\n\n // ==========================================================================\n // SECTION 12: JSX RETURN\n // ==========================================================================\n\n return (\n <div className={className} style={defaultContainerStyle}>\n <canvas ref={canvasRef} style={defaultCanvasStyle} />\n <div ref={layerContainerRef} style={defaultLayerStyle} />\n </div>\n );\n}\n\n// ============================================================================\n// SECTION 13: EXPORT\n// ============================================================================\n\nexport default AnnotPdf;\n"],"names":["AnnotPdf","pdfUrl","page","scale","annotations","currentTime","onLoad","onError","onPageChange","className","style","canvasStyle","canvasRef","useRef","layerContainerRef","engineRef","renderQueue","queueOperation","useCallback","operation","error","useEffect","AnnotationRenderer","cancelled","result","defaultContainerStyle","defaultLayerStyle","defaultCanvasStyle","jsxs","jsx"],"mappings":";;;AA4EA,SAASA,EAAS;AAAA;AAAA,EAEhB,QAAAC;AAAA;AAAA,EAGA,MAAAC,IAAO;AAAA,EACP,OAAAC,IAAQ;AAAA,EACR,aAAAC,IAAc,CAAA;AAAA,EACd,aAAAC,IAAc;AAAA;AAAA,EAGd,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,cAAAC;AAAA;AAAA,EAGA,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,aAAAC;AACF,GAAG;AAUD,QAAMC,IAAYC,EAAO,IAAI,GAMvBC,IAAoBD,EAAO,IAAI,GAO/BE,IAAYF,EAAO,IAAI,GAQvBG,IAAcH,EAAO,QAAQ,QAAA,CAAS,GAgBtCI,IAAiBC,EAAY,CAACC,MAAc;AAChD,IAAAH,EAAY,UAAUA,EAAY,QAC/B,KAAKG,CAAS,EACd,MAAM,CAAAC,MAAS;AAEd,cAAQ,MAAM,sCAAsCA,CAAK;AAAA,IAC3D,CAAC;AAAA,EACL,GAAG,CAAA,CAAE;AAUL,EAAAC,EAAU,MAAM;AAEd,QAAI,GAACT,EAAU,WAAW,CAACE,EAAkB,UAK7C;AAAA,UAAI;AACF,QAAAC,EAAU,UAAU,IAAIO,EAAmB;AAAA,UACzC,eAAeV,EAAU;AAAA,UACzB,WAAWE,EAAkB;AAAA,QAAA,CAC9B;AAAA,MACH,SAASM,GAAO;AACd,gBAAQ,MAAM,4CAA4CA,CAAK,GAC3Db,KACFA,EAAQa,CAAK;AAAA,MAEjB;AAGA,aAAO,MAAM;AACX,QAAIL,EAAU,YACZA,EAAU,QAAQ,QAAA,GAClBA,EAAU,UAAU;AAAA,MAExB;AAAA;AAAA,EACF,GAAG,CAAA,CAAE,GAWLM,EAAU,MAAM;AAEd,QAAI,CAACN,EAAU,WAAW,CAACd;AACzB;AAGF,QAAIsB,IAAY;AAiChB,WAAAN,EA/BgB,YAAY;AAC1B,UAAI;AACF,cAAMO,IAAS,MAAMT,EAAU,QAAQ,QAAQd,CAAM;AAGrD,YAAIsB,EAAW;AAGf,YAAI,CAACC,EAAO,SAAS;AACnB,kBAAQ,MAAM,iCAAiCA,EAAO,KAAK,GACvDjB,KACFA,EAAQ,IAAI,MAAMiB,EAAO,KAAK,CAAC;AAEjC;AAAA,QACF;AAGA,QAAIlB,KACFA,EAAO,EAAE,WAAWkB,EAAO,UAAA,CAAW;AAAA,MAE1C,SAASJ,GAAO;AACd,YAAIG,EAAW;AAEf,gBAAQ,MAAM,iCAAiCH,CAAK,GAChDb,KACFA,EAAQa,CAAK;AAAA,MAEjB;AAAA,IACF,CAGsB,GAGf,MAAM;AACX,MAAAG,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACtB,GAAQK,GAAQC,GAASU,CAAc,CAAC,GAU5CI,EAAU,MAAM;AAEd,IAAI,CAACN,EAAU,WAAW,CAACb,KAAQ,OAAOA,KAAS,YAKnDe,EAAe,YAAY;AACzB,UAAI;AACF,cAAMO,IAAS,MAAMT,EAAU,QAAQ,QAAQb,CAAI;AAGnD,YAAI,CAACsB,EAAO,SAAS;AACnB,kBAAQ,MAAM,iCAAiCA,EAAO,KAAK,GACvDjB,KACFA,EAAQ,IAAI,MAAMiB,EAAO,KAAK,CAAC;AAEjC;AAAA,QACF;AAGA,QAAIhB,KACFA,EAAaN,CAAI;AAAA,MAErB,SAASkB,GAAO;AACd,gBAAQ,MAAM,iCAAiCA,CAAK,GAChDb,KACFA,EAAQa,CAAK;AAAA,MAEjB;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAClB,GAAMM,GAAcD,GAASU,CAAc,CAAC,GAUhDI,EAAU,MAAM;AAEd,IAAI,CAACN,EAAU,WAAW,CAACZ,KAAS,OAAOA,KAAU,YAKrDc,EAAe,YAAY;AACzB,UAAI;AACF,cAAMO,IAAS,MAAMT,EAAU,QAAQ,SAASZ,CAAK;AAGrD,QAAKqB,EAAO,YACV,QAAQ,MAAM,kCAAkCA,EAAO,KAAK,GACxDjB,KACFA,EAAQ,IAAI,MAAMiB,EAAO,KAAK,CAAC;AAAA,MAGrC,SAASJ,GAAO;AACd,gBAAQ,MAAM,kCAAkCA,CAAK,GACjDb,KACFA,EAAQa,CAAK;AAAA,MAEjB;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACjB,GAAOI,GAASU,CAAc,CAAC,GASnCI,EAAU,MAAM;AAEd,QAAKN,EAAU;AAKf,UAAI;AACF,QAAAA,EAAU,QAAQ,eAAeX,KAAe,CAAA,CAAE;AAAA,MACpD,SAASgB,GAAO;AACd,gBAAQ,MAAM,wCAAwCA,CAAK,GACvDb,KACFA,EAAQa,CAAK;AAAA,MAEjB;AAAA,EACF,GAAG,CAAChB,GAAaG,CAAO,CAAC,GASzBc,EAAU,MAAM;AAEd,QAAI,GAACN,EAAU,WAAWV,MAAgB,UAAaA,MAAgB;AAKvE,UAAI;AACF,QAAAU,EAAU,QAAQ,QAAQV,CAAW;AAAA,MACvC,SAASe,GAAO;AACd,gBAAQ,MAAM,iCAAiCA,CAAK,GAChDb,KACFA,EAAQa,CAAK;AAAA,MAEjB;AAAA,EACF,GAAG,CAACf,GAAaE,CAAO,CAAC;AAUzB,QAAMkB,IAAwB;AAAA,IAC5B,UAAU;AAAA,IACV,SAAS;AAAA,IACT,YAAY;AAAA;AAAA,IACZ,GAAGf;AAAA;AAAA,EAAA,GAOCgB,IAAoB;AAAA,IACxB,UAAU;AAAA,IACV,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,eAAe;AAAA;AAAA,IACf,UAAU;AAAA,EAAA,GAONC,IAAqB;AAAA,IACzB,SAAS;AAAA,IACT,GAAGhB;AAAA;AAAA,EAAA;AAOL,SACE,gBAAAiB,EAAC,OAAA,EAAI,WAAAnB,GAAsB,OAAOgB,GAChC,UAAA;AAAA,IAAA,gBAAAI,EAAC,UAAA,EAAO,KAAKjB,GAAW,OAAOe,GAAoB;AAAA,IACnD,gBAAAE,EAAC,OAAA,EAAI,KAAKf,GAAmB,OAAOY,EAAA,CAAmB;AAAA,EAAA,GACzD;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"index14.js","sources":["../src/adapters/AnnotPdf.jsx"],"sourcesContent":["// ============================================================================\n// SECTION 1: IMPORTS\n// ============================================================================\n\nimport { useRef, useEffect, useCallback } from 'react';\nimport { AnnotationRenderer } from '../core/AnnotationRenderer.js';\n\n// ============================================================================\n// SECTION 2: JSDOC DOCUMENTATION\n// ============================================================================\n\n/**\n * AnnotPdf - Declarative React component for PDF annotation rendering\n *\n * A React wrapper around the AnnotationRenderer core engine that provides\n * a declarative, props-based API for rendering PDF documents with\n * timeline-synchronized annotations.\n *\n * Features:\n * - Automatic lifecycle management (initialization and cleanup)\n * - Declarative prop-to-method synchronization\n * - PDF rendering with pdf.js\n * - Timeline-synchronized annotation display\n * - Support for highlight, text, and ink annotations\n * - Page navigation and zoom control\n *\n * @component\n * @example\n * // Basic usage\n * <AnnotPdf\n * pdfUrl=\"/document.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={[]}\n * currentTime={0}\n * />\n *\n * @example\n * // With audio synchronization\n * const [currentTime, setCurrentTime] = useState(0);\n *\n * <div>\n * <AnnotPdf\n * pdfUrl=\"/lecture.pdf\"\n * page={1}\n * scale={1.5}\n * annotations={annotations}\n * currentTime={currentTime}\n * onLoad={({ pageCount }) => console.log('Loaded:', pageCount)}\n * />\n * <audio\n * src=\"/lecture.mp3\"\n * onTimeUpdate={(e) => setCurrentTime(e.target.currentTime)}\n * controls\n * />\n * </div>\n *\n * @param {Object} props - Component props\n * @param {string} props.pdfUrl - PDF document URL (required)\n * @param {number} [props.page=1] - Current page number (1-indexed)\n * @param {number} [props.scale=1.5] - Zoom scale factor\n * @param {Array} [props.annotations=[]] - Array of annotation objects\n * @param {number} [props.currentTime=0] - Timeline position in seconds\n * @param {Function} [props.onLoad] - Callback when PDF loads: ({pageCount}) => void\n * @param {Function} [props.onError] - Callback on error: (error) => void\n * @param {Function} [props.onPageChange] - Callback when page changes: (page) => void\n * @param {string} [props.className] - CSS class for container div\n * @param {Object} [props.style] - Inline styles for container div\n * @param {Object} [props.canvasStyle] - Inline styles for canvas element\n * @returns {JSX.Element} PDF viewer component with annotation layers\n */\n\n// ============================================================================\n// SECTION 3: COMPONENT DEFINITION\n// ============================================================================\n\nfunction AnnotPdf({\n // Required props\n pdfUrl,\n\n // Optional props with defaults\n page = 1,\n scale = 1.5,\n annotations = [],\n currentTime = 0,\n\n // Callbacks\n onLoad,\n onError,\n onPageChange,\n\n // Styling\n className,\n style,\n canvasStyle\n}) {\n\n // ==========================================================================\n // SECTION 4: REFS INITIALIZATION\n // ==========================================================================\n\n /**\n * Reference to the canvas element for PDF rendering\n * @type {React.RefObject<HTMLCanvasElement>}\n */\n const canvasRef = useRef(null);\n\n /**\n * Reference to the layer container div for annotation layers\n * @type {React.RefObject<HTMLDivElement>}\n */\n const layerContainerRef = useRef(null);\n\n /**\n * Reference to the AnnotationRenderer engine instance\n * Stored in ref to avoid triggering re-renders\n * @type {React.RefObject<AnnotationRenderer|null>}\n */\n const engineRef = useRef(null);\n\n /**\n * Reference to the render operation queue\n * Ensures sequential execution of async canvas operations\n * Prevents PDF.js race condition: \"Cannot use the same canvas during multiple render() operations\"\n * @type {React.RefObject<Promise<void>>}\n */\n const renderQueue = useRef(Promise.resolve());\n\n // ==========================================================================\n // SECTION 4.5: RENDER QUEUE HELPER\n // ==========================================================================\n\n /**\n * Queue a render operation to execute sequentially\n *\n * This helper ensures that async canvas operations (loadPDF, setPage, setScale)\n * execute one at a time, preventing concurrent access to the PDF.js canvas.\n * Uses Promise chaining to maintain operation order.\n *\n * @param {Function} operation - Async function returning a Promise\n * @returns {void}\n */\n const queueOperation = useCallback((operation) => {\n renderQueue.current = renderQueue.current\n .then(operation)\n .catch(error => {\n // Log errors but don't break the queue\n console.error('AnnotPdf: Queued operation failed:', error);\n });\n }, []);\n\n // ==========================================================================\n // SECTION 5: ENGINE INITIALIZATION AND CLEANUP\n // ==========================================================================\n\n /**\n * Initialize AnnotationRenderer on component mount\n * Cleanup on component unmount\n */\n useEffect(() => {\n // Guard: Wait for DOM elements to be ready\n if (!canvasRef.current || !layerContainerRef.current) {\n return;\n }\n\n // Initialize engine\n try {\n engineRef.current = new AnnotationRenderer({\n canvasElement: canvasRef.current,\n container: layerContainerRef.current\n });\n } catch (error) {\n console.error('AnnotPdf: Failed to initialize renderer:', error);\n if (onError) {\n onError(error);\n }\n }\n\n // Cleanup on unmount\n return () => {\n if (engineRef.current) {\n engineRef.current.destroy();\n engineRef.current = null;\n }\n };\n }, []); // Empty deps - run once on mount\n\n // ==========================================================================\n // SECTION 6: PDF LOADING SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Load PDF document when pdfUrl prop changes\n * Handles async operation with cancellation support\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and pdfUrl must be valid\n if (!engineRef.current || !pdfUrl) {\n return;\n }\n\n let cancelled = false;\n\n const loadPdf = async () => {\n try {\n const result = await engineRef.current.loadPDF(pdfUrl);\n\n // Check if component unmounted during async operation\n if (cancelled) return;\n\n // Check if load was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to load PDF:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Call onLoad callback with pageCount from result\n if (onLoad) {\n onLoad({ pageCount: result.pageCount });\n }\n } catch (error) {\n if (cancelled) return;\n\n console.error('AnnotPdf: Failed to load PDF:', error);\n if (onError) {\n onError(error);\n }\n }\n };\n\n // Queue the PDF loading operation to prevent race conditions\n queueOperation(loadPdf);\n\n // Cleanup: Prevent state updates if component unmounts during load\n return () => {\n cancelled = true;\n };\n }, [pdfUrl, queueOperation]);\n\n // ==========================================================================\n // SECTION 7: PAGE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync page prop to engine.setPage() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and page must be valid\n if (!engineRef.current || !page || typeof page !== 'number') {\n return;\n }\n\n // Queue the page change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setPage(page);\n\n // Check if page change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set page:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n return;\n }\n\n // Optional: Notify parent of successful page change\n if (onPageChange) {\n onPageChange(page);\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set page:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [page, queueOperation]);\n\n // ==========================================================================\n // SECTION 8: SCALE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync scale prop to engine.setScale() method\n * Uses render queue to prevent concurrent canvas operations\n */\n useEffect(() => {\n // Guard: Engine must exist and scale must be valid\n if (!engineRef.current || !scale || typeof scale !== 'number') {\n return;\n }\n\n // Queue the scale change operation to prevent race conditions\n queueOperation(async () => {\n try {\n const result = await engineRef.current.setScale(scale);\n\n // Check if scale change was successful\n if (!result.success) {\n console.error('AnnotPdf: Failed to set scale:', result.error);\n if (onError) {\n onError(new Error(result.error));\n }\n }\n } catch (error) {\n console.error('AnnotPdf: Failed to set scale:', error);\n if (onError) {\n onError(error);\n }\n }\n });\n }, [scale, queueOperation]);\n\n // ==========================================================================\n // SECTION 9: ANNOTATIONS SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync annotations prop to engine.setAnnotations() method\n */\n useEffect(() => {\n // Guard: Engine must exist\n if (!engineRef.current) {\n return;\n }\n\n // Sync annotations to engine (default to empty array)\n try {\n engineRef.current.setAnnotations(annotations || []);\n } catch (error) {\n console.error('AnnotPdf: Failed to set annotations:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [annotations]);\n\n // ==========================================================================\n // SECTION 10: TIMELINE SYNCHRONIZATION\n // ==========================================================================\n\n /**\n * Sync currentTime prop to engine.setTime() method\n */\n useEffect(() => {\n // Guard: Engine must exist and currentTime must be defined\n if (!engineRef.current || currentTime === undefined || currentTime === null) {\n return;\n }\n\n // Sync timeline to engine\n try {\n engineRef.current.setTime(currentTime);\n } catch (error) {\n console.error('AnnotPdf: Failed to set time:', error);\n if (onError) {\n onError(error);\n }\n }\n }, [currentTime]);\n\n // ==========================================================================\n // SECTION 11: STYLING DEFINITIONS\n // ==========================================================================\n\n /**\n * Default container styles\n * Merged with user-provided styles (user styles override defaults)\n */\n const defaultContainerStyle = {\n position: 'relative',\n display: 'inline-block',\n lineHeight: 0, // Remove extra space below canvas\n ...style // User styles override defaults\n };\n\n /**\n * Default layer container styles\n * Positions layer div absolutely over canvas\n */\n const defaultLayerStyle = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n pointerEvents: 'none', // Allow clicks to pass through to canvas\n overflow: 'hidden'\n };\n\n /**\n * Default canvas styles\n * Merged with user-provided canvasStyle\n */\n const defaultCanvasStyle = {\n display: 'block',\n ...canvasStyle // User styles override defaults\n };\n\n // ==========================================================================\n // SECTION 12: JSX RETURN\n // ==========================================================================\n\n return (\n <div className={className} style={defaultContainerStyle}>\n <canvas ref={canvasRef} style={defaultCanvasStyle} />\n <div ref={layerContainerRef} style={defaultLayerStyle} />\n </div>\n );\n}\n\n// ============================================================================\n// SECTION 13: EXPORT\n// ============================================================================\n\nexport default AnnotPdf;\n"],"names":["AnnotPdf","pdfUrl","page","scale","annotations","currentTime","onLoad","onError","onPageChange","className","style","canvasStyle","canvasRef","useRef","layerContainerRef","engineRef","renderQueue","queueOperation","useCallback","operation","error","useEffect","AnnotationRenderer","cancelled","result","defaultContainerStyle","defaultLayerStyle","defaultCanvasStyle","jsxs","jsx"],"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
|
|
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;
|
|
2
2
|
//# sourceMappingURL=index7.cjs.map
|
package/dist/index7.cjs.map
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/index7.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { rectNormToAbs as
|
|
3
|
-
class
|
|
1
|
+
import p from "./index6.js";
|
|
2
|
+
import { rectNormToAbs as c } from "./index10.js";
|
|
3
|
+
class f extends p {
|
|
4
4
|
/**
|
|
5
5
|
* Creates a new HighlightLayer instance
|
|
6
6
|
*
|
|
@@ -10,8 +10,8 @@ class g extends c {
|
|
|
10
10
|
* @param {number} viewport.height - Viewport height in pixels
|
|
11
11
|
* @param {number} viewport.scale - PDF scale/zoom level
|
|
12
12
|
*/
|
|
13
|
-
constructor(e,
|
|
14
|
-
super(e,
|
|
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
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Renders highlight elements for all annotations
|
|
@@ -24,18 +24,18 @@ class g extends c {
|
|
|
24
24
|
this.layerElement.innerHTML = "", this.elements.clear(), this.annotations.forEach((e) => {
|
|
25
25
|
if (e.mode !== "quads" || !e.quads?.length)
|
|
26
26
|
return;
|
|
27
|
-
const
|
|
28
|
-
e.quads.forEach((
|
|
29
|
-
const
|
|
30
|
-
t.style.position = "absolute", t.style.left = `${
|
|
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
31
|
const l = document.createElement("div");
|
|
32
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}-${
|
|
33
|
+
const m = `${e.id}-${s}`;
|
|
34
34
|
this.elements.set(m, {
|
|
35
35
|
element: l,
|
|
36
36
|
wrapper: t,
|
|
37
37
|
annotation: e,
|
|
38
|
-
segStart:
|
|
38
|
+
segStart: n,
|
|
39
39
|
segEnd: d
|
|
40
40
|
});
|
|
41
41
|
});
|
|
@@ -44,38 +44,34 @@ class g extends c {
|
|
|
44
44
|
/**
|
|
45
45
|
* Updates highlight animations based on current timeline position
|
|
46
46
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
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
50
|
*
|
|
51
51
|
* @param {number} nowSec - Current timeline position in seconds
|
|
52
52
|
*/
|
|
53
53
|
updateTime(e) {
|
|
54
|
-
super.updateTime(e), this.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Math.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
Math.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
}), this.rafId = requestAnimationFrame(r));
|
|
77
|
-
};
|
|
78
|
-
r();
|
|
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
|
+
});
|
|
79
75
|
}
|
|
80
76
|
/**
|
|
81
77
|
* Updates the visual state of the layer
|
|
@@ -87,14 +83,13 @@ class g extends c {
|
|
|
87
83
|
/**
|
|
88
84
|
* Destroys the layer and releases all resources
|
|
89
85
|
*
|
|
90
|
-
*
|
|
91
|
-
* and calls parent cleanup.
|
|
86
|
+
* Clears element storage, removes DOM elements, and calls parent cleanup.
|
|
92
87
|
*/
|
|
93
88
|
destroy() {
|
|
94
|
-
this.
|
|
89
|
+
this.elements.clear(), this.elements = null, this.layerElement && this.layerElement.parentNode && this.layerElement.parentNode.removeChild(this.layerElement), this.layerElement = null, super.destroy();
|
|
95
90
|
}
|
|
96
91
|
}
|
|
97
92
|
export {
|
|
98
|
-
|
|
93
|
+
f as default
|
|
99
94
|
};
|
|
100
95
|
//# sourceMappingURL=index7.js.map
|
package/dist/index7.js.map
CHANGED
|
@@ -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
|
|
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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"}
|
package/dist/index9.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("./index6.cjs");class c extends l.default{constructor(t,e){super(t,e),this.canvasElement=document.createElement("canvas"),this.canvasElement.style.position="absolute",this.canvasElement.style.inset="0",this.canvasElement.style.pointerEvents="none",this.canvasElement.style.zIndex="40",this.container.appendChild(this.canvasElement),this.ctx=this.canvasElement.getContext("2d"),this._setupCanvas()}_setupCanvas(){const t=window.devicePixelRatio||1;this.canvasElement.width=Math.round(this.viewport.width*t),this.canvasElement.height=Math.round(this.viewport.height*t),this.canvasElement.style.width=`${this.viewport.width}px`,this.canvasElement.style.height=`${this.viewport.height}px`,this.ctx.setTransform(t,0,0,t,0,0)}setViewport(t){super.setViewport(t),this._setupCanvas()}updateTime(t){if(super.updateTime(t),!this.isDestroyed){this.ctx.clearRect(0,0,this.canvasElement.width,this.canvasElement.height);for(const e of this.annotations){if(t<e.start)continue;const o=e.end-e.start,r=Math.min(t-e.start,o);for(const s of e.strokes||[]){this.ctx.lineCap="round",this.ctx.lineJoin="round",this.ctx.strokeStyle=s.color||"#1f2937",this.ctx.lineWidth=s.size||3,this.ctx.beginPath();let i=!1;for(const n of s.points){if(n.t>r)break;const a=n.x*this.viewport.width,h=n.y*this.viewport.height;i?this.ctx.lineTo(a,h):(this.ctx.moveTo(a,h),i=!0)}i&&this.ctx.stroke()}}}}render(){}update(){}destroy(){this.ctx=null,this.canvasElement&&this.canvasElement.parentNode&&this.canvasElement.parentNode.removeChild(this.canvasElement),this.canvasElement=null,super.destroy()}}exports.default=c;
|
|
2
2
|
//# sourceMappingURL=index9.cjs.map
|
package/dist/index9.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index9.cjs","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer 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 canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n //
|
|
1
|
+
{"version":3,"file":"index9.cjs","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer 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 canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n // Setup canvas with device pixel ratio\n this._setupCanvas();\n }\n\n /**\n * Configures canvas dimensions with device pixel ratio scaling\n *\n * Sets canvas buffer size for high-resolution rendering on Retina displays\n * while maintaining correct display size in CSS pixels. Scales context\n * transform to allow drawing with CSS pixel coordinates.\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas buffer resolution (high-res for crisp rendering)\n this.canvasElement.width = Math.round(this.viewport.width * dpr);\n this.canvasElement.height = Math.round(this.viewport.height * dpr);\n\n // Set canvas display size (CSS pixels)\n this.canvasElement.style.width = `${this.viewport.width}px`;\n this.canvasElement.style.height = `${this.viewport.height}px`;\n\n // Scale context to account for device pixel ratio\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * Updates viewport dimensions and resizes canvas\n *\n * Reconfigures canvas buffer and display size when viewport changes\n * due to page navigation or zoom operations.\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 * @override\n */\n setViewport(viewport) {\n super.setViewport(viewport);\n this._setupCanvas();\n }\n\n /**\n * Updates timeline position and draws progressive strokes\n *\n * Redraws the canvas with strokes progressively drawn based on elapsed time.\n * Clears the canvas and redraws all visible strokes.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n * @override\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Check destroyed state\n if (this.isDestroyed) return;\n\n // Clear canvas\n this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);\n\n // Draw each annotation\n for (const a of this.annotations) {\n // Skip annotations that haven't started yet\n if (nowSec < a.start) continue;\n\n // Calculate elapsed time (capped at duration for persistence)\n const duration = a.end - a.start;\n const elapsed = Math.min(nowSec - a.start, duration);\n\n // Draw each stroke\n for (const stroke of (a.strokes || [])) {\n // Configure stroke style\n this.ctx.lineCap = 'round';\n this.ctx.lineJoin = 'round';\n this.ctx.strokeStyle = stroke.color || '#1f2937';\n this.ctx.lineWidth = stroke.size || 3;\n this.ctx.beginPath();\n\n let started = false;\n\n // Draw points up to current time\n for (const point of stroke.points) {\n // Skip points that haven't been drawn yet\n if (point.t > elapsed) break;\n\n // Convert normalized coordinates to canvas pixels\n const x = point.x * this.viewport.width;\n const y = point.y * this.viewport.height;\n\n if (!started) {\n this.ctx.moveTo(x, y);\n started = true;\n } else {\n this.ctx.lineTo(x, y);\n }\n }\n\n // Render the stroke\n if (started) {\n this.ctx.stroke();\n }\n }\n }\n }\n\n /**\n * Renders the layer content\n *\n * No-op for DrawingLayer - canvas rendering happens in updateTime().\n * Canvas element is created once in constructor.\n *\n * @override\n */\n render() {\n // No-op: Canvas rendering happens in updateTime()\n // Canvas element is created once in constructor\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used for DrawingLayer - updateTime() handles drawing directly.\n *\n * @override\n */\n update() {\n // Not used - updateTime handles drawing directly\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Clears references and removes canvas from DOM.\n * Safe to call multiple times (idempotent).\n *\n * @override\n */\n destroy() {\n // Clear context reference\n this.ctx = null;\n\n // Remove canvas from DOM\n if (this.canvasElement && this.canvasElement.parentNode) {\n this.canvasElement.parentNode.removeChild(this.canvasElement);\n }\n this.canvasElement = null;\n\n // Call parent cleanup (always last)\n super.destroy();\n }\n}\n\nexport default DrawingLayer;\n"],"names":["DrawingLayer","BaseLayer","container","viewport","dpr","nowSec","a","duration","elapsed","stroke","started","point","x","y"],"mappings":"4IAkBA,MAAMA,UAAqBC,EAAAA,OAAU,CAUnC,YAAYC,EAAWC,EAAU,CAC/B,MAAMD,EAAWC,CAAQ,EAGzB,KAAK,cAAgB,SAAS,cAAc,QAAQ,EACpD,KAAK,cAAc,MAAM,SAAW,WACpC,KAAK,cAAc,MAAM,MAAQ,IACjC,KAAK,cAAc,MAAM,cAAgB,OACzC,KAAK,cAAc,MAAM,OAAS,KAGlC,KAAK,UAAU,YAAY,KAAK,aAAa,EAG7C,KAAK,IAAM,KAAK,cAAc,WAAW,IAAI,EAG7C,KAAK,aAAY,CACnB,CAWA,cAAe,CACb,MAAMC,EAAM,OAAO,kBAAoB,EAGvC,KAAK,cAAc,MAAQ,KAAK,MAAM,KAAK,SAAS,MAAQA,CAAG,EAC/D,KAAK,cAAc,OAAS,KAAK,MAAM,KAAK,SAAS,OAASA,CAAG,EAGjE,KAAK,cAAc,MAAM,MAAQ,GAAG,KAAK,SAAS,KAAK,KACvD,KAAK,cAAc,MAAM,OAAS,GAAG,KAAK,SAAS,MAAM,KAGzD,KAAK,IAAI,aAAaA,EAAK,EAAG,EAAGA,EAAK,EAAG,CAAC,CAC5C,CAcA,YAAYD,EAAU,CACpB,MAAM,YAAYA,CAAQ,EAC1B,KAAK,aAAY,CACnB,CAaA,WAAWE,EAAQ,CAIjB,GAHA,MAAM,WAAWA,CAAM,EAGnB,MAAK,YAGT,MAAK,IAAI,UAAU,EAAG,EAAG,KAAK,cAAc,MAAO,KAAK,cAAc,MAAM,EAG5E,UAAWC,KAAK,KAAK,YAAa,CAEhC,GAAID,EAASC,EAAE,MAAO,SAGtB,MAAMC,EAAWD,EAAE,IAAMA,EAAE,MACrBE,EAAU,KAAK,IAAIH,EAASC,EAAE,MAAOC,CAAQ,EAGnD,UAAWE,KAAWH,EAAE,SAAW,CAAA,EAAK,CAEtC,KAAK,IAAI,QAAU,QACnB,KAAK,IAAI,SAAW,QACpB,KAAK,IAAI,YAAcG,EAAO,OAAS,UACvC,KAAK,IAAI,UAAYA,EAAO,MAAQ,EACpC,KAAK,IAAI,UAAS,EAElB,IAAIC,EAAU,GAGd,UAAWC,KAASF,EAAO,OAAQ,CAEjC,GAAIE,EAAM,EAAIH,EAAS,MAGvB,MAAMI,EAAID,EAAM,EAAI,KAAK,SAAS,MAC5BE,EAAIF,EAAM,EAAI,KAAK,SAAS,OAE7BD,EAIH,KAAK,IAAI,OAAOE,EAAGC,CAAC,GAHpB,KAAK,IAAI,OAAOD,EAAGC,CAAC,EACpBH,EAAU,GAId,CAGIA,GACF,KAAK,IAAI,OAAM,CAEnB,CACF,EACF,CAUA,QAAS,CAGT,CASA,QAAS,CAET,CAUA,SAAU,CAER,KAAK,IAAM,KAGP,KAAK,eAAiB,KAAK,cAAc,YAC3C,KAAK,cAAc,WAAW,YAAY,KAAK,aAAa,EAE9D,KAAK,cAAgB,KAGrB,MAAM,QAAO,CACf,CACF"}
|
package/dist/index9.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
class p extends
|
|
1
|
+
import c from "./index6.js";
|
|
2
|
+
class p extends c {
|
|
3
3
|
/**
|
|
4
4
|
* Creates a new DrawingLayer instance
|
|
5
5
|
*
|
|
@@ -9,8 +9,8 @@ class p extends l {
|
|
|
9
9
|
* @param {number} viewport.height - Viewport height in pixels
|
|
10
10
|
* @param {number} viewport.scale - PDF scale/zoom level
|
|
11
11
|
*/
|
|
12
|
-
constructor(t,
|
|
13
|
-
super(t,
|
|
12
|
+
constructor(t, e) {
|
|
13
|
+
super(t, e), this.canvasElement = document.createElement("canvas"), this.canvasElement.style.position = "absolute", this.canvasElement.style.inset = "0", this.canvasElement.style.pointerEvents = "none", this.canvasElement.style.zIndex = "40", this.container.appendChild(this.canvasElement), this.ctx = this.canvasElement.getContext("2d"), this._setupCanvas();
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Configures canvas dimensions with device pixel ratio scaling
|
|
@@ -41,45 +41,40 @@ class p extends l {
|
|
|
41
41
|
super.setViewport(t), this._setupCanvas();
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
|
-
* Updates timeline position and
|
|
44
|
+
* Updates timeline position and draws progressive strokes
|
|
45
45
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* Redraws the canvas with strokes progressively drawn based on elapsed time.
|
|
47
|
+
* Clears the canvas and redraws all visible strokes.
|
|
48
|
+
* Renders once per call - no continuous loop.
|
|
49
49
|
*
|
|
50
50
|
* @param {number} nowSec - Current timeline position in seconds
|
|
51
51
|
* @throws {Error} If called after layer is destroyed
|
|
52
52
|
* @override
|
|
53
53
|
*/
|
|
54
54
|
updateTime(t) {
|
|
55
|
-
super.updateTime(t), this.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const h = a.x * this.viewport.width, r = a.y * this.viewport.height;
|
|
68
|
-
n ? this.ctx.lineTo(h, r) : (this.ctx.moveTo(h, r), n = !0);
|
|
69
|
-
}
|
|
70
|
-
n && this.ctx.stroke();
|
|
55
|
+
if (super.updateTime(t), !this.isDestroyed) {
|
|
56
|
+
this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
|
|
57
|
+
for (const e of this.annotations) {
|
|
58
|
+
if (t < e.start) continue;
|
|
59
|
+
const o = e.end - e.start, r = Math.min(t - e.start, o);
|
|
60
|
+
for (const s of e.strokes || []) {
|
|
61
|
+
this.ctx.lineCap = "round", this.ctx.lineJoin = "round", this.ctx.strokeStyle = s.color || "#1f2937", this.ctx.lineWidth = s.size || 3, this.ctx.beginPath();
|
|
62
|
+
let i = !1;
|
|
63
|
+
for (const n of s.points) {
|
|
64
|
+
if (n.t > r) break;
|
|
65
|
+
const a = n.x * this.viewport.width, h = n.y * this.viewport.height;
|
|
66
|
+
i ? this.ctx.lineTo(a, h) : (this.ctx.moveTo(a, h), i = !0);
|
|
71
67
|
}
|
|
68
|
+
i && this.ctx.stroke();
|
|
72
69
|
}
|
|
73
|
-
this.rafId = requestAnimationFrame(s);
|
|
74
70
|
}
|
|
75
|
-
}
|
|
76
|
-
s();
|
|
71
|
+
}
|
|
77
72
|
}
|
|
78
73
|
/**
|
|
79
74
|
* Renders the layer content
|
|
80
75
|
*
|
|
81
|
-
* No-op for DrawingLayer - canvas rendering happens in updateTime()
|
|
82
|
-
* Canvas element is created once in constructor
|
|
76
|
+
* No-op for DrawingLayer - canvas rendering happens in updateTime().
|
|
77
|
+
* Canvas element is created once in constructor.
|
|
83
78
|
*
|
|
84
79
|
* @override
|
|
85
80
|
*/
|
|
@@ -88,7 +83,7 @@ class p extends l {
|
|
|
88
83
|
/**
|
|
89
84
|
* Updates the visual state of the layer
|
|
90
85
|
*
|
|
91
|
-
* Not used for DrawingLayer - updateTime() handles
|
|
86
|
+
* Not used for DrawingLayer - updateTime() handles drawing directly.
|
|
92
87
|
*
|
|
93
88
|
* @override
|
|
94
89
|
*/
|
|
@@ -97,13 +92,13 @@ class p extends l {
|
|
|
97
92
|
/**
|
|
98
93
|
* Destroys the layer and releases resources
|
|
99
94
|
*
|
|
100
|
-
*
|
|
95
|
+
* Clears references and removes canvas from DOM.
|
|
101
96
|
* Safe to call multiple times (idempotent).
|
|
102
97
|
*
|
|
103
98
|
* @override
|
|
104
99
|
*/
|
|
105
100
|
destroy() {
|
|
106
|
-
this.
|
|
101
|
+
this.ctx = null, this.canvasElement && this.canvasElement.parentNode && this.canvasElement.parentNode.removeChild(this.canvasElement), this.canvasElement = null, super.destroy();
|
|
107
102
|
}
|
|
108
103
|
}
|
|
109
104
|
export {
|
package/dist/index9.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index9.js","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer 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 canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n //
|
|
1
|
+
{"version":3,"file":"index9.js","sources":["../src/layers/DrawingLayer.js"],"sourcesContent":["import BaseLayer from './BaseLayer.js';\n\n/**\n * DrawingLayer - Renders ink/drawing annotations on HTML canvas\n *\n * Extends BaseLayer to provide progressive stroke animation for ink annotations.\n * Draws stroke points incrementally based on timeline position using requestAnimationFrame.\n * Handles device pixel ratio scaling for crisp rendering on high-DPI displays.\n *\n * Features:\n * - Progressive stroke drawing point-by-point\n * - Multiple strokes per annotation with custom colors/sizes\n * - Device pixel ratio handling for Retina displays\n * - Smooth 60fps animation with RAF\n * - Efficient canvas clear/redraw cycle\n *\n * @extends BaseLayer\n */\nclass DrawingLayer extends BaseLayer {\n /**\n * Creates a new DrawingLayer 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 canvas element\n this.canvasElement = document.createElement('canvas');\n this.canvasElement.style.position = 'absolute';\n this.canvasElement.style.inset = '0';\n this.canvasElement.style.pointerEvents = 'none';\n this.canvasElement.style.zIndex = '40';\n\n // Append to container\n this.container.appendChild(this.canvasElement);\n\n // Get 2D context\n this.ctx = this.canvasElement.getContext('2d');\n\n // Setup canvas with device pixel ratio\n this._setupCanvas();\n }\n\n /**\n * Configures canvas dimensions with device pixel ratio scaling\n *\n * Sets canvas buffer size for high-resolution rendering on Retina displays\n * while maintaining correct display size in CSS pixels. Scales context\n * transform to allow drawing with CSS pixel coordinates.\n *\n * @private\n */\n _setupCanvas() {\n const dpr = window.devicePixelRatio || 1;\n\n // Set canvas buffer resolution (high-res for crisp rendering)\n this.canvasElement.width = Math.round(this.viewport.width * dpr);\n this.canvasElement.height = Math.round(this.viewport.height * dpr);\n\n // Set canvas display size (CSS pixels)\n this.canvasElement.style.width = `${this.viewport.width}px`;\n this.canvasElement.style.height = `${this.viewport.height}px`;\n\n // Scale context to account for device pixel ratio\n this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n /**\n * Updates viewport dimensions and resizes canvas\n *\n * Reconfigures canvas buffer and display size when viewport changes\n * due to page navigation or zoom operations.\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 * @override\n */\n setViewport(viewport) {\n super.setViewport(viewport);\n this._setupCanvas();\n }\n\n /**\n * Updates timeline position and draws progressive strokes\n *\n * Redraws the canvas with strokes progressively drawn based on elapsed time.\n * Clears the canvas and redraws all visible strokes.\n * Renders once per call - no continuous loop.\n *\n * @param {number} nowSec - Current timeline position in seconds\n * @throws {Error} If called after layer is destroyed\n * @override\n */\n updateTime(nowSec) {\n super.updateTime(nowSec);\n\n // Check destroyed state\n if (this.isDestroyed) return;\n\n // Clear canvas\n this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);\n\n // Draw each annotation\n for (const a of this.annotations) {\n // Skip annotations that haven't started yet\n if (nowSec < a.start) continue;\n\n // Calculate elapsed time (capped at duration for persistence)\n const duration = a.end - a.start;\n const elapsed = Math.min(nowSec - a.start, duration);\n\n // Draw each stroke\n for (const stroke of (a.strokes || [])) {\n // Configure stroke style\n this.ctx.lineCap = 'round';\n this.ctx.lineJoin = 'round';\n this.ctx.strokeStyle = stroke.color || '#1f2937';\n this.ctx.lineWidth = stroke.size || 3;\n this.ctx.beginPath();\n\n let started = false;\n\n // Draw points up to current time\n for (const point of stroke.points) {\n // Skip points that haven't been drawn yet\n if (point.t > elapsed) break;\n\n // Convert normalized coordinates to canvas pixels\n const x = point.x * this.viewport.width;\n const y = point.y * this.viewport.height;\n\n if (!started) {\n this.ctx.moveTo(x, y);\n started = true;\n } else {\n this.ctx.lineTo(x, y);\n }\n }\n\n // Render the stroke\n if (started) {\n this.ctx.stroke();\n }\n }\n }\n }\n\n /**\n * Renders the layer content\n *\n * No-op for DrawingLayer - canvas rendering happens in updateTime().\n * Canvas element is created once in constructor.\n *\n * @override\n */\n render() {\n // No-op: Canvas rendering happens in updateTime()\n // Canvas element is created once in constructor\n }\n\n /**\n * Updates the visual state of the layer\n *\n * Not used for DrawingLayer - updateTime() handles drawing directly.\n *\n * @override\n */\n update() {\n // Not used - updateTime handles drawing directly\n }\n\n /**\n * Destroys the layer and releases resources\n *\n * Clears references and removes canvas from DOM.\n * Safe to call multiple times (idempotent).\n *\n * @override\n */\n destroy() {\n // Clear context reference\n this.ctx = null;\n\n // Remove canvas from DOM\n if (this.canvasElement && this.canvasElement.parentNode) {\n this.canvasElement.parentNode.removeChild(this.canvasElement);\n }\n this.canvasElement = null;\n\n // Call parent cleanup (always last)\n super.destroy();\n }\n}\n\nexport default DrawingLayer;\n"],"names":["DrawingLayer","BaseLayer","container","viewport","dpr","nowSec","a","duration","elapsed","stroke","started","point","x","y"],"mappings":";AAkBA,MAAMA,UAAqBC,EAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUnC,YAAYC,GAAWC,GAAU;AAC/B,UAAMD,GAAWC,CAAQ,GAGzB,KAAK,gBAAgB,SAAS,cAAc,QAAQ,GACpD,KAAK,cAAc,MAAM,WAAW,YACpC,KAAK,cAAc,MAAM,QAAQ,KACjC,KAAK,cAAc,MAAM,gBAAgB,QACzC,KAAK,cAAc,MAAM,SAAS,MAGlC,KAAK,UAAU,YAAY,KAAK,aAAa,GAG7C,KAAK,MAAM,KAAK,cAAc,WAAW,IAAI,GAG7C,KAAK,aAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,eAAe;AACb,UAAMC,IAAM,OAAO,oBAAoB;AAGvC,SAAK,cAAc,QAAQ,KAAK,MAAM,KAAK,SAAS,QAAQA,CAAG,GAC/D,KAAK,cAAc,SAAS,KAAK,MAAM,KAAK,SAAS,SAASA,CAAG,GAGjE,KAAK,cAAc,MAAM,QAAQ,GAAG,KAAK,SAAS,KAAK,MACvD,KAAK,cAAc,MAAM,SAAS,GAAG,KAAK,SAAS,MAAM,MAGzD,KAAK,IAAI,aAAaA,GAAK,GAAG,GAAGA,GAAK,GAAG,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,YAAYD,GAAU;AACpB,UAAM,YAAYA,CAAQ,GAC1B,KAAK,aAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAWE,GAAQ;AAIjB,QAHA,MAAM,WAAWA,CAAM,GAGnB,MAAK,aAGT;AAAA,WAAK,IAAI,UAAU,GAAG,GAAG,KAAK,cAAc,OAAO,KAAK,cAAc,MAAM;AAG5E,iBAAWC,KAAK,KAAK,aAAa;AAEhC,YAAID,IAASC,EAAE,MAAO;AAGtB,cAAMC,IAAWD,EAAE,MAAMA,EAAE,OACrBE,IAAU,KAAK,IAAIH,IAASC,EAAE,OAAOC,CAAQ;AAGnD,mBAAWE,KAAWH,EAAE,WAAW,CAAA,GAAK;AAEtC,eAAK,IAAI,UAAU,SACnB,KAAK,IAAI,WAAW,SACpB,KAAK,IAAI,cAAcG,EAAO,SAAS,WACvC,KAAK,IAAI,YAAYA,EAAO,QAAQ,GACpC,KAAK,IAAI,UAAS;AAElB,cAAIC,IAAU;AAGd,qBAAWC,KAASF,EAAO,QAAQ;AAEjC,gBAAIE,EAAM,IAAIH,EAAS;AAGvB,kBAAMI,IAAID,EAAM,IAAI,KAAK,SAAS,OAC5BE,IAAIF,EAAM,IAAI,KAAK,SAAS;AAElC,YAAKD,IAIH,KAAK,IAAI,OAAOE,GAAGC,CAAC,KAHpB,KAAK,IAAI,OAAOD,GAAGC,CAAC,GACpBH,IAAU;AAAA,UAId;AAGA,UAAIA,KACF,KAAK,IAAI,OAAM;AAAA,QAEnB;AAAA,MACF;AAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAAS;AAAA,EAGT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAAU;AAER,SAAK,MAAM,MAGP,KAAK,iBAAiB,KAAK,cAAc,cAC3C,KAAK,cAAc,WAAW,YAAY,KAAK,aAAa,GAE9D,KAAK,gBAAgB,MAGrB,MAAM,QAAO;AAAA,EACf;AACF;"}
|
package/package.json
CHANGED