Skip to content
This repository was archived by the owner on May 20, 2023. It is now read-only.

Commit ac13e44

Browse files
cpellingnshahan
authored andcommitted
Move to using PopupSizeProvider instead of CSS inside the popup to control the height of the date range picker.
Keeping the existing maximum height of 600px for now, for backwards compatibility. Also implements a WithinViewportPopupSizeProvider and accompanying directive, for use in non-scrolling areas, as I need this for my use case. PiperOrigin-RevId: 220886736
1 parent da83b47 commit ac13e44

File tree

8 files changed

+75
-18
lines changed

8 files changed

+75
-18
lines changed

angular_components/lib/material_datepicker/_constants.scss

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ $week-rows-in-month: 6; // DUPLICATED: material_calendar_picker.dart
2828
$icon-size: $mat-grid * 3;
2929
$icon-button-size: $icon-size;
3030

31-
// Max-height of the entire preset list
32-
$preset-list-max-height: $mat-grid * 67;
33-
3431
/// Regular calendar sizes.
3532
$cal-date-size: 48px; // DUPLICATED: material_calendar_picker.dart
3633
$cal-title-padding: $mat-grid-type * 3;

angular_components/lib/material_datepicker/date_range_editor.scss

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@
2828
overflow-x: hidden;
2929
overflow-y: auto;
3030

31-
// Stops the date-range-editor from increasing its height to match a
32-
// lengthy preset list.
33-
max-height: $preset-list-max-height;
34-
3531
.group {
3632
padding: $date-range-picker-vertical-padding 0;
3733
border-bottom: 1px solid $mat-gray-300;

angular_components/lib/material_datepicker/material_date_range_picker.dart

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ import 'package:angular_components/utils/disposer/disposer.dart';
3737
/// Custom date range formatter interface.
3838
typedef RangeFormatter = String Function(DateRange range);
3939

40+
/// Default height of the date range picker, if no [PopupSizeProvider] is
41+
/// provided.
42+
const _defaultMaxHeight = 600;
43+
4044
/// A material-design-styled date range picker.
4145
///
4246
/// Users can choose preset date ranges, type in custom date ranges, or select
@@ -53,6 +57,10 @@ typedef RangeFormatter = String Function(DateRange range);
5357
/// (The [DatepickerModel] class is also provided to make using it easier in
5458
/// dependency injection.)
5559
///
60+
/// To control the size of the popup, provide a [PopupSizeProvider] through
61+
/// dependency injection. If no PopupSizeProvider is provided, the maximum
62+
/// height of the popup is 600px.
63+
///
5664
/// __Attributes:__
5765
///
5866
/// - `popupClass` -- Class to be added to the range picker popup so that the
@@ -76,9 +84,9 @@ typedef RangeFormatter = String Function(DateRange range);
7684
FocusTrapComponent,
7785
],
7886
providers: [
79-
Provider(DateRangeEditorHost,
80-
useExisting: MaterialDateRangePickerComponent),
81-
Provider(HasDisabled, useExisting: MaterialDateRangePickerComponent),
87+
ExistingProvider(DateRangeEditorHost, MaterialDateRangePickerComponent),
88+
ExistingProvider(HasDisabled, MaterialDateRangePickerComponent),
89+
ExistingProvider(PopupSizeProvider, MaterialDateRangePickerComponent),
8290
],
8391
)
8492
class MaterialDateRangePickerComponent extends KeyboardHandlerMixin
@@ -87,9 +95,11 @@ class MaterialDateRangePickerComponent extends KeyboardHandlerMixin
8795
OnInit,
8896
AfterChanges,
8997
OnDestroy,
90-
DateRangeEditorHost {
98+
DateRangeEditorHost,
99+
PopupSizeProvider {
91100
DateRangeEditorComponent _dateRangeEditor;
92101
bool _focusOnDateRangeEditorInit = false;
102+
PopupSizeProvider _popupSizeProvider;
93103

94104
List<RelativePosition> get overlapAlignments =>
95105
RelativePosition.overlapAlignments;
@@ -377,6 +387,7 @@ class MaterialDateRangePickerComponent extends KeyboardHandlerMixin
377387
Clock legacyClock,
378388
@Optional() DatepickerConfig config,
379389
@Attribute('popupClass') String popupClass,
390+
@Optional() @SkipSelf() this._popupSizeProvider,
380391
HtmlElement element,
381392
this._domService,
382393
this._ngZone)
@@ -508,6 +519,23 @@ class MaterialDateRangePickerComponent extends KeyboardHandlerMixin
508519
});
509520
}
510521

