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

Components update #96

Merged
merged 2 commits into from
May 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## 0.5.2

* Material Progress: Cleanup animations on destroy to prevent memory leaks.
* Material Select:
* Support deselect item in Material dropdown select with single selection
model.
* Unified template files (deleted material_select_dropdown_item.html).
* Add support for `Selectable` `SelectionOptions`.
* Create a `ControlValueAccessor`.
* Add backspace and delete keys to `KeyboardHandlerMixin`.
* Add `selectedValue` getter to `RadioGroupSingleSelectionModel`.
* Add null check to `ObservableComposite`'s `register` method.
* Add `totalEntitiesCountChange` getter to table selection models.
* Add `isStandardMouseEvent` utility to test for clicks without modifier keys.
* Add string selection sanitizing options.
* Remove `NoopStream` in favor of `Stream.empty()` as provided by the SDK.
* Migrate use of LazyEventController to StreamController.
* Fix bug in lazy group creation that would cause multiple groups to be
created.
* Strong mode fixes.

## 0.5.1

* Glyph: Add baseline attribute.
Expand Down
1 change: 1 addition & 0 deletions lib/src/all_components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export 'components/material_chips/material_chip.dart';
export 'components/material_chips/material_chips.dart';
export 'components/material_dialog/material_dialog.dart';
export 'components/material_expansionpanel/material_expansionpanel.dart';
export 'components/material_expansionpanel/material_expansionpanel_auto_dismiss.dart';
export 'components/material_expansionpanel/material_expansionpanel_set.dart';
export 'components/material_input/base_material_input.dart';
export 'components/material_input/deferred_validator.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/src/components/material_button/material_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:angular2/angular2.dart';

import '../button_decorator/button_decorator.dart';
import '../material_ripple/material_ripple.dart';
import '../theme/dark_theme.dart';

import 'material_button_base.dart';

/// Material button is a button.
Expand Down
2 changes: 1 addition & 1 deletion lib/src/components/material_button/material_fab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:angular2/angular2.dart';

import '../material_ripple/material_ripple.dart';

import 'material_button_base.dart';

/// Material FAB is a Floating Action Button. It is round, and behaves mostly
Expand Down
2 changes: 1 addition & 1 deletion lib/src/components/material_chips/material_chip.scss.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'package:intl/intl.dart';
import '../../model/action/async_action.dart';
import '../../utils/angular/managed_zone/angular_2.dart';
import '../../utils/angular/properties/properties.dart';
import '../../utils/async/async.dart';
import '../../utils/browser/dom_service/dom_service.dart';
import '../../utils/disposer/disposer.dart';
import '../button_decorator/button_decorator.dart';
Expand Down Expand Up @@ -159,13 +158,17 @@ class MaterialExpansionPanel
}

@Output('expandedChange')
final isExpandedChange = new LazyEventEmitter<bool>.broadcast();
Stream<bool> get isExpandedChange => _isExpandedChange.stream;
final _isExpandedChange = new StreamController<bool>.broadcast(sync: true);

@Output('expandedChangeByUser')
final isExpandedChangeByUserAction = new LazyEventEmitter<bool>.broadcast();
Stream<bool> get isExpandedChangeByUserAction =>
_isExpandedChangeByUserAction.stream;
final _isExpandedChangeByUserAction =
new StreamController<bool>.broadcast(sync: true);

@override
LazyEventEmitter<bool> get contentVisible => isExpandedChange;
Stream<bool> get contentVisible => isExpandedChange;

