@@ -13,7 +13,6 @@ import { clsx } from 'clsx';
1313import type { CSSProperties , ReactElement , ReactNode } from 'react' ;
1414import { cloneElement , forwardRef , isValidElement , useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
1515import { ObjectPageMode } from '../../enums/index.js' ;
16- import { addCustomCSSWithScoping } from '../../internal/addCustomCSSWithScoping.js' ;
1716import { safeGetChildrenArray } from '../../internal/safeGetChildrenArray.js' ;
1817import { useObserveHeights } from '../../internal/useObserveHeights.js' ;
1918import type { CommonProps , Ui5CustomEvent } from '../../types/index.js' ;
@@ -32,17 +31,7 @@ import type {
3231} from '../ObjectPageTitle/index.js' ;
3332import { CollapsedAvatar } from './CollapsedAvatar.js' ;
3433import { classNames , styleData } from './ObjectPage.module.css.js' ;
35- import { extractSectionIdFromHtmlId , getSectionById } from './ObjectPageUtils.js' ;
36-
37- addCustomCSSWithScoping (
38- 'ui5-tabcontainer' ,
39- // todo: the additional text span adds 3px to the container - needs to be investigated why
40- `
41- :host([data-component-name="ObjectPageTabContainer"]) [id$="additionalText"] {
42- display: none;
43- }
44- `
45- ) ;
34+ import { getSectionById } from './ObjectPageUtils.js' ;
4635
4736const ObjectPageCssVariables = {
4837 headerDisplay : '--_ui5wcr_ObjectPage_header_display' ,
@@ -239,7 +228,6 @@ const ObjectPage = forwardRef<ObjectPageDomRef, ObjectPagePropTypes>((props, ref
239228 const anchorBarRef = useRef < HTMLDivElement > ( null ) ;
240229 const objectPageContentRef = useRef < HTMLDivElement > ( null ) ;
241230 const selectionScrollTimeout = useRef ( null ) ;
242- const [ isAfterScroll , setIsAfterScroll ] = useState ( false ) ;
243231 const isToggledRef = useRef ( false ) ;
244232 const [ headerCollapsedInternal , setHeaderCollapsedInternal ] = useState < undefined | boolean > ( undefined ) ;
245233 const [ scrolledHeaderExpanded , setScrolledHeaderExpanded ] = useState ( false ) ;
@@ -256,7 +244,7 @@ const ObjectPage = forwardRef<ObjectPageDomRef, ObjectPagePropTypes>((props, ref
256244
257245 const prevInternalSelectedSectionId = useRef ( internalSelectedSectionId ) ;
258246 const fireOnSelectedChangedEvent = ( targetEvent , index , id , section ) => {
259- if ( typeof onSelectedSectionChange === 'function' && prevInternalSelectedSectionId . current !== id ) {
247+ if ( typeof onSelectedSectionChange === 'function' && targetEvent && prevInternalSelectedSectionId . current !== id ) {
260248 onSelectedSectionChange (
261249 enrichEventWithDetails ( targetEvent , {
262250 selectedSectionIndex : parseInt ( index , 10 ) ,
@@ -344,7 +332,7 @@ const ObjectPage = forwardRef<ObjectPageDomRef, ObjectPagePropTypes>((props, ref
344332 safeTopHeaderHeight +
345333 anchorBarHeight +
346334 TAB_CONTAINER_HEADER_HEIGHT +
347- ( headerPinned ? headerContentHeight : 0 ) +
335+ ( headerPinned && ! headerCollapsed ? headerContentHeight : 0 ) +
348336 'px' ;
349337 section . focus ( ) ;
350338 section . scrollIntoView ( { behavior : 'smooth' } ) ;
@@ -558,76 +546,53 @@ const ObjectPage = forwardRef<ObjectPageDomRef, ObjectPagePropTypes>((props, ref
558546
559547 const { onScroll : _0 , selectedSubSectionId : _1 , ...propsWithoutOmitted } = rest ;
560548
549+ const visibleSectionIds = useRef < Set < string > > ( new Set ( ) ) ;
561550 useEffect ( ( ) => {
562551 const sectionNodes = objectPageRef . current ?. querySelectorAll ( 'section[data-component-name="ObjectPageSection"]' ) ;
563- const objectPageHeight = objectPageRef . current ?. clientHeight ?? 1000 ;
564- const marginBottom = objectPageHeight - totalHeaderHeight - /*TabContainer*/ TAB_CONTAINER_HEADER_HEIGHT ;
565- const rootMargin = `- ${ totalHeaderHeight } px 0px - ${ marginBottom < 0 ? 0 : marginBottom } px 0px` ;
552+ // only the sticky part of the header must be added as margin
553+ const rootMargin = `- ${ ( headerPinned && ! headerCollapsed ? totalHeaderHeight : topHeaderHeight ) + TAB_CONTAINER_HEADER_HEIGHT } px 0px 0px 0px` ;
554+
566555 const observer = new IntersectionObserver (
567- ( [ section ] ) => {
568- if ( section . isIntersecting && isProgrammaticallyScrolled . current === false ) {
569- if (
570- objectPageRef . current . getBoundingClientRect ( ) . top + totalHeaderHeight + TAB_CONTAINER_HEADER_HEIGHT <=
571- section . target . getBoundingClientRect ( ) . bottom
572- ) {
573- const currentId = extractSectionIdFromHtmlId ( section . target . id ) ;
574- setInternalSelectedSectionId ( currentId ) ;
575- const currentIndex = safeGetChildrenArray ( children ) . findIndex ( ( objectPageSection ) => {
576- return (
577- isValidElement ( objectPageSection ) &&
578- ( objectPageSection as ReactElement < ObjectPageSectionPropTypes > ) . props ?. id === currentId
579- ) ;
580- } ) ;
581- debouncedOnSectionChange ( scrollEvent . current , currentIndex , currentId , section . target ) ;
556+ ( entries ) => {
557+ entries . forEach ( ( entry ) => {
558+ const sectionId = entry . target . id ;
559+ if ( entry . isIntersecting ) {
560+ visibleSectionIds . current . add ( sectionId ) ;
561+ } else {
562+ visibleSectionIds . current . delete ( sectionId ) ;
582563 }
583- }
564+
565+ let currentIndex : undefined | number ;
566+ const sortedVisibleSections = Array . from ( sectionNodes ) . filter ( ( section , index ) => {
567+ const isVisibleSection = visibleSectionIds . current . has ( section . id ) ;
568+ if ( currentIndex === undefined && isVisibleSection ) {
569+ currentIndex = index ;
570+ }
571+ return visibleSectionIds . current . has ( section . id ) ;
572+ } ) ;
573+
574+ if ( sortedVisibleSections . length > 0 ) {
575+ const section = sortedVisibleSections [ 0 ] ;
576+ const id = sortedVisibleSections [ 0 ] . id . slice ( 18 ) ;
577+ setInternalSelectedSectionId ( id ) ;
578+ debouncedOnSectionChange ( scrollEvent . current , currentIndex , id , section ) ;
579+ }
580+ } ) ;
584581 } ,
585582 {
586583 root : objectPageRef . current ,
587584 rootMargin,
588585 threshold : [ 0 ]
589586 }
590587 ) ;
591-
592588 sectionNodes . forEach ( ( el ) => {
593589 observer . observe ( el ) ;
594590 } ) ;
595591
596592 return ( ) => {
597593 observer . disconnect ( ) ;
598594 } ;
599- } , [ children , totalHeaderHeight , setInternalSelectedSectionId , isProgrammaticallyScrolled ] ) ;
600-
601- // Fallback when scrolling faster than the IntersectionObserver can observe (in most cases faster than 60fps)
602- useEffect ( ( ) => {
603- const sectionNodes = objectPageRef . current ?. querySelectorAll ( 'section[data-component-name="ObjectPageSection"]' ) ;
604- if ( isAfterScroll ) {
605- let currentSection = sectionNodes [ sectionNodes . length - 1 ] ;
606- let currentIndex : number ;
607- for ( let i = 0 ; i <= sectionNodes . length - 1 ; i ++ ) {
608- const sectionNode = sectionNodes [ i ] ;
609- if (
610- objectPageRef . current . getBoundingClientRect ( ) . top + totalHeaderHeight + TAB_CONTAINER_HEADER_HEIGHT <=
611- sectionNode . getBoundingClientRect ( ) . bottom
612- ) {
613- currentSection = sectionNode ;
614- currentIndex = i ;
615- break ;
616- }
617- }
618- const currentSectionId = extractSectionIdFromHtmlId ( currentSection ?. id ) ;
619- if ( currentSectionId !== internalSelectedSectionId ) {
620- setInternalSelectedSectionId ( currentSectionId ) ;
621- debouncedOnSectionChange (
622- scrollEvent . current ,
623- currentIndex ?? sectionNodes . length - 1 ,
624- currentSectionId ,
625- currentSection
626- ) ;
627- }
628- setIsAfterScroll ( false ) ;
629- }
630- } , [ isAfterScroll ] ) ;
595+ } , [ children , totalHeaderHeight , setInternalSelectedSectionId , headerPinned , debouncedOnSectionChange ] ) ;
631596
632597 const onTitleClick = ( e ) => {
633598 e . stopPropagation ( ) ;
@@ -721,9 +686,6 @@ const ObjectPage = forwardRef<ObjectPageDomRef, ObjectPagePropTypes>((props, ref
721686 if ( selectionScrollTimeout . current ) {
722687 clearTimeout ( selectionScrollTimeout . current ) ;
723688 }
724- selectionScrollTimeout . current = setTimeout ( ( ) => {
725- setIsAfterScroll ( true ) ;
726- } , 100 ) ;
727689 if ( ! headerPinned || e . target . scrollTop === 0 ) {
728690 objectPageRef . current ?. classList . remove ( classNames . headerCollapsed ) ;
729691 }
@@ -894,7 +856,7 @@ const ObjectPage = forwardRef<ObjectPageDomRef, ObjectPagePropTypes>((props, ref
894856 </ div >
895857 ) }
896858 < div data-component-name = "ObjectPageContent" className = { classNames . content } ref = { objectPageContentRef } >
897- < div style = { { height : headerCollapsed ? `${ headerContentHeight } px` : 0 } } aria-hidden />
859+ < div style = { { height : headerCollapsed && ! headerPinned ? `${ headerContentHeight } px` : 0 } } aria-hidden />
898860 { placeholder ? placeholder : sections }
899861 < div style = { { height : `${ sectionSpacer } px` } } aria-hidden />
900862 </ div >
0 commit comments