@@ -40,9 +40,18 @@ const MAX_ELEMENTS = 500; // max items
40
40
const SCROLL_WIDTH = 30 ;
41
41
// we have to put the html on top of the notebook to be visible. This is the z-index we use.
42
42
const Z_INDEX = 1 ;
43
- // no matter what when the html is in the REACT dom, it will have its position updated this frequently.
44
- // it also gets updated on scroll of the cell list.
45
- const POSITION_WHEN_MOUNTED_INTERVAL_MS = 500 ;
43
+
44
+ // POSITION_WHEN_MOUNTED_INTERVAL_MS: No matter what when the html is in the REACT
45
+ // dom, it will have its position updated this frequently.
46
+ // it also gets updated on scroll of the cell list. This also serves to
47
+ // ensure that this item has a recent ttl so it isn't cleared from the ttl cache.
48
+ // It should NOT ever actually be needed, since we always update the position on
49
+ // resize and scroll events.
50
+ const POSITION_WHEN_MOUNTED_INTERVAL_MS = 10000 ;
51
+
52
+ // Scroll actively this many frames after each update, due to throttling of onscroll
53
+ // and other events. This is to eliminate lag.
54
+ const SCROLL_COUNT = 30 ;
46
55
47
56
const cache = new TTL < string , any > ( {
48
57
ttl : IDLE_TIMEOUT_S * 1000 ,
@@ -121,7 +130,7 @@ export default function StableUnsafeHtml({
121
130
// }px`;
122
131
123
132
// clip our immortal html so it isn't visible outside the parent
124
- const parent = $ ( stableHtmlContext . cellListDivRef ?. current ) [ 0 ] ;
133
+ const parent = stableHtmlContext . cellListDivRef ?. current ;
125
134
if ( parent != null ) {
126
135
const parentRect = parent . getBoundingClientRect ( ) ;
127
136
// Calculate the overlap area
@@ -151,8 +160,8 @@ export default function StableUnsafeHtml({
151
160
// Apply clip-path to elt to make it visible only inside of parentRect:
152
161
elt . style . clipPath = `polygon(${ left } px ${ top } px, ${ right } px ${ top } px, ${ right } px ${ bottom } px, ${ left } px ${ bottom } px)` ;
153
162
154
- // Set widht , so it possible to scroll horizontally and see whatever widget is in the output.
155
- const w = $ ( divRef . current ) . width ( ) ;
163
+ // Set width , so it possible to scroll horizontally and see whatever widget is in the output.
164
+ const w = divRef . current . offsetWidth ;
156
165
if ( w ) {
157
166
elt . style . width = `${ w } px` ;
158
167
}
@@ -212,24 +221,35 @@ export default function StableUnsafeHtml({
212
221
} , [ isVisible ] ) ;
213
222
214
223
useEffect ( ( ) => {
215
- // TOOD: can we get rid of interval by using a resize observer on
216
- // this stableHtmlContext.cellListDivRef?
217
224
intervalRef . current = setInterval (
218
225
position ,
219
226
POSITION_WHEN_MOUNTED_INTERVAL_MS ,
220
227
) ;
221
- if ( stableHtmlContext . htmlOnScrolls != null ) {
222
- stableHtmlContext . htmlOnScrolls [ globalKey ] = async ( ) => {
223
- position ( ) ;
224
- await new Promise ( requestAnimationFrame ) ;
228
+ if ( stableHtmlContext . scrollOrResize != null ) {
229
+ let count = 0 ;
230
+ stableHtmlContext . scrollOrResize [ globalKey ] = async ( ) => {
231
+ if ( count > 0 ) {
232
+ return ;
233
+ }
234
+ // We run position a lot whenever there is a scroll
235
+ // in order to make it so the iframe doesn't appear
236
+ // to just get "dragged along" nearly as much, as
237
+ // onScroll is throttled.
238
+ count = SCROLL_COUNT ;
239
+ while ( count > 0 ) {
240
+ position ( ) ;
241
+ await new Promise ( requestAnimationFrame ) ;
242
+ count -= 1 ;
243
+ }
244
+ // throw in an update when we're done.
225
245
position ( ) ;
226
246
} ;
227
247
}
228
248
position ( ) ;
229
249
setTimeout ( position , 0 ) ;
230
250
231
251
return ( ) => {
232
- delete stableHtmlContext . htmlOnScrolls ?. [ globalKey ] ;
252
+ delete stableHtmlContext . scrollOrResize ?. [ globalKey ] ;
233
253
if ( intervalRef . current ) {
234
254
clearInterval ( intervalRef . current ) ;
235
255
}
0 commit comments