@@ -10,6 +10,7 @@ import {
10
10
import { $selectedBreakpoint } from "~/shared/nano-states" ;
11
11
import { $selectedPage } from "~/shared/awareness" ;
12
12
import { serverSyncStore } from "~/shared/sync" ;
13
+ import { doNotTrackMutation } from "~/shared/dom-utils" ;
13
14
14
15
const isHtmlTag = ( tag : string ) : tag is HtmlTags =>
15
16
htmlTags . includes ( tag as HtmlTags ) ;
@@ -34,22 +35,6 @@ const isSelectorSupported = (selector: string) => {
34
35
}
35
36
} ;
36
37
37
- // This mark helps us detect if mutations were caused by the collapse algorithm
38
- const markCollapsedMutationProperty = `--ws-sys-collapsed-mutation` ;
39
-
40
- /**
41
- * Avoid infinite loop of mutations
42
- */
43
- export const hasCollapsedMutationRecord = (
44
- mutationRecords : MutationRecord [ ]
45
- ) => {
46
- return mutationRecords . some ( ( record ) =>
47
- record . type === "attributes"
48
- ? ( record . oldValue ?. includes ( markCollapsedMutationProperty ) ?? false )
49
- : false
50
- ) ;
51
- } ;
52
-
53
38
const getInstanceSize = ( instanceId : string , tagName : HtmlTags | undefined ) => {
54
39
const metas = $registeredComponentMetas . get ( ) ;
55
40
const breakpoints = $breakpoints . get ( ) ;
@@ -246,14 +231,25 @@ const recalculate = () => {
246
231
// If most elements are collapsed at the next step, scrollHeight becomes equal to clientHeight,
247
232
// which resets the scroll position. To prevent this, we set the document's height to the current scrollHeight
248
233
// to preserve the scroll position.
249
- const preserveHeight = document . documentElement . style . height ;
250
-
251
- // Mark that we are in the process of recalculating collapsed elements
252
- document . documentElement . style . setProperty (
253
- markCollapsedMutationProperty ,
254
- `true`
255
- ) ;
256
- document . documentElement . style . height = `${ document . documentElement . scrollHeight } px` ;
234
+ // use nested element to avoid full page repaint and freeze on big projects
235
+ let collapsedElement = document . querySelector (
236
+ "#ws-collapsed"
237
+ ) as null | HTMLElement ;
238
+ if ( ! collapsedElement ) {
239
+ collapsedElement = document . createElement ( "div" ) as HTMLElement ;
240
+ collapsedElement . style . position = "absolute" ;
241
+ collapsedElement . style . top = "0px" ;
242
+ collapsedElement . style . left = "0px" ;
243
+ collapsedElement . style . right = "0px" ;
244
+ collapsedElement . setAttribute ( "id" , "ws-collapsed" ) ;
245
+ collapsedElement . setAttribute ( "hidden" , "true" ) ;
246
+ // Mark that we are in the process of recalculating collapsed elements
247
+ // to avoid infinite loop of mutations
248
+ doNotTrackMutation ( collapsedElement ) ;
249
+ document . documentElement . appendChild ( collapsedElement ) ;
250
+ }
251
+ collapsedElement . removeAttribute ( "hidden" ) ;
252
+ collapsedElement . style . height = `${ document . documentElement . scrollHeight } px` ;
257
253
258
254
// Now combine all operations in batches.
259
255
@@ -299,8 +295,7 @@ const recalculate = () => {
299
295
element . setAttribute ( collapsedAttribute , value ) ;
300
296
}
301
297
302
- document . documentElement . style . height = preserveHeight ;
303
- document . documentElement . style . removeProperty ( markCollapsedMutationProperty ) ;
298
+ collapsedElement . setAttribute ( "hidden" , "true" ) ;
304
299
} ;
305
300
306
301
/**
0 commit comments