@@ -118,6 +118,7 @@ export class Datetime implements ComponentInterface {
118118
119119 private destroyCalendarListener ?: ( ) => void ;
120120 private destroyKeyboardMO ?: ( ) => void ;
121+ private destroyOverlayListeners ?: ( ) => void ;
121122
122123 // TODO(FW-2832): types (DatetimeParts causes some errors that need untangling)
123124 private minParts ?: any ;
@@ -1081,6 +1082,10 @@ export class Datetime implements ComponentInterface {
10811082 this . resizeObserver . disconnect ( ) ;
10821083 this . resizeObserver = undefined ;
10831084 }
1085+ if ( this . destroyOverlayListeners ) {
1086+ this . destroyOverlayListeners ( ) ;
1087+ this . destroyOverlayListeners = undefined ;
1088+ }
10841089 }
10851090
10861091 /**
@@ -1105,26 +1110,6 @@ export class Datetime implements ComponentInterface {
11051110 this . initializeKeyboardListeners ( ) ;
11061111 }
11071112
1108- /**
1109- * FW-6931: Fallback check for when ResizeObserver doesn't fire reliably
1110- * (e.g., WebKit during modal re-presentation). Called after element is
1111- * hidden to catch when it becomes visible again.
1112- */
1113- private checkVisibilityFallback = ( ) => {
1114- const { el } = this ;
1115- if ( el . classList . contains ( 'datetime-ready' ) ) {
1116- return ;
1117- }
1118-
1119- const rect = el . getBoundingClientRect ( ) ;
1120- if ( rect . width > 0 && rect . height > 0 ) {
1121- this . initializeListeners ( ) ;
1122- writeTask ( ( ) => {
1123- el . classList . add ( 'datetime-ready' ) ;
1124- } ) ;
1125- }
1126- } ;
1127-
11281113 componentDidLoad ( ) {
11291114 const { el } = this ;
11301115
@@ -1141,6 +1126,9 @@ export class Datetime implements ComponentInterface {
11411126 * especially when the element is inside a modal or popover.
11421127 */
11431128 const markReady = ( ) => {
1129+ if ( el . classList . contains ( 'datetime-ready' ) ) {
1130+ return ;
1131+ }
11441132 this . initializeListeners ( ) ;
11451133 writeTask ( ( ) => {
11461134 el . classList . add ( 'datetime-ready' ) ;
@@ -1153,13 +1141,28 @@ export class Datetime implements ComponentInterface {
11531141 writeTask ( ( ) => {
11541142 el . classList . remove ( 'datetime-ready' ) ;
11551143 } ) ;
1156- /**
1157- * Schedule fallback check for browsers where ResizeObserver
1158- * doesn't fire reliably on re-presentation (e.g., WebKit).
1159- */
1160- setTimeout ( ( ) => this . checkVisibilityFallback ( ) , 100 ) ;
11611144 } ;
11621145
1146+ /**
1147+ * FW-6931: If datetime is inside a popover or modal, listen for the
1148+ * overlay's present/dismiss events. This is more reliable than
1149+ * ResizeObserver in some browsers (e.g., WebKit) where the observer
1150+ * doesn't always fire when the overlay opens.
1151+ */
1152+ const parentOverlay = el . closest ( 'ion-modal, ion-popover' ) as HTMLIonModalElement | HTMLIonPopoverElement | null ;
1153+ if ( parentOverlay ) {
1154+ const handlePresent = ( ) => markReady ( ) ;
1155+ const handleDismiss = ( ) => markHidden ( ) ;
1156+
1157+ parentOverlay . addEventListener ( 'didPresent' , handlePresent ) ;
1158+ parentOverlay . addEventListener ( 'didDismiss' , handleDismiss ) ;
1159+
1160+ this . destroyOverlayListeners = ( ) => {
1161+ parentOverlay . removeEventListener ( 'didPresent' , handlePresent ) ;
1162+ parentOverlay . removeEventListener ( 'didDismiss' , handleDismiss ) ;
1163+ } ;
1164+ }
1165+
11631166 if ( typeof ResizeObserver !== 'undefined' ) {
11641167 this . resizeObserver = new ResizeObserver ( ( entries ) => {
11651168 const entry = entries [ 0 ] ;
@@ -1179,12 +1182,6 @@ export class Datetime implements ComponentInterface {
11791182 * its display animation starting (such as when shown in a modal).
11801183 */
11811184 raf ( ( ) => this . resizeObserver ?. observe ( el ) ) ;
1182-
1183- /**
1184- * Fallback for initial presentation in case ResizeObserver
1185- * doesn't fire reliably (e.g., WebKit).
1186- */
1187- setTimeout ( ( ) => this . checkVisibilityFallback ( ) , 100 ) ;
11881185 } else {
11891186 /**
11901187 * Fallback for test environments where ResizeObserver is not available.
0 commit comments