@@ -13,7 +13,6 @@ function applyCodeFocus() {
1313 const focusEnd = parseInt ( viewport . dataset . focusEnd ) ;
1414
1515 if ( ! focusStart || ! focusEnd ) {
16- // No focus specified - reset
1716 const scroll = viewport . querySelector ( '.code-scroll' ) ;
1817 const dimTop = viewport . querySelector ( '.code-dim-top' ) ;
1918 const dimBottom = viewport . querySelector ( '.code-dim-bottom' ) ;
@@ -28,33 +27,27 @@ function applyCodeFocus() {
2827 const dimBottom = viewport . querySelector ( '.code-dim-bottom' ) ;
2928 if ( ! scroll ) return ;
3029
31- // Wait for content to render, then calculate positions
3230 requestAnimationFrame ( ( ) => {
33- // Find the pre element and measure line height
3431 const pre = scroll . querySelector ( 'pre' ) ;
3532 if ( ! pre ) return ;
3633
37- // Get computed line height from the code content
3834 const code = pre . querySelector ( 'code, syntax-code' ) || pre ;
3935 const style = getComputedStyle ( code ) ;
4036 const lineHeight = parseFloat ( style . lineHeight ) || parseFloat ( style . fontSize ) * 1.6 ;
4137
4238 const padding = parseFloat ( getComputedStyle ( scroll ) . paddingTop ) || 16 ;
4339 const viewportHeight = viewport . clientHeight ;
4440
45- // Calculate pixel positions for focus region
4641 const focusTopPx = padding + ( focusStart - 1 ) * lineHeight ;
4742 const focusBottomPx = padding + focusEnd * lineHeight ;
4843 const focusHeight = focusBottomPx - focusTopPx ;
4944
50- // Center the focus region in the viewport
5145 const targetCenter = focusTopPx + focusHeight / 2 ;
5246 const viewportCenter = viewportHeight / 2 ;
5347 const translateY = Math . min ( 0 , viewportCenter - targetCenter ) ;
5448
5549 scroll . style . transform = `translateY(${ translateY } px)` ;
5650
57- // Position the dim overlays
5851 const dimTopHeight = Math . max ( 0 , focusTopPx + translateY ) ;
5952 const dimBottomHeight = Math . max ( 0 , viewportHeight - ( focusBottomPx + translateY ) ) ;
6053
@@ -64,8 +57,44 @@ function applyCodeFocus() {
6457 } ) ;
6558}
6659
67- // Re-highlight and apply focus after Live DOM updates:
60+ // Detect the transition type from the incoming HTML before morphdom applies it.
61+ function detectTransition ( html ) {
62+ const match = html . match ( / d a t a - t r a n s i t i o n = " ( [ ^ " ] + ) " / ) ;
63+ return match ? match [ 1 ] : null ;
64+ }
65+
66+ // Track the active view transition so we can skip overlapping ones.
67+ let activeTransition = null ;
68+
69+ // Wrap Live's update method to support view transitions.
70+ const originalUpdate = live . update . bind ( live ) ;
71+ live . update = function ( id , html , options ) {
72+ // Only apply transitions on the display view, not the presenter:
73+ const transition = document . querySelector ( '.display' ) ? detectTransition ( html ) : null ;
74+
75+ if ( transition && document . startViewTransition && ! activeTransition ) {
76+ document . documentElement . dataset . transition = transition ;
77+
78+ activeTransition = document . startViewTransition ( ( ) => {
79+ originalUpdate ( id , html , options ) ;
80+ } ) ;
81+
82+ activeTransition . finished . finally ( ( ) => {
83+ delete document . documentElement . dataset . transition ;
84+ activeTransition = null ;
85+ Syntax . highlight ( ) ;
86+ applyCodeFocus ( ) ;
87+ } ) ;
88+ } else {
89+ originalUpdate ( id , html , options ) ;
90+ Syntax . highlight ( ) ;
91+ applyCodeFocus ( ) ;
92+ }
93+ } ;
94+
95+ // Re-highlight and apply focus after non-update DOM mutations (e.g. replace):
6896const observer = new MutationObserver ( ( ) => {
97+ if ( activeTransition ) return ;
6998 Syntax . highlight ( ) ;
7099 applyCodeFocus ( ) ;
71100} ) ;
0 commit comments