@@ -235,7 +235,14 @@ export class FixedLayout extends HTMLElement {
235235 if ( ! iframe ) return
236236 if ( onZoom ) {
237237 const p = onZoom ( { doc : frame . iframe . contentDocument , scale, pageColors : this . #pageColors } )
238- if ( p ?. then ) renderPromises . push ( p )
238+ if ( p ?. then ) {
239+ // onZoom (e.g. pdf.js) may rebuild the text layer DOM,
240+ // invalidating Range objects stored in the overlayer. After
241+ // the rebuild, re-emit create-overlayer so listeners can
242+ // re-anchor annotations against the fresh DOM.
243+ const refreshed = p . then ( ( ) => this . #refreshOverlayerForFrame( frame ) )
244+ renderPromises . push ( refreshed )
245+ }
239246 }
240247 const iframeScale = onZoom ? scale : 1
241248 const zoomedOut = this . #scaleFactor < 1.0
@@ -1028,6 +1035,35 @@ export class FixedLayout extends HTMLElement {
10281035 ? parseInt ( frame . iframe . dataset . sectionIndex ) : undefined
10291036 if ( idx != null ) this . #overlayers. delete ( idx )
10301037 }
1038+ // Drop a frame's overlayer and re-emit create-overlayer so listeners can
1039+ // re-add annotations. Called after a text layer rebuild (e.g. pdf.js
1040+ // onZoom) which invalidates Range objects stored in the overlayer.
1041+ #refreshOverlayerForFrame( frame ) {
1042+ if ( ! frame ?. iframe ) return
1043+ const index = frame . iframe . dataset . sectionIndex != null
1044+ ? parseInt ( frame . iframe . dataset . sectionIndex ) : undefined
1045+ if ( index == null ) return
1046+ const stale = this . #overlayers. get ( index )
1047+ if ( ! stale ) return
1048+ // Only refresh for frames currently visible; hidden frames keep their
1049+ // overlayer untouched until they are shown again.
1050+ const isVisible = frame . element ?. parentNode
1051+ && frame . element . style . visibility !== 'hidden'
1052+ if ( ! isVisible ) return
1053+ stale . element ?. remove ( )
1054+ this . #overlayers. delete ( index )
1055+ const doc = frame . iframe . contentDocument
1056+ if ( ! doc ) return
1057+ this . dispatchEvent ( new CustomEvent ( 'create-overlayer' , {
1058+ detail : {
1059+ doc, index,
1060+ attach : overlayer => {
1061+ this . #overlayers. set ( index , overlayer )
1062+ frame . element . append ( overlayer . element )
1063+ } ,
1064+ } ,
1065+ } ) )
1066+ }
10311067 async select ( target ) {
10321068 await this . goTo ( target )
10331069 // TODO
0 commit comments