522+
@override
523+
num getMaxHeight(num positionY, num viewportHeight) =>
524+
_popupSizeProvider?.getMaxHeight(positionY, viewportHeight) ??
525+
_defaultMaxHeight;
526+
527+
// Width and min-height are unconstrained by default (return null), but
528+
// do delegate to the popupSizeProvider if one is provided.
529+
@override
530+
num getMaxWidth(num positionX, num viewportWidth) =>
531+
_popupSizeProvider?.getMaxWidth(positionX, viewportWidth);
532+
@override
533+
num getMinHeight(num positionY, num viewportHeight) =>
534+
_popupSizeProvider?.getMinHeight(positionY, viewportHeight);
535+
@override
536+
num getMinWidth(num positionX, num viewportWidth) =>
537+
_popupSizeProvider?.getMinWidth(positionX, viewportWidth);
538+
511539
@override
512540
void handleEscapeKey(KeyboardEvent event) {
513541
close();

angular_components/lib/src/laminate/popup/popup_size_provider.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,30 @@ class PercentagePopupSizeProvider implements PopupSizeProvider {
6464
viewportHeight * _maxHeightPercentage;
6565
}
6666

67+
/// Constrains popups to fit within the viewport's bottom and right edges.
68+
///
69+
/// This assumes that the position of the popup source does not change, and is
70+
/// intended for use in cases where the popup source is not within a scrollable
71+
/// area. Since it controls only the size and not the position, it works best
72+
/// for popups that open to the bottom and right of the anchor.
73+
class WithinViewportPopupSizeProvider implements PopupSizeProvider {
74+
static const _paddingPixels = 8;
75+
76+
@override
77+
num getMaxHeight(num positionY, num viewportHeight) =>
78+
viewportHeight - positionY - _paddingPixels;
79+
80+
@override
81+
num getMaxWidth(num positionX, num viewportWidth) =>
82+
viewportWidth - positionX - _paddingPixels;
83+
84+
@override
85+
num getMinHeight(num positionY, num viewportHeight) => null;
86+
87+
@override
88+
num getMinWidth(num positionX, num viewportWidth) => null;
89+
}
90+
6791
/// Provides a popup size with a fixed maximum width and height in pixels.
6892
///
6993
/// A null value for max width or max height indicates no limit.

angular_components/lib/src/laminate/popup/popup_size_provider_directive.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,10 @@ class _PercentSizeDefinition implements _SizeDefinition {
109109
@override
110110
num getPixels(num viewportSize) => viewportSize * _percent / 100;
111111
}
112+
113+
/// Applies a [WithinViewportPopupSizeProvider] to the attached element and
114+
/// its descendants.
115+
@Directive(selector: '[popupWithinViewport]', providers: [
116+
ClassProvider(PopupSizeProvider, useClass: WithinViewportPopupSizeProvider)
117+
])
118+
class PopupWithinViewportDirective {}

examples/material_datepicker_example/lib/material_date_range_picker_demo.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'package:angular/angular.dart';
66
import 'package:quiver/time.dart';
7+
import 'package:angular_components/laminate/popup/popup.dart';
78
import 'package:angular_components/material_checkbox/material_checkbox.dart';
89
import 'package:angular_components/material_datepicker/comparison.dart';
910
import 'package:angular_components/material_datepicker/date_range_input.dart';
@@ -45,7 +46,8 @@ List<DatepickerPreset> manyPresets(Clock clock) => [
4546
MaterialCheckboxComponent,
4647
MaterialDateRangePickerComponent,
4748
NgIf,
48-
DateRangeInputComponent
49+
DateRangeInputComponent,
50+
PopupSizeProviderDirective,
4951
],
5052
styleUrls: ['material_date_range_picker_demo.scss.css'],
5153
templateUrl: 'material_date_range_picker_demo.html',

examples/material_datepicker_example/lib/material_date_range_picker_demo.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ <h4>Options</h4>
1818
Maintain range length when moving start date
1919
</material-checkbox>
2020
<div class="limit-label">Limit to date range:</div>
21-
<date-range-input [(range)]="limitToRange"></date-range-input>
21+
<date-range-input class="range-limit" [(range)]="limitToRange"></date-range-input>
2222
<div class="selection-label">The current selection is: {{range}}</div>
23+
<div class="height-info">This picker's popup is restricted to 50% of the screen height.</div>
2324
</div>
2425
<div>
2526
<material-date-range-picker
@@ -29,6 +30,8 @@ <h4>Options</h4>
2930
[supportsComparison]="supportsComparison"
3031
[showNextPrevButtons]="showNextPrevButtons"
3132
[movingStartMaintainsLength]="movingStartMaintainsLength"
33+
popupMaxWidth="1000px"
34+
popupMaxHeight="50%"
3235
[(range)]="range">
3336
<div *ngIf="showMessageBar" messageBar class="message-bar">
3437
Custom message

examples/material_datepicker_example/lib/material_date_range_picker_demo.scss

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ h4 {
2626
margin: $mat-grid $mat-grid 0;
2727
}
2828

29-
date-range-input {
30-
display: inline-flex;
31-
width: 100%;
29+
.range-limit {
30+
margin: 0 $mat-grid;
3231
}
3332

34-
.selection-label {
35-
margin: 0 $mat-grid;
33+
.selection-label,
34+
.height-info {
35+
margin: $mat-grid;
3636
}
3737

3838
.simplified-example {

0 commit comments

Comments
 (0)