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

Commit adbdfb2

Browse files
committed
Add material_dialog component
Update all changes since last release.
1 parent 3f77cb7 commit adbdfb2

File tree

90 files changed

+6321
-591
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+6321
-591
lines changed

CHANGELOG.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
## 0.1.2
1+
## 0.2.0
22

3+
* Add a modal dialog window called material_dialog.
4+
* Rename MultilineMaterialInputComponent to MaterialMultilineInputComponent.
5+
* Make the deferredContent placeholder element optional, off by default.
6+
* Remove InputTextModel.
7+
* Cleanup linter warnings.
8+
* Refactor color support.
39
* Many components now support removing whitespace in the templates.
410
* Refactor tab key index to a mixin.
5-
* Various UI tweaks and cleanup.
11+
* Various updates and cleanup.
612

713
## 0.1.1
814

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ applications.
55

66
Only a small fragment of all the components is available right now. We want
77
developers to have an opportunity to play around with the package as soon as
8-
possible.
8+
possible.
99

1010
*`<glyph>`
1111
*`<material-button>`
@@ -22,13 +22,15 @@ possible.
2222
*`<material-yes-no-buttons>`
2323
*`<reorder-list>`
2424
*`<acx-scorecard>`
25-
*`<material-input>`
25+
*`<material-input>`
26+
*`<material-dialog>`
27+
*`<material-popup>`
28+
*`<material-tooltip>`
2629
*`<material-auto-suggest-input>`
2730
*`<material-date-range-picker>`
28-
*`<material-dialog>`
2931
*`<material-list>`
3032
*`<material-menu>`
31-
* many more, including a fast table
33+
* many more, including a fast table
3234

3335

3436
## Useful links

lib/angular2_components.dart

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@ export 'src/all_components.dart';
1010

