@@ -23,14 +23,19 @@ SPDX-License-Identifier: AGPL-3.0-or-later
2323 />
2424 <div
2525 class =" overlay"
26+ :role =" isAddingMode ? 'button' : undefined"
27+ :tabindex =" isAddingMode ? 0 : -1"
28+ :aria-label =" getOverlayAriaLabel(docIndex, pIndex)"
2629 @mousemove =" handleMouseMove"
2730 @touchmove =" handleMouseMove"
2831 @click =" handleOverlayClick(docIndex, pIndex, $event)"
2932 @touchend =" handleOverlayClick(docIndex, pIndex, $event)"
33+ @keydown =" handleOverlayKeyDown(docIndex, pIndex, $event)"
3034 >
3135 <div
3236 v-if =" isAddingMode && previewPageDocIndex === docIndex && previewPageIndex === pIndex && previewElement && previewVisible"
3337 class =" preview-element"
38+ aria-hidden =" true"
3439 :style =" {
3540 left: `${previewPosition.x * previewScale.x}px`,
3641 top: `${previewPosition.y * previewScale.y}px`,
@@ -217,6 +222,10 @@ export default defineComponent({
217222 type: Boolean ,
218223 default: false ,
219224 },
225+ pageAriaLabel: {
226+ type: Function as PropType <(info : { docIndex: number ; docName: string ; totalDocs: number ; pageNumber: number ; totalPages: number ; isAddingMode: boolean }) => string >,
227+ default: null ,
228+ },
220229 pdfjsOptions: {
221230 type: Object as PropType <Record <string , unknown >>,
222231 default : () => ({}),
@@ -532,16 +541,77 @@ export default defineComponent({
532541 },
533542 getPointerPosition(event ) {
534543 if (event ?.type ?.includes ?.(' touch' )) {
544+ const touch = event .touches ?.[0 ] || event .changedTouches ?.[0 ]
535545 return {
536- x: event . touches ?.[ 0 ] ?.clientX ,
537- y: event . touches ?.[ 0 ] ?.clientY ,
546+ x: touch ?.clientX ,
547+ y: touch ?.clientY ,
538548 }
539549 }
540550 return {
541551 x: event ?.clientX ,
542552 y: event ?.clientY ,
543553 }
544554 },
555+ updatePreviewFromClientPoint(cursorX , cursorY ) {
556+ let target = null
557+
558+ if (this .lastHoverRect &&
559+ cursorX >= this .lastHoverRect .left && cursorX <= this .lastHoverRect .right &&
560+ cursorY >= this .lastHoverRect .top && cursorY <= this .lastHoverRect .bottom ) {
561+ target = {
562+ docIndex: this .previewPageDocIndex ,
563+ pageIndex: this .previewPageIndex ,
564+ rect: this .lastHoverRect ,
565+ }
566+ } else {
567+ const rectEntries = this .getPageBoundsList ().length
568+ ? this .getPageBoundsList ()
569+ : Object .values (this .getPageBoundsMap ())
570+ for (let i = 0 ; i < rectEntries .length ; i ++ ) {
571+ const entry = rectEntries [i ]
572+ const rect = entry .rect
573+ if (cursorX >= rect .left && cursorX <= rect .right &&
574+ cursorY >= rect .top && cursorY <= rect .bottom ) {
575+ target = entry
576+ break
577+ }
578+ }
579+ }
580+
581+ if (! target ) {
582+ this .previewVisible = false
583+ this .previewScale = { x: 1 , y: 1 }
584+ this .lastHoverRect = null
585+ return false
586+ }
587+
588+ this .previewPageDocIndex = target .docIndex
589+ this .previewPageIndex = target .pageIndex
590+ this .lastHoverRect = target .rect
591+ const canvasEl = this .getPageCanvasElement (target .docIndex , target .pageIndex )
592+ const pagesScale = this .pdfDocuments [target .docIndex ]?.pagesScale ?.[target .pageIndex ] || 1
593+ const renderWidth = canvasEl ?.width || target .rect .width
594+ const renderHeight = canvasEl ?.height || target .rect .height
595+ const layoutScaleX = renderWidth ? target .rect .width / renderWidth : 1
596+ const layoutScaleY = renderHeight ? target .rect .height / renderHeight : 1
597+ const relX = (cursorX - target .rect .left ) / layoutScaleX / pagesScale
598+ const relY = (cursorY - target .rect .top ) / layoutScaleY / pagesScale
599+
600+ const pageWidth = renderWidth / pagesScale
601+ const pageHeight = renderHeight / pagesScale
602+ this .previewScale .x = pagesScale
603+ this .previewScale .y = pagesScale
604+ let x = relX - this .previewElement .width / 2
605+ let y = relY - this .previewElement .height / 2
606+
607+ x = Math .max (0 , Math .min (x , pageWidth - this .previewElement .width ))
608+ y = Math .max (0 , Math .min (y , pageHeight - this .previewElement .height ))
609+
610+ this .previewPosition .x = x
611+ this .previewPosition .y = y
612+ this .previewVisible = true
613+ return true
614+ },
545615
546616 getDisplayedPageScale(docIndex , pageIndex ) {
547617 void this .pageBoundsVersion
@@ -619,65 +689,7 @@ export default defineComponent({
619689 const pending = this .pendingHoverClientPos
620690 if (! pending ) return
621691
622- const cursorX = pending .x
623- const cursorY = pending .y
624- let target = null
625-
626- if (this .lastHoverRect &&
627- cursorX >= this .lastHoverRect .left && cursorX <= this .lastHoverRect .right &&
628- cursorY >= this .lastHoverRect .top && cursorY <= this .lastHoverRect .bottom ) {
629- target = {
630- docIndex: this .previewPageDocIndex ,
631- pageIndex: this .previewPageIndex ,
632- rect: this .lastHoverRect ,
633- }
634- } else {
635- const rectEntries = this .getPageBoundsList ().length
636- ? this .getPageBoundsList ()
637- : Object .values (this .getPageBoundsMap ())
638- for (let i = 0 ; i < rectEntries .length ; i ++ ) {
639- const entry = rectEntries [i ]
640- const rect = entry .rect
641- if (cursorX >= rect .left && cursorX <= rect .right &&
642- cursorY >= rect .top && cursorY <= rect .bottom ) {
643- target = entry
644- break
645- }
646- }
647- }
648-
649- if (! target ) {
650- this .previewVisible = false
651- this .previewScale = { x: 1 , y: 1 }
652- this .lastHoverRect = null
653- return
654- }
655-
656- this .previewPageDocIndex = target .docIndex
657- this .previewPageIndex = target .pageIndex
658- this .lastHoverRect = target .rect
659- const canvasEl = this .getPageCanvasElement (target .docIndex , target .pageIndex )
660- const pagesScale = this .pdfDocuments [target .docIndex ]?.pagesScale ?.[target .pageIndex ] || 1
661- const renderWidth = canvasEl ?.width || target .rect .width
662- const renderHeight = canvasEl ?.height || target .rect .height
663- const layoutScaleX = renderWidth ? target .rect .width / renderWidth : 1
664- const layoutScaleY = renderHeight ? target .rect .height / renderHeight : 1
665- const relX = (cursorX - target .rect .left ) / layoutScaleX / pagesScale
666- const relY = (cursorY - target .rect .top ) / layoutScaleY / pagesScale
667-
668- const pageWidth = renderWidth / pagesScale
669- const pageHeight = renderHeight / pagesScale
670- this .previewScale .x = pagesScale
671- this .previewScale .y = pagesScale
672- let x = relX - this .previewElement .width / 2
673- let y = relY - this .previewElement .height / 2
674-
675- x = Math .max (0 , Math .min (x , pageWidth - this .previewElement .width ))
676- y = Math .max (0 , Math .min (y , pageHeight - this .previewElement .height ))
677-
678- this .previewPosition .x = x
679- this .previewPosition .y = y
680- this .previewVisible = true
692+ this .updatePreviewFromClientPoint (pending .x , pending .y )
681693 })
682694 },
683695 handleOverlayClick(docIndex , pageIndex , event ) {
@@ -730,6 +742,42 @@ export default defineComponent({
730742 }
731743 },
732744
745+ getOverlayAriaLabel(docIndex , pageIndex ) {
746+ const doc = this .pdfDocuments ?.[docIndex ]
747+ const docName = doc ?.name ?? ` Document ${docIndex + 1 } `
748+ const totalDocs = this .pdfDocuments ?.length ?? 1
749+ const totalPages = doc ?.numPages ?? 0
750+ const pageNumber = pageIndex + 1
751+ if (this .pageAriaLabel ) {
752+ return this .pageAriaLabel ({ docIndex , docName , totalDocs , pageNumber , totalPages , isAddingMode: this .isAddingMode })
753+ }
754+ const docPrefix = totalDocs > 1 ? ` Document ${docIndex + 1 } of ${totalDocs } (${docName }), ` : ' '
755+ if (this .isAddingMode ) {
756+ return ` ${docPrefix }Page ${pageNumber } of ${totalPages }. Press Enter or Space to place here. `
757+ }
758+ return ` ${docPrefix }Page ${pageNumber } of ${totalPages }. `
759+ },
760+
761+ handleOverlayKeyDown(docIndex , pageIndex , event ) {
762+ if (! this .isAddingMode || ! this .previewElement ) return
763+ if (event .key !== ' Enter' && event .key !== ' ' ) return
764+ event .preventDefault ()
765+
766+ const pageWidth = this .getPageWidth (docIndex , pageIndex )
767+ const pageHeight = this .getPageHeight (docIndex , pageIndex )
768+ const scale = this .getDisplayedPageScale (docIndex , pageIndex ) || 1
769+
770+ this .previewPageDocIndex = docIndex
771+ this .previewPageIndex = pageIndex
772+ this .previewScale = { x: scale , y: scale }
773+ this .previewPosition = {
774+ x: Math .round ((pageWidth - this .previewElement .width ) / 2 ),
775+ y: Math .round ((pageHeight - this .previewElement .height ) / 2 ),
776+ }
777+ this .previewVisible = true
778+ this .finishAdding ()
779+ },
780+
733781 handleWheel(event ) {
734782 if (! event .ctrlKey ) return
735783 event .preventDefault ()
@@ -755,8 +803,14 @@ export default defineComponent({
755803 this .cachePageBounds ()
756804 },
757805
758- finishAdding() {
806+ finishAdding(event ) {
759807 if (! this .isAddingMode || ! this .previewElement ) return
808+ if (! this .previewVisible && event ) {
809+ const { x, y } = this .getPointerPosition (event )
810+ if (Number .isFinite (x ) && Number .isFinite (y )) {
811+ this .updatePreviewFromClientPoint (x , y )
812+ }
813+ }
760814 if (! this .previewVisible ) return
761815
762816 const objectToAdd = {
@@ -1205,7 +1259,7 @@ export default defineComponent({
12051259 .flatMap (doc => doc .pageWidths || [])
12061260 .filter (width => width > 0 )
12071261
1208- let maxCanvasWidth = 0
1262+ let maxCanvasWidth
12091263 if (widths .length ) {
12101264 maxCanvasWidth = Math .max (... widths )
12111265 } else {
0 commit comments