/// Whether a different panel in the set is currently expanded.
///
Expand Down Expand Up @@ -379,8 +382,8 @@ class MaterialExpansionPanel
actionCtrl.execute(() {
if (closeOnSave) {
_isExpanded = false;
isExpandedChange.add(false);
isExpandedChangeByUserAction.add(false);
_isExpandedChange.add(false);
_isExpandedChangeByUserAction.add(false);
_changeDetector.markForCheck();
}
return true;
Expand All @@ -399,8 +402,8 @@ class MaterialExpansionPanel
_changeDetector.markForCheck();
actionCtrl.execute(() {
_isExpanded = false;
isExpandedChange.add(false);
isExpandedChangeByUserAction.add(false);
_isExpandedChange.add(false);
_isExpandedChangeByUserAction.add(false);
_changeDetector.markForCheck();
return true;
}, valueOnCancel: false);
Expand All @@ -424,8 +427,8 @@ class MaterialExpansionPanel
stream.add(actionCtrl.action);
actionCtrl.execute(() {
_isExpanded = expand;
isExpandedChange.add(expand);
if (byUserAction) isExpandedChangeByUserAction.add(expand);
_isExpandedChange.add(expand);
if (byUserAction) _isExpandedChangeByUserAction.add(expand);
_changeDetector.markForCheck();
if (expand && autoFocusChild != null) {
_domService.scheduleWrite(() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import 'dart:html';

import 'package:angular2/angular2.dart';

import '../../../laminate/overlay/module.dart' show overlayContainerToken;
import '../material_expansionpanel.dart';
import '../../laminate/overlay/module.dart' show overlayContainerToken;
import './material_expansionpanel.dart';

/// A directive that automatically collapses [MaterialExpansionPanel].
///
Expand Down
12 changes: 11 additions & 1 deletion lib/src/components/material_progress/material_progress.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Map<String, double> _indeterminateTiming = const {
templateUrl: 'material_progress.html',
styleUrls: const ['material_progress.scss.css'],
changeDetection: ChangeDetectionStrategy.OnPush)
class MaterialProgressComponent implements AfterViewInit {
class MaterialProgressComponent implements AfterViewInit, OnDestroy {
final HtmlElement _element;

/// The current progress value.
Expand Down Expand Up @@ -106,6 +106,16 @@ class MaterialProgressComponent implements AfterViewInit {
if (indeterminate) _tryFancyAnimation();
}

@override
void ngOnDestroy() {
_primaryAnimation?.cancel();
_secondaryAnimation?.cancel();
_primaryAnimation = null;
_secondaryAnimation = null;
_primaryIndicator = null;
_secondaryIndicator = null;
}

/// Sets up the "indeterminate" animation using the animation API.
void _tryFancyAnimation() {
// Only set this up if we support the animation API and if the component's
Expand Down
47 changes: 39 additions & 8 deletions lib/src/components/material_select/material_dropdown_select.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import '../../model/selection/selection_model.dart';
import '../../model/selection/selection_options.dart';
import '../../model/ui/has_renderer.dart';
import '../../model/ui/template_support.dart';
import '../../utils/async/async.dart';
import '../../utils/id_generator/id_generator.dart';
import '../annotations/rtl_annotation.dart';
import '../content/deferred_content.dart';
Expand Down Expand Up @@ -90,6 +89,8 @@ import './shift_click_selection.dart';
/// as wide as the select width.
/// - `slide: String` -- Direction of popup scaling. Valid values are `x`, `y`,
/// or `null`.
/// - `deselectLabel: String` -- Text label for select item that deselects
/// the current selection.
@Component(
selector: 'material-dropdown-select',
inputs: const [
Expand Down Expand Up @@ -168,6 +169,10 @@ class MaterialDropdownSelectComponent extends MaterialSelectBase
/// instead of the implementation of this class.
final PopupSizeProvider _popupSizeDelegate;

/// Text label for select item that deselects the current selection.
@Input()
String deselectLabel;

MaterialDropdownSelectComponent(
@Optional() IdGenerator idGenerator,
@Optional() @SkipSelf() this._popupSizeDelegate,
Expand All @@ -188,28 +193,32 @@ class MaterialDropdownSelectComponent extends MaterialSelectBase
set options(SelectionOptions newOptions) {
super.options = newOptions;

activeModel.items = options?.optionsList ?? [];
_updateActiveModel();
_setInitialActiveItem();

_optionsListener?.cancel();
_optionsListener = options?.stream?.listen((_) {
activeModel.items = options.optionsList;
_updateActiveModel();
_setInitialActiveItem();
});
}

@Output()
LazyEventEmitter<FocusEvent> focus = new LazyEventEmitter<FocusEvent>();
Stream<FocusEvent> get focus => _focus.stream;
StreamController<FocusEvent> _focus =
new StreamController<FocusEvent>.broadcast(sync: true);

@Output()
LazyEventEmitter<FocusEvent> blur = new LazyEventEmitter<FocusEvent>();
Stream<FocusEvent> get blur => _blur.stream;
StreamController<FocusEvent> _blur =
new StreamController<FocusEvent>.broadcast(sync: true);

void onFocus(FocusEvent event) {
focus.add(event);
_focus.add(event);
}

void onBlur(FocusEvent event) {
blur.add(event);
_blur.add(event);
}

@override
Expand All @@ -228,6 +237,14 @@ class MaterialDropdownSelectComponent extends MaterialSelectBase
});
}

void _updateActiveModel() {
var items = options?.optionsList?.toList() ?? [];
if (showDeselectItem) {
items.insert(0, deselectLabel);
}
activeModel.items = items;
}

void _setInitialActiveItem() {
if (selection == null || selection.selectedValues.isEmpty) {
activeModel.activate(null);
Expand Down Expand Up @@ -289,7 +306,9 @@ class MaterialDropdownSelectComponent extends MaterialSelectBase
} else {
var item = activeModel.activeItem;
if (item != null && selection != null) {
if (selection.isSelected(item)) {
if (item == deselectLabel) {
deselectCurrentSelection();
} else if (selection.isSelected(item)) {
selection.deselect(item);
} else {
selection.select(item);
Expand Down Expand Up @@ -372,6 +391,18 @@ class MaterialDropdownSelectComponent extends MaterialSelectBase
}
return false;
}

/// Whether to show select item that deselects the current selection.
bool get showDeselectItem =>
!isMultiSelect && deselectLabel?.isNotEmpty == true;

bool get isDeselectItemSelected => selection.isEmpty;

void deselectCurrentSelection() {
if (selection.isNotEmpty) {
selection.deselect(selection.selectedValues.single);
}
}
}

// TODO(google): Move it to a common home to increase reusability.
Expand Down
52 changes: 32 additions & 20 deletions lib/src/components/material_select/material_dropdown_select.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@
(trigger)="handleClick($event)"
popupSource
#source="popupSource">
<ng-content select="[buttonContent]"></ng-content>
<ng-content select="[buttonContent]"></ng-content>
</dropdown-button>
<material-popup enforceSpaceConstraints
[preferredPositions]="preferredPositions"
[matchMinSourceWidth]="popupMatchInputWidth"
[slide]="slide"
[source]="source"
[autoDismiss]="autoDismiss"
[trackLayoutChanges]="trackLayoutChanges"
[visible]="visible"
(visibleChange)="onVisible($event)">
[preferredPositions]="preferredPositions"
[matchMinSourceWidth]="popupMatchInputWidth"
[slide]="slide"
[source]="source"
[autoDismiss]="autoDismiss"
[trackLayoutChanges]="trackLayoutChanges"
[visible]="visible"
(visibleChange)="onVisible($event)">
<div header
(keydown)="onKeyDown($event)"
(keypress)="onKeyPress($event)"
Expand All @@ -46,21 +46,33 @@
(mouseout)="activeModel.activate(null)">
<ng-content></ng-content>
<div class="options-wrapper" *ngIf="options != null">
<div *ngFor="let group of options.optionGroups trackBy trackByIndexFn" group
[class.empty]="group.isEmpty && !group.hasEmptyLabel">
<material-select-dropdown-item
*ngIf="showDeselectItem"
[class.empty]="options.optionGroups.length == 1"
keyboardOnlyFocusIndicator
[selected]="isDeselectItemSelected"
[value]="deselectLabel"
(trigger)="deselectCurrentSelection()"
[active]="activeModel.isActive(deselectLabel)"
[attr.id]="activeModel.id(deselectLabel)"
(mouseenter)="activeModel.activate(deselectLabel)">
</material-select-dropdown-item>
<div *ngFor="let group of options.optionGroups trackBy trackByIndexFn"
group
[class.empty]="group.isEmpty && !group.hasEmptyLabel">
<template [ngIf]="group.isNotEmpty || group.hasEmptyLabel">
<span *ngIf="group.hasLabel" label>{{group.uiDisplayName}}</span>
<template [ngIf]="group.isNotEmpty">
<material-select-dropdown-item *ngFor="let item of group"
keyboardOnlyFocusIndicator
[itemRenderer]="itemRenderer"
[componentRenderer]="componentRenderer"
[selection]="selection"
[disabled]="isOptionDisabled(item)"
[value]="item"
[active]="activeModel.isActive(item)"
[attr.id]="activeModel.id(item)"
(mouseenter)="activeModel.activate(item)">
keyboardOnlyFocusIndicator
[itemRenderer]="itemRenderer"
[componentRenderer]="componentRenderer"
[selection]="selection"
[disabled]="isOptionDisabled(item)"
[value]="item"
[active]="activeModel.isActive(item)"
[attr.id]="activeModel.id(item)"
(mouseenter)="activeModel.activate(item)">
</material-select-dropdown-item>
</template>
<material-select-dropdown-item
Expand Down
11 changes: 11 additions & 0 deletions lib/src/components/material_select/material_select.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'dart:async';

import 'package:angular2/angular2.dart';

import '../../model/selection/select.dart';
import '../../model/selection/selection_container.dart';
import '../../model/selection/selection_model.dart';
import '../../model/ui/has_renderer.dart';
Expand Down Expand Up @@ -68,6 +69,16 @@ class MaterialSelectComponent extends MaterialSelectBase implements OnDestroy {
@override
SelectionModel get selection => super.selection;

/// If selectionOptions implements Selectable, it is called to decided
/// whether an item is disabled.
bool isOptionDisabled(Object item) {
if (options is Selectable) {
return (options as Selectable).getSelectable(item) !=
SelectableOption.Selectable;
}
return false;
}

@Input()
set disabled(value) {
_disabled = getBool(value);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/components/material_select/material_select.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<span *ngIf="group.hasLabel" label>{{group.uiDisplayName}}</span>
<material-select-item *ngFor="let item of group"
[itemRenderer]="itemRenderer"
[disabled]="disabled"
[disabled]="disabled || isOptionDisabled(item)"
[componentRenderer]="componentRenderer"
[selection]="selection"
[value]="item">
Expand Down
Loading