1111
/// A convenience list of all Directives exposed by this package.
1212
const List<Type> materialDirectives = const [
13+
AutoDismissDirective,
14+
AutoFocusDirective,
1315
CachingDeferredContentDirective,
1416
DeferredContentDirective,
1517
FixedMaterialTabStripComponent,
1618
FocusActivableItemDirective,
1719
FocusItemDirective,
1820
FocusListDirective,
1921
FocusableDirective,
22+
FocusTrapComponent,
2023
GlyphComponent,
21-
InputTextModel,
2224
MaterialButtonComponent,
2325
MaterialCheckboxComponent,
2426
MaterialChipComponent,
2527
MaterialChipsComponent,
28+
MaterialDialogComponent,
2629
MaterialExpansionPanel,
2730
MaterialExpansionPanelSet,
2831
MaterialFabComponent,
@@ -37,13 +40,16 @@ const List<Type> materialDirectives = const [
3740
MaterialTabPanelComponent,
3841
MaterialToggleComponent,
3942
MaterialYesNoButtonsComponent,
40-
MultilineMaterialInputComponent,
43+
MaterialMultilineInputComponent,
44+
ModalComponent,
45+
NgModel,
4146
ReorderItemDirective,
4247
ReorderListComponent,
43-
ScorecardComponent
48+
ScorecardComponent,
4449
];
4550

4651
/// A convenience list of all providers exposed by this package.
4752
const List<List<Provider>> materialProviders = const <List<Provider>>[
48-
rippleBindings
53+
rippleBindings,
54+
overlayBindings,
4955
];

lib/src/all_components.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
library angular2_components.all_components;
66

77
export 'components/annotations/rtl_annotation.dart';
8+
export 'components/auto_dismiss/auto_dismiss.dart';
89
export 'components/button_decorator/button_decorator.dart';
910
export 'components/content/deferred_content.dart';
1011
export 'components/content/deferred_content_aware.dart';
1112
export 'components/focus/focus.dart';
1213
export 'components/focus/focus_activable_item.dart';
1314
export 'components/focus/focus_item.dart';
1415
export 'components/focus/focus_list.dart';
16+
export 'components/focus/focus_trap.dart';
1517
export 'components/focus/keyboard_only_focus_indicator.dart';
1618
export 'components/glyph/glyph.dart';
1719
export 'components/material_button/material_button.dart';
@@ -21,6 +23,7 @@ export 'components/material_checkbox/material_checkbox.dart'
2123
show MaterialCheckboxComponent;
2224
export 'components/material_chips/material_chip.dart';
2325
export 'components/material_chips/material_chips.dart';
26+
export 'components/material_dialog/material_dialog.dart';
2427
export 'components/material_expansionpanel/material_expansionpanel.dart';
2528
export 'components/material_expansionpanel/material_expansionpanel_set.dart';
2629
export 'components/material_input/base_material_input.dart';
@@ -35,14 +38,10 @@ export 'components/material_radio/material_radio.dart';
3538
export 'components/material_radio/material_radio_group.dart';
3639
export 'components/material_ripple/material_ripple.dart';
3740
export 'components/material_ripple/module.dart';
38-
export 'components/material_ripple/src/wave.dart';
3941
export 'components/material_spinner/material_spinner.dart';
4042
export 'components/material_tab/fixed_material_tab_strip.dart';
4143
export 'components/material_tab/material_tab.dart';
4244
export 'components/material_tab/material_tab_panel.dart';
43-
export 'components/material_tab/src/navigation_bar.dart';
44-
export 'components/material_tab/src/tab_button.dart';
45-
export 'components/material_tab/src/tab_mixin.dart';
4645
export 'components/material_tab/tab_change_event.dart';
4746
export 'components/material_toggle/material_toggle.dart';
4847
export 'components/material_yes_no_buttons/material_yes_no_buttons.dart';
@@ -51,6 +50,7 @@ export 'components/mixins/has_tab_index.dart';
5150
export 'components/reorder_list/reorder_list.dart';
5251
export 'components/scorecard/scoreboard.dart';
5352
export 'components/scorecard/scorecard.dart';
54-
export 'components/scorecard/src/scorecard_bar.dart';
5553
export 'components/theme/dark_theme.dart';
5654
export 'components/theme/module.dart';
55+
export 'laminate/components/modal/modal.dart';
56+
export 'laminate/overlay/module.dart';
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
7+
import 'package:angular2/angular2.dart';
8+
9+
import '../../utils/angular/properties/properties.dart';
10+
import '../../utils/browser/events/events.dart';
11+
12+
/// A directive that publishes a (dismiss) event when the user clicks outside of
13+
/// it.
14+
///
15+
/// Note: For [MaterialExpansionPanel] please consider using the dedicated
16+
/// directive [MaterialExpansionPanelAutoDismiss].
17+
///
18+
/// __Example Usage:__
19+
///
20+
/// <div>
21+
/// <div class="disclaimer" [class.visible]="disclaimerVisible"
22+
/// [autoDismissable]="disclaimerVisible"
23+
/// (dismiss)="disclaimerVisible = false">
24+
/// Some scary disclaimery text
25+
/// <div>
26+
/// <button (click)="disclaimerVisible = true">Confirm</button>
27+
/// </div>
28+
///
29+
@Directive(selector: '[autoDismissable]:not(material-expansionpanel)')
30+
class AutoDismissDirective {
31+
final Stream _click;
32+
final NgZone _zone;
33+
34+
AutoDismissDirective(ElementRef element, this._zone)
35+
: _click = triggersOutside(element);
36+
37+
bool _ignoreClicks = false;
38+
bool _autoDismissable = false;
39+
bool get autoDismissable => _autoDismissable;
40+
41+
/// Boolean indicating if the dismiss event be published.
42+
@Input()
43+
set autoDismissable(b) {
44+
_autoDismissable = getBool(b);
45+
46+
// If a click set autoDismissable to `true`, then we don't want the same
47+
// click to dismiss right away. Stop listening for clicks until we see a
48+
// click event, or until the next event loop.
49+
_ignoreClicks = b;
50+
_click.first.then(_listenForClicks);
51+
// Run the timer outside of Angular so that it doesn't trigger a new digest
52+
// cycle.
53+
_zone.runOutsideAngular(() => Timer.run(_listenForClicks));
54+
}
55+
56+
/// Event which is published when the user clicks outside of the element.
57+
@Output()
58+
Stream get dismiss => _click.where((_) => _autoDismissable && !_ignoreClicks);
59+
60+
_listenForClicks([_]) => _ignoreClicks = false;
61+
}

lib/src/components/content/deferred_content.dart

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:html';
66

77
import 'package:angular2/angular2.dart';
88

9+
import '../../utils/angular/properties/properties.dart';
910
import '../../utils/disposer/disposer.dart';
1011

1112
import 'deferred_content_aware.dart';
@@ -31,35 +32,51 @@ class DeferredContentDirective implements OnDestroy {
3132
EmbeddedViewRef _viewRef;
3233
TemplateRef _template;
3334

35+
/// Create a placeholder element to maintain content size when hidden.
36+
///
37+
/// Used like *deferredContent="true".
38+
bool _preserveDimensions = false;
39+
@Input('deferredContent')
40+
set preserveDimensions(value) {
41+
// If it's just *deferredContent, default to false.
42+
_preserveDimensions = getBool(value ?? false);
43+
}
44+
3445
// Keep around the current state.
3546
bool _visible = false;
3647

3748
void _setVisible(bool value) {
3849
if (value == _visible) return;
3950
if (value) {
40-
// Remove the placeholder and add the deferred content.
41-
_placeholder.remove();
51+
if (_preserveDimensions) {
52+
// Remove the placeholder and add the deferred content.
53+
_placeholder.remove();
54+
}
4255
_viewRef = _viewContainer.createEmbeddedView(_template);
4356
} else {
44-
// Save the dimensions of the deferred content.
45-
var rootNodes = _viewRef?.rootNodes ?? [];
46-
var content = rootNodes.length > 0 ? rootNodes.first : null;
47-
if (content is HtmlElement) {
48-
// This isn't in DomService.schedule{Read,Write} because
49-
// it needs to work with components that aren't scheduled.
50-
var dimensions = content.getBoundingClientRect();
51-
_placeholder.style
52-
..width = '${dimensions.width}px'
53-
..height = '${dimensions.height}px';
57+
if (_preserveDimensions) {
58+
// Save the dimensions of the deferred content.
59+
var rootNodes = _viewRef?.rootNodes ?? [];
60+
var content = rootNodes.length > 0 ? rootNodes.first : null;
61+
if (content is HtmlElement) {
62+
// This isn't in DomService.schedule{Read,Write} because
63+
// it needs to work with components that aren't scheduled.
64+
var dimensions = content.getBoundingClientRect();
65+
_placeholder.style
66+
..width = '${dimensions.width}px'
67+
..height = '${dimensions.height}px';
68+
}
5469
}
5570

5671
// Remove the deferred content.
5772
_viewContainer.clear();
5873

59-
// Add the placeholder so the parent's size doesn't change.
60-
var container = _viewContainer.element?.nativeElement;
61-
if (container != null) {
62-
container.parentNode.insertBefore(_placeholder, container);
74+
if (_preserveDimensions) {
75+
// Add the placeholder so the parent's size doesn't change.
76+
var container = _viewContainer.element?.nativeElement;
77+
if (container != null) {
78+
container.parentNode.insertBefore(_placeholder, container);
79+
}
6380
}
6481
}
6582
_visible = value;

lib/src/components/focus/focus.dart

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import 'dart:html' show KeyCode, KeyboardEvent, Element;
77

88
import 'package:angular2/angular2.dart';
99

10+
import '../../laminate/components/modal/modal.dart';
11+
import '../../laminate/popup/popup.dart';
12+
import '../../utils/angular/properties/properties.dart';
13+
import '../../utils/browser/dom_service/dom_service.dart';
1014
import '../../utils/disposer/disposer.dart';
1115

1216
/// A component or directive that can be programmatically focused.
@@ -38,6 +42,7 @@ abstract class RootFocusable implements Focusable, Disposable {
3842
element.focus();
3943
}
4044

45+
@override
4146
void dispose() {
4247
_root = null;
4348
}
@@ -118,6 +123,82 @@ class FocusMoveEvent {
118123
keyCode == KeyCode.LEFT || keyCode == KeyCode.UP;
119124
}
120125

126+
/// The element will be focused as soon as directive is initialized.
127+
///
128+
/// Please put only on content that appears after user action and
129+
/// requires focus to be changed to it.
130+
@Directive(selector: '[autoFocus]')
131+
class AutoFocusDirective extends RootFocusable implements OnInit, OnDestroy {
132+
final _disposer = new Disposer.oneShot();
133+
134+
bool _autoFocus;
135+
// These fields are not final to support nulling them out for easier memory
136+
// leak detection.
137+
Focusable _focusable;
138+
DomService _domService;
139+
ModalComponent _modal;
140+
PopupRef _popupRef;
141+
142+
AutoFocusDirective(
143+
ElementRef node,
144+
this._domService,
145+
@Optional() this._focusable,
146+
@Optional() this._modal,
147+
@Optional() this._popupRef)
148+
: super(node);
149+
150+
@override
151+
void ngOnInit() {
152+
if (!_autoFocus) return;
153+
154+
if (_modal != null || _popupRef != null) {
155+
var isVisible = _popupRef != null
156+
? _popupRef.isVisible
157+
: _modal.resolvedOverlayRef.isVisible;
158+
_onModalOrPopupVisibleChanged(isVisible);
159+
160+
var onVisibleChanged = _popupRef != null
161+
? _popupRef.onVisibleChanged
162+
: _modal.resolvedOverlayRef.onVisibleChanged;
163+
_disposer.addStreamSubscription(
164+
onVisibleChanged.listen(_onModalOrPopupVisibleChanged));
165+
} else {
166+
_domService.scheduleWrite(focus);
167+
}
168+
}
169+
170+
/// Enables the auto focus directive so that it can be conditionally applied.
171+
///
172+
/// This value should not change during the component's life.
173+
@Input()
174+
set autoFocus(value) {
175+
assert(_autoFocus == null);
176+
_autoFocus = getBool(value);
177+
}
178+
179+
@override
180+
void focus() {
181+
if (_focusable != null) {
182+
_focusable.focus();
183+
} else {
184+
super.focus();
185+
}
186+
}
187+
188+
@override
189+
void ngOnDestroy() {
190+
super.dispose();
191+
_disposer.dispose();
192+
_focusable = null;
193+
_domService = null;
194+
_modal = null;
195+
_popupRef = null;
196+
}
197+
198+
void _onModalOrPopupVisibleChanged(bool isVisible) {
199+
if (isVisible) _domService.scheduleWrite(focus);
200+
}
201+
}
121202

122203
/// This directive is used to [ViewChild] focusable element in your view.
123204
@Directive(selector: '[focusableElement]', exportAs: 'focusableElement')

lib/src/components/focus/focus_activable_item.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class FocusActivableItemDirective extends RootFocusable
1717
implements FocusableActivateItem {
1818
/// Key to assign to the focusable item.
1919
@Input('focusActivableItem')
20+
@override
2021
String key;
2122

2223
FocusActivableItemDirective(ElementRef root) : super(root);

lib/src/components/focus/focus_list.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class FocusListDirective implements OnDestroy {
9494
_children[newIndex].tabbable = true;
9595
}
9696

97+
@override
9798
void ngOnDestroy() {
9899
_disposer.dispose();
99100
}

0 commit comments

Comments
 (0)