123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- import { Subject } from 'rxjs';
- /**
- * Class to be used to power selecting one or more options from a list.
- */
- class SelectionModel {
- _multiple;
- _emitChanges;
- compareWith;
- /** Currently-selected values. */
- _selection = new Set();
- /** Keeps track of the deselected options that haven't been emitted by the change event. */
- _deselectedToEmit = [];
- /** Keeps track of the selected options that haven't been emitted by the change event. */
- _selectedToEmit = [];
- /** Cache for the array value of the selected items. */
- _selected;
- /** Selected values. */
- get selected() {
- if (!this._selected) {
- this._selected = Array.from(this._selection.values());
- }
- return this._selected;
- }
- /** Event emitted when the value has changed. */
- changed = new Subject();
- constructor(_multiple = false, initiallySelectedValues, _emitChanges = true, compareWith) {
- this._multiple = _multiple;
- this._emitChanges = _emitChanges;
- this.compareWith = compareWith;
- if (initiallySelectedValues && initiallySelectedValues.length) {
- if (_multiple) {
- initiallySelectedValues.forEach(value => this._markSelected(value));
- }
- else {
- this._markSelected(initiallySelectedValues[0]);
- }
- // Clear the array in order to avoid firing the change event for preselected values.
- this._selectedToEmit.length = 0;
- }
- }
- /**
- * Selects a value or an array of values.
- * @param values The values to select
- * @return Whether the selection changed as a result of this call
- * @breaking-change 16.0.0 make return type boolean
- */
- select(...values) {
- this._verifyValueAssignment(values);
- values.forEach(value => this._markSelected(value));
- const changed = this._hasQueuedChanges();
- this._emitChangeEvent();
- return changed;
- }
- /**
- * Deselects a value or an array of values.
- * @param values The values to deselect
- * @return Whether the selection changed as a result of this call
- * @breaking-change 16.0.0 make return type boolean
- */
- deselect(...values) {
- this._verifyValueAssignment(values);
- values.forEach(value => this._unmarkSelected(value));
- const changed = this._hasQueuedChanges();
- this._emitChangeEvent();
- return changed;
- }
- /**
- * Sets the selected values
- * @param values The new selected values
- * @return Whether the selection changed as a result of this call
- * @breaking-change 16.0.0 make return type boolean
- */
- setSelection(...values) {
- this._verifyValueAssignment(values);
- const oldValues = this.selected;
- const newSelectedSet = new Set(values.map(value => this._getConcreteValue(value)));
- values.forEach(value => this._markSelected(value));
- oldValues
- .filter(value => !newSelectedSet.has(this._getConcreteValue(value, newSelectedSet)))
- .forEach(value => this._unmarkSelected(value));
- const changed = this._hasQueuedChanges();
- this._emitChangeEvent();
- return changed;
- }
- /**
- * Toggles a value between selected and deselected.
- * @param value The value to toggle
- * @return Whether the selection changed as a result of this call
- * @breaking-change 16.0.0 make return type boolean
- */
- toggle(value) {
- return this.isSelected(value) ? this.deselect(value) : this.select(value);
- }
- /**
- * Clears all of the selected values.
- * @param flushEvent Whether to flush the changes in an event.
- * If false, the changes to the selection will be flushed along with the next event.
- * @return Whether the selection changed as a result of this call
- * @breaking-change 16.0.0 make return type boolean
- */
- clear(flushEvent = true) {
- this._unmarkAll();
- const changed = this._hasQueuedChanges();
- if (flushEvent) {
- this._emitChangeEvent();
- }
- return changed;
- }
- /**
- * Determines whether a value is selected.
- */
- isSelected(value) {
- return this._selection.has(this._getConcreteValue(value));
- }
- /**
- * Determines whether the model does not have a value.
- */
- isEmpty() {
- return this._selection.size === 0;
- }
- /**
- * Determines whether the model has a value.
- */
- hasValue() {
- return !this.isEmpty();
- }
- /**
- * Sorts the selected values based on a predicate function.
- */
- sort(predicate) {
- if (this._multiple && this.selected) {
- this._selected.sort(predicate);
- }
- }
- /**
- * Gets whether multiple values can be selected.
- */
- isMultipleSelection() {
- return this._multiple;
- }
- /** Emits a change event and clears the records of selected and deselected values. */
- _emitChangeEvent() {
- // Clear the selected values so they can be re-cached.
- this._selected = null;
- if (this._selectedToEmit.length || this._deselectedToEmit.length) {
- this.changed.next({
- source: this,
- added: this._selectedToEmit,
- removed: this._deselectedToEmit,
- });
- this._deselectedToEmit = [];
- this._selectedToEmit = [];
- }
- }
- /** Selects a value. */
- _markSelected(value) {
- value = this._getConcreteValue(value);
- if (!this.isSelected(value)) {
- if (!this._multiple) {
- this._unmarkAll();
- }
- if (!this.isSelected(value)) {
- this._selection.add(value);
- }
- if (this._emitChanges) {
- this._selectedToEmit.push(value);
- }
- }
- }
- /** Deselects a value. */
- _unmarkSelected(value) {
- value = this._getConcreteValue(value);
- if (this.isSelected(value)) {
- this._selection.delete(value);
- if (this._emitChanges) {
- this._deselectedToEmit.push(value);
- }
- }
- }
- /** Clears out the selected values. */
- _unmarkAll() {
- if (!this.isEmpty()) {
- this._selection.forEach(value => this._unmarkSelected(value));
- }
- }
- /**
- * Verifies the value assignment and throws an error if the specified value array is
- * including multiple values while the selection model is not supporting multiple values.
- */
- _verifyValueAssignment(values) {
- if (values.length > 1 && !this._multiple && (typeof ngDevMode === 'undefined' || ngDevMode)) {
- throw getMultipleValuesInSingleSelectionError();
- }
- }
- /** Whether there are queued up change to be emitted. */
- _hasQueuedChanges() {
- return !!(this._deselectedToEmit.length || this._selectedToEmit.length);
- }
- /** Returns a value that is comparable to inputValue by applying compareWith function, returns the same inputValue otherwise. */
- _getConcreteValue(inputValue, selection) {
- if (!this.compareWith) {
- return inputValue;
- }
- else {
- selection = selection ?? this._selection;
- for (let selectedValue of selection) {
- if (this.compareWith(inputValue, selectedValue)) {
- return selectedValue;
- }
- }
- return inputValue;
- }
- }
- }
- /**
- * Returns an error that reports that multiple values are passed into a selection model
- * with a single value.
- * @docs-private
- */
- function getMultipleValuesInSingleSelectionError() {
- return Error('Cannot pass multiple values into SelectionModel with single-value mode.');
- }
- export { SelectionModel as S, getMultipleValuesInSingleSelectionError as g };
- //# sourceMappingURL=selection-model-CeeHVIcP.mjs.map
|