@@ -5,7 +5,7 @@ import { getIonMode } from '../../global/ionic-global';
5
5
import type { Color , DatetimePresentation } from '../../interface' ;
6
6
import { createColorClasses } from '../../utils/theme' ;
7
7
import { printIonError } from '../../utils/logging' ;
8
- import { componentOnReady , addEventListener } from '../../utils/helpers' ;
8
+ import { componentOnReady , addEventListener , raf } from '../../utils/helpers' ;
9
9
import { parseDate } from '../datetime/utils/parse' ;
10
10
import { getToday } from '../datetime/utils/data' ;
11
11
import { is24Hour } from '../datetime/utils/helpers' ;
@@ -20,6 +20,7 @@ import { getMonthAndYear, getMonthDayAndYear, getLocalizedDateTime, getLocalized
20
20
} )
21
21
export class DatetimeButton implements ComponentInterface {
22
22
private datetimeEl : HTMLIonDatetimeElement | null = null ;
23
+ private overlayEl : HTMLElement | null = null ;
23
24
24
25
// STUBS
25
26
@State ( ) datetimePresentation ?: DatetimePresentation = 'date-time' ;
@@ -80,7 +81,22 @@ export class DatetimeButton implements ComponentInterface {
80
81
81
82
io . observe ( datetimeEl ) ;
82
83
84
+ /**
85
+ * Get a reference to any modal/popover
86
+ * the datetime is being used in so we can
87
+ * correctly size it when it is presented.
88
+ */
89
+ const overlayEl = this . overlayEl = datetimeEl . closest ( 'ion-modal, ion-popover' ) ;
90
+
83
91
componentOnReady ( datetimeEl , ( ) => {
92
+ /**
93
+ * Datetimes in overlays linked with datetime-button
94
+ * should display full width so that the overlay
95
+ * can be sized correctly.
96
+ */
97
+ if ( overlayEl ) {
98
+ datetimeEl . size = 'cover' ;
99
+ }
84
100
const datetimePresentation = ( this . datetimePresentation = datetimeEl . presentation || 'date-time' ) ;
85
101
86
102
/**
@@ -201,6 +217,8 @@ export class DatetimeButton implements ComponentInterface {
201
217
* the datetime is opened.
202
218
*/
203
219
this . selectedButton = 'date' ;
220
+
221
+ this . setOverlaySize ( ) ;
204
222
} ;
205
223
206
224
private handleTimeClick = ( ) => {
@@ -234,8 +252,83 @@ export class DatetimeButton implements ComponentInterface {
234
252
* the datetime is opened.
235
253
*/
236
254
this . selectedButton = 'time' ;
255
+
256
+ this . setOverlaySize ( ) ;
237
257
} ;
238
258
259
+ /**
260
+ * If the datetime is presented in an
261
+ * overlay, the datetime and overlay
262
+ * should be appropriately size.
263
+ * These classes provide default sizing values
264
+ * that developers can customize.
265
+ * The goal is to provide an overlay that
266
+ * reasonably sized with a datetime that
267
+ * fills the entire container.
268
+ */
269
+ private setOverlaySize = ( ) => {
270
+ const { overlayEl, datetimeEl } = this ;
271
+
272
+ if ( ! overlayEl || ! datetimeEl ) {
273
+ return ;
274
+ }
275
+
276
+ const { presentation } = datetimeEl ;
277
+
278
+ /**
279
+ * All datetime overlays should have
280
+ * a consistent width and border radius.
281
+ * This is controlled by the ion-datetime-button-overlay
282
+ * class which developers can customize globally.
283
+ */
284
+ overlayEl . classList . add ( 'ion-datetime-button-overlay' ) ;
285
+
286
+ /**
287
+ * Wheel picker styles in datetime always
288
+ * have a fixed height of 200px. This is
289
+ * because the buttons/headers are not shown
290
+ * with the wheel picker by design.
291
+ */
292
+ const hasWheelPicker = [ 'month' , 'year' , 'month-year' , 'time' ] . includes ( presentation ) ;
293
+ const needsWiderWheel = presentation === 'month-year' ;
294
+
295
+ if ( hasWheelPicker ) {
296
+ overlayEl . style . setProperty ( '--height' , `200px` ) ;
297
+
298
+ /**
299
+ * The default width for month-year
300
+ * is too small, so we set it to 300px so
301
+ * the text is not cut off.
302
+ */
303
+ if ( needsWiderWheel ) {
304
+ overlayEl . style . setProperty ( '--width' , '300px' ) ;
305
+ }
306
+
307
+ /**
308
+ * If we are not using the
309
+ * wheel picker then we need to automatically
310
+ * determine the height of the datetime by
311
+ * looking at scrollHeight. We look at scrollHeight
312
+ * as it will give us the height of the datetime
313
+ * even if it overflows outside of the overlay initially.
314
+ *
315
+ * We also wait a frame to allow the browser to
316
+ * unhide the overlay and calculate the size
317
+ * of the datetime.
318
+ *
319
+ * Doing this means developers can control the size
320
+ * of the overlay by setting the height of
321
+ * the datetime directly.
322
+ */
323
+ } else {
324
+ overlayEl . style . setProperty ( '--width' , '300px' ) ;
325
+
326
+ raf ( ( ) => {
327
+ overlayEl . style . setProperty ( '--height' , `${ datetimeEl . scrollHeight } px` ) ;
328
+ } ) ;
329
+ }
330
+ }
331
+
239
332
render ( ) {
240
333
const { color, dateText, timeText, datetimePresentation, selectedButton, datetimeActive } = this ;
241
334
0 commit comments