@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
307 lines • 73.9 kB
JavaScript
import { LiveAnnouncer } from '@angular/cdk/a11y';
import { ArrayDataSource } from '@angular/cdk/collections';
import { FlatTreeControl } from '@angular/cdk/tree';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, inject, Input, Output, ViewChildren } from '@angular/core';
import { ColumnPickerService } from './column-picker.service';
import { isColumnPickerGroupItem } from './interfaces/column-picker-group-item.interface';
import * as i0 from "@angular/core";
import * as i1 from "../../../directives/accessibility/focus-indicator/default-focus-indicator.directive";
import * as i2 from "../../../directives/accessibility/focus-indicator/focus-indicator.directive";
import * as i3 from "../../../directives/accessibility/tabbable-list/tabbable-list.directive";
import * as i4 from "../../../directives/accessibility/tabbable-list/tabbable-list-item.directive";
import * as i5 from "@angular/cdk/tree";
import * as i6 from "@angular/common";
import * as i7 from "../../icon/icon.component";
import * as i8 from "../../../directives/reorderable/reorderable.directive";
import * as i9 from "../../../directives/reorderable/reorderable-handle.directive";
import * as i10 from "../../../directives/reorderable/reorderable-model.directive";
import * as i11 from "../../../directives/selection/selection.directive";
import * as i12 from "../../../directives/selection/selection-item.directive";
let uniqueId = 0;
export class ColumnPickerComponent {
constructor() {
this._columnPicker = inject(ColumnPickerService);
/** Access the LiveAnnounce to provide accessibility on reordering */
this._liveAnnouncer = inject(LiveAnnouncer);
/** We are using OnPush change detection so we must manually trigger CD */
this._changeDetectorRef = inject(ChangeDetectorRef);
/** Sets the id of the column picker. */
this.id = `ux-number-picker-${uniqueId++}`;
/** Define a list of all selected columns. */
this.selected = [];
/** Define a list of columns that are always selected. The columns cannot be moved or reordered. */
this.locked = [];
/** Define a list of columns that are not selected or locked. All columns must have unique names, including columns in different groups. */
this.deselected = [];
/** Define a function to get the aria label of reorderable items in the selected column. */
this.selectedAriaLabel = this.getDefaultSelectedAriaLabel;
/** Define a function to get the aria label of a group in the deselected list. */
this.deselectedGroupAriaLabel = this.getDefaultDeselectedGroupAriaLabel;
/** Define a function that returns a column move announcement. */
this.columnMovedAnnouncement = this.getColumnMovedAnnouncement;
/** Define the aria label for the add column button */
this.addColumnAriaLabel = 'Add selected item';
/** Define the aria label for the remove column button */
this.removeColumnAriaLabel = 'Remove selected item';
/** Define the aria label for the add all column button */
this.addAllColumnsAriaLabel = 'Add all items';
/** Define the aria label for the remove all column button */
this.removeAllColumnsAriaLabel = 'Remove all items';
/** Emits when the selected items change or the order of the selected items change. */
this.selectedChange = new EventEmitter();
/** Emits when the deselected items change. */
this.deselectedChange = new EventEmitter();
/** The Nested tree control used for the deselect tree */
this._treeControl = new FlatTreeControl(node => node.level, node => node.expandable);
/** The remaining selectable columns in the deselected list */
this._availableDeselectedColumns = 0;
/** An array of items that are currently selected in the left column. */
this._deselectedSelection = [];
/** An array of items that are currently selected in the right column. */
this._selectedSelection = [];
/** Cache selection during reordering */
this._selection = [];
/** Shallow copy of selection for reordering directive */
this._storedSelection = [];
}
/** Define settings for the grouped deselected items. */
set groups(groups) {
this._columnPicker.groups = groups;
}
get groups() {
return this._columnPicker.groups;
}
ngOnChanges(changes) {
// recreate tree when deselected changes
if (changes.deselected && changes.deselected.currentValue !== changes.deselected.previousValue) {
this.rebuildDeselectTree();
}
}
/** Parse data into suitable format for the FlatTreeComponent to understand and initialize deselect tree */
rebuildDeselectTree() {
const columns = this._columnPicker.getDeselectedColumnsInPresentationOrder(this.deselected.slice(), this.sort);
const treeData = this._columnPicker.createTreeData(columns);
this._treeData = treeData;
this._treeDataSource = new ArrayDataSource(treeData);
// set initial count for deselected values
this.updateAvailableDeselectedColumns();
}
/** A function that can be called to add columns. If no columns are passed to the function, the items that are selected in the left column will be added. */
addColumns(columns = this._deselectedSelection) {
const deselectedSelection = columns.filter(column => this.selected.indexOf(column) === -1);
// add each item to the selected columns list
this.selected = [...this.selected, ...deselectedSelection];
this.deselected = this.deselected.filter(column => deselectedSelection.indexOf(column) === -1);
// emit the selection changes
this.selectedChange.emit(this.selected);
this.deselectedChange.emit(this.deselected);
// store the available deselected items
this.updateAvailableDeselectedColumns();
// clear the current selection
this._deselectedSelection = [];
}
/** A function that can be called to remove columns. If no columns are passed to the function, the items that are selected in the right column will be removed. */
removeColumns(columns = this._selectedSelection) {
// remove each item from the selected columns list
this.selected = this.selected.filter(column => columns.indexOf(column) === -1);
this.deselected = [
...this.deselected,
...columns
];
// emit the selection changes
this.selectedChange.emit(this.selected);
this.deselectedChange.emit(this.deselected);
// store the available deselected items
this.updateAvailableDeselectedColumns();
// clear the current selection
this._selectedSelection = [];
}
/** A function that can be called to add all columns. */
addAllColumns() {
this.addColumns(this.deselected);
}
/** A function that can be called to remove all columns. */
removeAllColumns() {
this.removeColumns(this.selected);
}
/** Ensure we don't select while dragging */
storeSelection() {
this._selection = [...this._selectedSelection];
this._storedSelection = [...this.selected];
}
/** Restore the selection once dragging ends */
restoreSelection() {
this._selectedSelection = [...this._selection];
}
/** Update when reordering has occurred */
onReorder() {
this.selectedChange.emit(this.selected);
}
/** Get an aria label for deselected list groups */
getDefaultDeselectedGroupAriaLabel(column) {
return `Toggle ${column}`;
}
/** Get an aria label for reorderable items */
getDefaultSelectedAriaLabel(column) {
return `${column}. Press Alt up and alt down to reorder.`;
}
/** Get the announcement to read when a selected column is moved */
getColumnMovedAnnouncement(column, delta) {
return `${column} column moved ${delta > 0 ? 'down' : 'up'}`;
}
/** Perform a reorder with the keyboard */
move(column, delta) {
// perform the move
const index = this.selected.indexOf(column);
this.swap(index, index + delta);
// Announce the move if the order has changed
if (this.selected.indexOf(column) !== index) {
this._liveAnnouncer.announce(`Column moved ${delta > 0 ? 'down' : 'up'}`);
}
// emit the changes
this.selectedChange.emit(this.selected);
// perform change detection
this._changeDetectorRef.detectChanges();
// after the UI has updated focus the element again (ngFor creates new DOM elements)
setTimeout(() => {
const columnIndex = this.selected.indexOf(column);
const target = this.selectedElements.toArray()[columnIndex];
if (target) {
// focus the element
target.nativeElement.focus();
}
});
}
/** Provide a trackBy function for the reorderable options */
selectedTrackBy(index, column) {
return index + getColumnPickerGroupItemName(column);
}
/** Swap two elements in the selected columns array */
swap(source, target) {
// perform boundary checks
if (target < 0 || target > this.selected.length - 1) {
return;
}
// create a copy of the array to manipulate
const selected = [...this.selected];
// swap the array elements
[selected[target], selected[source]] = [selected[source], selected[target]];
// update the original array
this.selected = [...selected];
}
/** Get the column name based on type */
_getColumnName(item) {
return isColumnPickerGroupItem(item) ? item.name : item;
}
/** Check if tree group has visible children */
_nodeHasChildren(_, node) {
return node.expandable;
}
_nodeHasAvailableChildren(node) {
return node.children.filter(column => this.selected.indexOf(column) === -1).length > 0;
}
/** Check to see if current item should display in deselect tree */
_shouldRenderNode(node) {
const parent = this.getTreeParent(node);
return (!parent || parent.isExpanded) && !this.selected.find(column => this._getColumnName(column) === node.name);
}
/** Work backwards from the index of the current node to find the parent node */
getTreeParent(node) {
const nodeIndex = this._treeData.indexOf(node);
if (node.level > 0) {
for (let i = nodeIndex - 1; i >= 0; i--) {
if (this._treeData[i].level === 0) {
return this._treeData[i];
}
}
}
return null;
}
/** Store the current count of nodes that are available for selection from the deselected list */
updateAvailableDeselectedColumns() {
this._availableDeselectedColumns = this.deselected.length;
}
/** Update the order of the items when reordering has changed */
onReorderChange(model) {
this.selected = [...model];
this.onReorder();
}
/** Get the action context, ensuring that functions have a pre-bound context */
_getActionContext() {
return {
addSelection: this._deselectedSelection,
removeSelection: this._selectedSelection,
addColumns: this.addColumns.bind(this),
removeColumns: this.removeColumns.bind(this),
addAllColumns: this.addAllColumns.bind(this),
removeAllColumns: this.removeAllColumns.bind(this)
};
}
/** Change the expanded state of a node */
_setNodeExpanded(node, isExpanded) {
node.isExpanded = isExpanded;
// the first change detection cycle will hide the elements but we need to trigger
// a second change detection cycle on the next tick to ensure the ContentChildren
// QueryList gets updated in the uxTabbableList directive
requestAnimationFrame(() => this._changeDetectorRef.detectChanges());
}
_isNodeSelected(name) {
const filtered = this._deselectedSelection.filter(selection => (isColumnPickerGroupItem(selection) ? selection.name === name : selection === name));
return filtered.length > 0;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ColumnPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: ColumnPickerComponent, selector: "ux-column-picker", inputs: { id: "id", selected: "selected", locked: "locked", deselected: "deselected", selectedTitleTemplate: "selectedTitleTemplate", deselectedTitleTemplate: "deselectedTitleTemplate", deselectedTemplate: "deselectedTemplate", selectedTemplate: "selectedTemplate", lockedTemplate: "lockedTemplate", actionsTemplate: "actionsTemplate", selectedAriaLabel: "selectedAriaLabel", deselectedGroupAriaLabel: "deselectedGroupAriaLabel", columnMovedAnnouncement: "columnMovedAnnouncement", groups: "groups", sort: "sort", addColumnAriaLabel: "addColumnAriaLabel", removeColumnAriaLabel: "removeColumnAriaLabel", addAllColumnsAriaLabel: "addAllColumnsAriaLabel", removeAllColumnsAriaLabel: "removeAllColumnsAriaLabel" }, outputs: { selectedChange: "selectedChange", deselectedChange: "deselectedChange" }, providers: [ColumnPickerService], viewQueries: [{ propertyName: "selectedElements", predicate: ["selectedColumn"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"column-picker-column\">\n\n <div class=\"column-picker-stats\" [id]=\"id + '-stats-left'\">\n\n @if (!deselectedTitleTemplate) {\n {{ _deselectedSelection.length }} of {{ _availableDeselectedColumns }} selected\n }\n\n @if (deselectedTitleTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"deselectedTitleTemplate\">\n </ng-container>\n }\n </div>\n\n <cdk-tree class=\"column-picker-list\"\n [dataSource]=\"_treeDataSource\"\n [treeControl]=\"_treeControl\"\n [(uxSelection)]=\"_deselectedSelection\"\n [attr.aria-labelledby]=\"id + '-stats-left'\"\n tabindex=\"-1\"\n uxTabbableList>\n\n <!-- Create item for not expandable node -->\n <cdk-tree-node *cdkTreeNodeDef=\"let node\"\n [attr.aria-hidden]=\"selected && selected.indexOf(node.name) > -1\"\n [attr.aria-selected]=\"_isNodeSelected(node.name)\">\n @if (_shouldRenderNode(node)) {\n <div uxTabbableListItem\n [uxSelectionItem]=\"node.column\"\n addAriaAttributes=\"false\"\n class=\"column-picker-list-item\"\n [ngClass]=\"'column-picker-tree-node-level-' + node.level\">\n @if (!deselectedTemplate) {\n {{ node.name }}\n }\n @if (deselectedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"deselectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: node.name }\">\n </ng-container>\n }\n </div>\n }\n\n </cdk-tree-node>\n\n <!-- Create item for expandable node -->\n <cdk-tree-node *cdkTreeNodeDef=\"let node; when: _nodeHasChildren\"\n [attr.aria-expanded]=\"node.isExpanded\">\n\n @if (_nodeHasAvailableChildren(node)) {\n <div\n class=\"column-picker-tree-group-node\">\n <button uxTabbableListItem\n (click)=\"_setNodeExpanded(node, !node.isExpanded)\"\n (keydown.arrowright)=\"_setNodeExpanded(node, true)\"\n (keydown.arrowleft)=\"_setNodeExpanded(node, false)\"\n [style.visibility]=\"node.expandable ? 'visible' : 'hidden'\"\n [attr.aria-label]=\"deselectedGroupAriaLabel(node.name, node.isExpanded)\"\n class=\"column-picker-group-toggle-btn\">\n <ux-icon [name]=\"node.isExpanded ? 'chevron-down' : 'chevron-right'\"></ux-icon>\n @if (!deselectedTemplate) {\n {{ node.name }}\n }\n @if (deselectedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"deselectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: node.name }\">\n </ng-container>\n }\n </button>\n </div>\n }\n </cdk-tree-node>\n </cdk-tree>\n</div>\n\n<div class=\"column-picker-actions-column\">\n <!-- Show the default action buttons -->\n @if (!actionsTemplate) {\n <button class=\"btn button-primary btn-block\"\n [disabled]=\"_deselectedSelection.length === 0\"\n [attr.aria-label]=\"addColumnAriaLabel\"\n (click)=\"addColumns()\">\n <ux-icon name=\"chevron-right\"></ux-icon>\n </button>\n <button class=\"btn button-primary btn-block m-b-md\"\n [disabled]=\"_selectedSelection.length === 0\"\n [attr.aria-label]=\"removeColumnAriaLabel\"\n (click)=\"removeColumns()\">\n <ux-icon name=\"chevron-left\"></ux-icon>\n </button>\n <button class=\"btn button-secondary btn-block\"\n [disabled]=\"_availableDeselectedColumns === 0\"\n [attr.aria-label]=\"addAllColumnsAriaLabel\"\n (click)=\"addAllColumns()\">\n <ux-icon name=\"chevron-right-double\"></ux-icon>\n </button>\n <button class=\"btn button-secondary btn-block\"\n [disabled]=\"selected.length === 0\"\n [attr.aria-label]=\"removeAllColumnsAriaLabel\"\n (click)=\"removeAllColumns()\">\n <ux-icon name=\"chevron-left-double\"></ux-icon>\n </button>\n }\n\n <!-- Allow custom actions template -->\n @if (actionsTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"actionsTemplate\"\n [ngTemplateOutletContext]=\"_getActionContext()\">\n </ng-container>\n }\n\n</div>\n\n<div class=\"column-picker-column\">\n <div class=\"column-picker-stats\" [id]=\"id + '-stats-right'\">\n\n @if (!selectedTitleTemplate) {\n {{ selected.length + locked.length }} columns added\n }\n\n @if (selectedTitleTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"selectedTitleTemplate\">\n </ng-container>\n }\n </div>\n\n <div class=\"column-picker-list\" role=\"listbox\" [attr.aria-labelledby]=\"id + '-stats-right'\">\n\n @for (column of locked; track column) {\n <div\n class=\"column-picker-list-item column-picker-list-item-locked\">\n @if (!lockedTemplate) {\n {{ column }} <ux-icon name=\"lock\"></ux-icon>\n }\n @if (lockedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"lockedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: column }\">\n </ng-container>\n }\n </div>\n }\n\n <div [(uxSelection)]=\"_selectedSelection\"\n uxReorderable\n [reorderableModel]=\"_storedSelection\"\n (reorderableModelChange)=\"onReorderChange($event)\"\n (reorderStart)=\"storeSelection()\"\n (reorderEnd)=\"restoreSelection()\">\n\n @for (column of selected; track selectedTrackBy(index, column); let index = $index) {\n <div\n #selectedColumn\n uxFocusIndicator\n [programmaticFocusIndicator]=\"true\"\n class=\"column-picker-list-item column-picker-list-item-selected\"\n [uxSelectionItem]=\"column\"\n [uxReorderableModel]=\"column\"\n [attr.aria-label]=\"selectedAriaLabel(column, selected.indexOf(column))\"\n (keydown.alt.arrowup)=\"move(column, -1)\"\n (keydown.alt.arrowdown)=\"move(column, 1)\"\n role=\"option\">\n @if (!selectedTemplate) {\n <ux-icon uxReorderableHandle name=\"drag\" class=\"drag-handle-icon\"></ux-icon>\n {{ _getColumnName(column) }}\n }\n @if (selectedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"selectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: column }\">\n </ng-container>\n }\n </div>\n }\n </div>\n\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.DefaultFocusIndicatorDirective, selector: ".btn:not([uxFocusIndicator]):not([uxMenuNavigationToggle]):not([uxMenuTriggerFor]), a[href]:not([uxFocusIndicator]):not([uxMenuNavigationToggle]):not([uxMenuTriggerFor])" }, { kind: "directive", type: i2.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "directive", type: i3.TabbableListDirective, selector: "[uxTabbableList]", inputs: ["direction", "wrap", "focusOnShow", "returnFocus", "hierarchy", "allowAltModifier", "allowCtrlModifier", "allowBoundaryKeys"], exportAs: ["ux-tabbable-list"] }, { kind: "directive", type: i4.TabbableListItemDirective, selector: "[uxTabbableListItem]", inputs: ["parent", "rank", "disabled", "expanded", "key"], outputs: ["expandedChange", "activated"], exportAs: ["ux-tabbable-list-item"] }, { kind: "directive", type: i5.CdkTreeNodeDef, selector: "[cdkTreeNodeDef]", inputs: ["cdkTreeNodeDefWhen"] }, { kind: "component", type: i5.CdkTree, selector: "cdk-tree", inputs: ["dataSource", "treeControl", "levelAccessor", "childrenAccessor", "trackBy", "expansionKey"], exportAs: ["cdkTree"] }, { kind: "directive", type: i5.CdkTreeNode, selector: "cdk-tree-node", inputs: ["role", "isExpandable", "isExpanded", "isDisabled", "cdkTreeNodeTypeaheadLabel"], outputs: ["activation", "expandedChange"], exportAs: ["cdkTreeNode"] }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i7.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }, { kind: "directive", type: i8.ReorderableDirective, selector: "[uxReorderable]", inputs: ["reorderableModel", "reorderableGroup", "reorderingDisabled"], outputs: ["reorderableModelChange", "reorderStart", "reorderCancel", "reorderEnd"] }, { kind: "directive", type: i9.ReorderableHandleDirective, selector: "[uxReorderableHandle]" }, { kind: "directive", type: i10.ReorderableModelDirective, selector: "[uxReorderableModel]", inputs: ["uxReorderableModel"] }, { kind: "directive", type: i11.SelectionDirective, selector: "[uxSelection]", inputs: ["uxSelection", "disabled", "mode", "clickSelection", "keyboardSelection", "selectionItems", "tabindex"], outputs: ["uxSelectionChange"], exportAs: ["ux-selection"] }, { kind: "directive", type: i12.SelectionItemDirective, selector: "[uxSelectionItem]", inputs: ["uxSelectionItem", "selected", "tabindex", "uxSelectionDisabled", "addAriaAttributes"], outputs: ["selectedChange"], exportAs: ["ux-selection-item"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ColumnPickerComponent, decorators: [{
type: Component,
args: [{ selector: 'ux-column-picker', changeDetection: ChangeDetectionStrategy.OnPush, providers: [ColumnPickerService], template: "<div class=\"column-picker-column\">\n\n <div class=\"column-picker-stats\" [id]=\"id + '-stats-left'\">\n\n @if (!deselectedTitleTemplate) {\n {{ _deselectedSelection.length }} of {{ _availableDeselectedColumns }} selected\n }\n\n @if (deselectedTitleTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"deselectedTitleTemplate\">\n </ng-container>\n }\n </div>\n\n <cdk-tree class=\"column-picker-list\"\n [dataSource]=\"_treeDataSource\"\n [treeControl]=\"_treeControl\"\n [(uxSelection)]=\"_deselectedSelection\"\n [attr.aria-labelledby]=\"id + '-stats-left'\"\n tabindex=\"-1\"\n uxTabbableList>\n\n <!-- Create item for not expandable node -->\n <cdk-tree-node *cdkTreeNodeDef=\"let node\"\n [attr.aria-hidden]=\"selected && selected.indexOf(node.name) > -1\"\n [attr.aria-selected]=\"_isNodeSelected(node.name)\">\n @if (_shouldRenderNode(node)) {\n <div uxTabbableListItem\n [uxSelectionItem]=\"node.column\"\n addAriaAttributes=\"false\"\n class=\"column-picker-list-item\"\n [ngClass]=\"'column-picker-tree-node-level-' + node.level\">\n @if (!deselectedTemplate) {\n {{ node.name }}\n }\n @if (deselectedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"deselectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: node.name }\">\n </ng-container>\n }\n </div>\n }\n\n </cdk-tree-node>\n\n <!-- Create item for expandable node -->\n <cdk-tree-node *cdkTreeNodeDef=\"let node; when: _nodeHasChildren\"\n [attr.aria-expanded]=\"node.isExpanded\">\n\n @if (_nodeHasAvailableChildren(node)) {\n <div\n class=\"column-picker-tree-group-node\">\n <button uxTabbableListItem\n (click)=\"_setNodeExpanded(node, !node.isExpanded)\"\n (keydown.arrowright)=\"_setNodeExpanded(node, true)\"\n (keydown.arrowleft)=\"_setNodeExpanded(node, false)\"\n [style.visibility]=\"node.expandable ? 'visible' : 'hidden'\"\n [attr.aria-label]=\"deselectedGroupAriaLabel(node.name, node.isExpanded)\"\n class=\"column-picker-group-toggle-btn\">\n <ux-icon [name]=\"node.isExpanded ? 'chevron-down' : 'chevron-right'\"></ux-icon>\n @if (!deselectedTemplate) {\n {{ node.name }}\n }\n @if (deselectedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"deselectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: node.name }\">\n </ng-container>\n }\n </button>\n </div>\n }\n </cdk-tree-node>\n </cdk-tree>\n</div>\n\n<div class=\"column-picker-actions-column\">\n <!-- Show the default action buttons -->\n @if (!actionsTemplate) {\n <button class=\"btn button-primary btn-block\"\n [disabled]=\"_deselectedSelection.length === 0\"\n [attr.aria-label]=\"addColumnAriaLabel\"\n (click)=\"addColumns()\">\n <ux-icon name=\"chevron-right\"></ux-icon>\n </button>\n <button class=\"btn button-primary btn-block m-b-md\"\n [disabled]=\"_selectedSelection.length === 0\"\n [attr.aria-label]=\"removeColumnAriaLabel\"\n (click)=\"removeColumns()\">\n <ux-icon name=\"chevron-left\"></ux-icon>\n </button>\n <button class=\"btn button-secondary btn-block\"\n [disabled]=\"_availableDeselectedColumns === 0\"\n [attr.aria-label]=\"addAllColumnsAriaLabel\"\n (click)=\"addAllColumns()\">\n <ux-icon name=\"chevron-right-double\"></ux-icon>\n </button>\n <button class=\"btn button-secondary btn-block\"\n [disabled]=\"selected.length === 0\"\n [attr.aria-label]=\"removeAllColumnsAriaLabel\"\n (click)=\"removeAllColumns()\">\n <ux-icon name=\"chevron-left-double\"></ux-icon>\n </button>\n }\n\n <!-- Allow custom actions template -->\n @if (actionsTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"actionsTemplate\"\n [ngTemplateOutletContext]=\"_getActionContext()\">\n </ng-container>\n }\n\n</div>\n\n<div class=\"column-picker-column\">\n <div class=\"column-picker-stats\" [id]=\"id + '-stats-right'\">\n\n @if (!selectedTitleTemplate) {\n {{ selected.length + locked.length }} columns added\n }\n\n @if (selectedTitleTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"selectedTitleTemplate\">\n </ng-container>\n }\n </div>\n\n <div class=\"column-picker-list\" role=\"listbox\" [attr.aria-labelledby]=\"id + '-stats-right'\">\n\n @for (column of locked; track column) {\n <div\n class=\"column-picker-list-item column-picker-list-item-locked\">\n @if (!lockedTemplate) {\n {{ column }} <ux-icon name=\"lock\"></ux-icon>\n }\n @if (lockedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"lockedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: column }\">\n </ng-container>\n }\n </div>\n }\n\n <div [(uxSelection)]=\"_selectedSelection\"\n uxReorderable\n [reorderableModel]=\"_storedSelection\"\n (reorderableModelChange)=\"onReorderChange($event)\"\n (reorderStart)=\"storeSelection()\"\n (reorderEnd)=\"restoreSelection()\">\n\n @for (column of selected; track selectedTrackBy(index, column); let index = $index) {\n <div\n #selectedColumn\n uxFocusIndicator\n [programmaticFocusIndicator]=\"true\"\n class=\"column-picker-list-item column-picker-list-item-selected\"\n [uxSelectionItem]=\"column\"\n [uxReorderableModel]=\"column\"\n [attr.aria-label]=\"selectedAriaLabel(column, selected.indexOf(column))\"\n (keydown.alt.arrowup)=\"move(column, -1)\"\n (keydown.alt.arrowdown)=\"move(column, 1)\"\n role=\"option\">\n @if (!selectedTemplate) {\n <ux-icon uxReorderableHandle name=\"drag\" class=\"drag-handle-icon\"></ux-icon>\n {{ _getColumnName(column) }}\n }\n @if (selectedTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"selectedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: column }\">\n </ng-container>\n }\n </div>\n }\n </div>\n\n </div>\n</div>\n" }]
}], propDecorators: { id: [{
type: Input
}], selected: [{
type: Input
}], locked: [{
type: Input
}], deselected: [{
type: Input
}], selectedTitleTemplate: [{
type: Input
}], deselectedTitleTemplate: [{
type: Input
}], deselectedTemplate: [{
type: Input
}], selectedTemplate: [{
type: Input
}], lockedTemplate: [{
type: Input
}], actionsTemplate: [{
type: Input
}], selectedAriaLabel: [{
type: Input
}], deselectedGroupAriaLabel: [{
type: Input
}], columnMovedAnnouncement: [{
type: Input
}], groups: [{
type: Input
}], sort: [{
type: Input
}], addColumnAriaLabel: [{
type: Input
}], removeColumnAriaLabel: [{
type: Input
}], addAllColumnsAriaLabel: [{
type: Input
}], removeAllColumnsAriaLabel: [{
type: Input
}], selectedChange: [{
type: Output
}], deselectedChange: [{
type: Output
}], selectedElements: [{
type: ViewChildren,
args: ['selectedColumn']
}] } });
function getColumnPickerGroupItemName(column) {
return isColumnPickerGroupItem(column) ? column.name : column;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sdW1uLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy90YWJsZS9jb2x1bW4tcGlja2VyL2NvbHVtbi1waWNrZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdGFibGUvY29sdW1uLXBpY2tlci9jb2x1bW4tcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNsRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3BELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQWMsWUFBWSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQWEsTUFBTSxFQUF5QyxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdk0sT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUF5Qix1QkFBdUIsRUFBRSxNQUFNLGlEQUFpRCxDQUFDOzs7Ozs7Ozs7Ozs7OztBQUdqSCxJQUFJLFFBQVEsR0FBRyxDQUFDLENBQUM7QUFRakIsTUFBTSxPQUFPLHFCQUFxQjtJQU5sQztRQU9xQixrQkFBYSxHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBRTdELHFFQUFxRTtRQUNwRCxtQkFBYyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUV4RCwwRUFBMEU7UUFDekQsdUJBQWtCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFaEUsd0NBQXdDO1FBQy9CLE9BQUUsR0FBVyxvQkFBb0IsUUFBUSxFQUFFLEVBQUUsQ0FBQztRQUV2RCw2Q0FBNkM7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QUFNLGFBQ3BDLENBQUMsbUJBQW1CLENBQUM7OEJBWXZCLEVBQUU7c0JBQVYsS0FBSztnQkFHRyxRQUFRO3NCQUFoQixLQUFLO2dCQUdHLE1BQU07c0JBQWQsS0FBSztnQkFHRyxVQUFVO3NCQUFsQixLQUFLO2dCQUdHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFHRyx1QkFBdUI7c0JBQS9CLEtBQUs7Z0JBR0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUdHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFHRyxjQUFjO3NCQUF0QixLQUFLO2dCQUdHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBR0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUdHLHdCQUF3QjtzQkFBaEMsS0FBSztnQkFHRyx1QkFBdUI7c0JBQS9CLEtBQUs7Z0JBR08sTUFBTTtzQkFBbEIsS0FBSztnQkFTRyxJQUFJO3NCQUFaLEtBQUs7Z0JBR0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUdHLHFCQUFxQjtzQkFBN0IsS0FBSztnQkFHRyxzQkFBc0I7c0JBQTlCLEtBQUs7Z0JBR0cseUJBQXlCO3NCQUFqQyxLQUFLO2dCQUdJLGNBQWM7c0JBQXZCLE1BQU07Z0JBR0csZ0JBQWdCO3NCQUF6QixNQUFNO2dCQThCeUIsZ0JBQWdCO3NCQUEvQyxZQUFZO3VCQUFDLGdCQUFnQjs7QUF5T2xDLFNBQVMsNEJBQTRCLENBQUMsTUFBc0M7SUFDeEUsT0FBTyx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO0FBQ2xFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMaXZlQW5ub3VuY2VyIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2ExMXknO1xuaW1wb3J0IHsgQXJyYXlEYXRhU291cmNlIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2NvbGxlY3Rpb25zJztcbmltcG9ydCB7IEZsYXRUcmVlQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Nkay90cmVlJztcbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIGluamVjdCwgSW5wdXQsIE9uQ2hhbmdlcywgT3V0cHV0LCBRdWVyeUxpc3QsIFNpbXBsZUNoYW5nZXMsIFRlbXBsYXRlUmVmLCBWaWV3Q2hpbGRyZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbHVtblBpY2tlclNlcnZpY2UgfSBmcm9tICcuL2NvbHVtbi1waWNrZXIuc2VydmljZSc7XG5pbXBvcnQgeyBDb2x1bW5QaWNrZXJHcm91cEl0ZW0sIGlzQ29sdW1uUGlja2VyR3JvdXBJdGVtIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2NvbHVtbi1waWNrZXItZ3JvdXAtaXRlbS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ29sdW1uUGlja2VyVHJlZU5vZGUgfSBmcm9tICcuL2ludGVyZmFjZXMvY29sdW1uLXBpY2tlci10cmVlLW5vZGUuaW50ZXJmYWNlJztcblxubGV0IHVuaXF1ZUlkID0gMDtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICd1eC1jb2x1bW4tcGlja2VyJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vY29sdW1uLXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgcHJvdmlkZXJzOiBbQ29sdW1uUGlja2VyU2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgQ29sdW1uUGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jb2x1bW5QaWNrZXIgPSBpbmplY3QoQ29sdW1uUGlja2VyU2VydmljZSk7XG5cbiAgICAvKiogQWNjZXNzIHRoZSBMaXZlQW5ub3VuY2UgdG8gcHJvdmlkZSBhY2Nlc3NpYmlsaXR5IG9uIHJlb3JkZXJpbmcgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9saXZlQW5ub3VuY2VyID0gaW5qZWN0KExpdmVBbm5vdW5jZXIpO1xuXG4gICAgLyoqIFdlIGFyZSB1c2luZyBPblB1c2ggY2hhbmdlIGRldGVjdGlvbiBzbyB3ZSBtdXN0IG1hbnVhbGx5IHRyaWdnZXIgQ0QgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jaGFuZ2VEZXRlY3RvclJlZiA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgICAvKiogU2V0cyB0aGUgaWQgb2YgdGhlIGNvbHVtbiBwaWNrZXIuICovXG4gICAgQElucHV0KCkgaWQ6IHN0cmluZyA9IGB1eC1udW1iZXItcGlja2VyLSR7dW5pcXVlSWQrK31gO1xuXG4gICAgLyoqIERlZmluZSBhIGxpc3Qgb2YgYWxsIHNlbGVjdGVkIGNvbHVtbnMuICovXG4gICAgQElucHV0KCkgc2VsZWN0ZWQ6IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgQ29sdW1uUGlja2VyR3JvdXBJdGVtPiA9IFtdO1xuXG4gICAgLyoqIERlZmluZSBhIGxpc3Qgb2YgY29sdW1ucyB0aGF0IGFyZSBhbHdheXMgc2VsZWN0ZWQuIFRoZSBjb2x1bW5zIGNhbm5vdCBiZSBtb3ZlZCBvciByZW9yZGVyZWQuICovXG4gICAgQElucHV0KCkgbG9ja2VkOiBSZWFkb25seUFycmF5PHN0cmluZz4gPSBbXTtcblxuICAgIC8qKiBEZWZpbmUgYSBsaXN0IG9mIGNvbHVtbnMgdGhhdCBhcmUgbm90IHNlbGVjdGVkIG9yIGxvY2tlZC4gQWxsIGNvbHVtbnMgbXVzdCBoYXZlIHVuaXF1ZSBuYW1lcywgaW5jbHVkaW5nIGNvbHVtbnMgaW4gZGlmZmVyZW50IGdyb3Vwcy4gKi9cbiAgICBASW5wdXQoKSBkZXNlbGVjdGVkOiBSZWFkb25seUFycmF5PHN0cmluZyB8IENvbHVtblBpY2tlckdyb3VwSXRlbT4gPSBbXTtcblxuICAgIC8qKiBEZWZpbmUgYSBjdXN0b20gc2VsZWN0ZWQgdGl0bGUgdGVtcGxhdGUuICovXG4gICAgQElucHV0KCkgc2VsZWN0ZWRUaXRsZVRlbXBsYXRlOiBUZW1wbGF0ZVJlZjx2b2lkPjtcblxuICAgIC8qKiBEZWZpbmUgYSBjdXN0b20gZGVzZWxlY3RlZCB0aXRsZSB0ZW1wbGF0ZS4gKi9cbiAgICBASW5wdXQoKSBkZXNlbGVjdGVkVGl0bGVUZW1wbGF0ZTogVGVtcGxhdGVSZWY8dm9pZD47XG5cbiAgICAvKiogRGVmaW5lIGEgY3VzdG9tIHRlbXBsYXRlIGZvciBkZXNlbGVjdGVkIGl0ZW1zLiAqL1xuICAgIEBJbnB1dCgpIGRlc2VsZWN0ZWRUZW1wbGF0ZTogVGVtcGxhdGVSZWY8c3RyaW5nPjtcblxuICAgIC8qKiBEZWZpbmUgYSBjdXN0b20gdGVtcGxhdGUgZm9yIHNlbGVjdGVkIGl0ZW1zLiAqL1xuICAgIEBJbnB1dCgpIHNlbGVjdGVkVGVtcGxhdGU6IFRlbXBsYXRlUmVmPHN0cmluZz47XG5cbiAgICAvKiogRGVmaW5lIGEgY3VzdG9tIHRlbXBsYXRlIGZvciBsb2NrZWQgaXRlbXMuICovXG4gICAgQElucHV0KCkgbG9ja2VkVGVtcGxhdGU6IFRlbXBsYXRlUmVmPHN0cmluZz47XG5cbiAgICAvKiogRGVmaW5lIGEgY3VzdG9tIHRlbXBsYXRlIGZvciB0aGUgYWN0aW9uIGJ1dHRvbnMgY29sdW1ucy4gKi9cbiAgICBASW5wdXQoKSBhY3Rpb25zVGVtcGxhdGU6IFRlbXBsYXRlUmVmPENvbHVtblBpY2tlckFjdGlvbnNDb250ZXh0PjtcblxuICAgIC8qKiBEZWZpbmUgYSBmdW5jdGlvbiB0byBnZXQgdGhlIGFyaWEgbGFiZWwgb2YgcmVvcmRlcmFibGUgaXRlbXMgaW4gdGhlIHNlbGVjdGVkIGNvbHVtbi4gKi9cbiAgICBASW5wdXQoKSBzZWxlY3RlZEFyaWFMYWJlbDogKGNvbHVtbjogc3RyaW5nIHwgQ29sdW1uUGlja2VyR3JvdXBJdGVtLCBpbmRleDogbnVtYmVyKSA9PiBzdHJpbmcgPSB0aGlzLmdldERlZmF1bHRTZWxlY3RlZEFyaWFMYWJlbDtcblxuICAgIC8qKiBEZWZpbmUgYSBmdW5jdGlvbiB0byBnZXQgdGhlIGFyaWEgbGFiZWwgb2YgYSBncm91cCBpbiB0aGUgZGVzZWxlY3RlZCBsaXN0LiAqL1xuICAgIEBJbnB1dCgpIGRlc2VsZWN0ZWRHcm91cEFyaWFMYWJlbDogKGNvbHVtbjogc3RyaW5nIHwgQ29sdW1uUGlja2VyR3JvdXBJdGVtLCBpc0V4cGFuZGVkOiBib29sZWFuKSA9PiBzdHJpbmcgPSB0aGlzLmdldERlZmF1bHREZXNlbGVjdGVkR3JvdXBBcmlhTGFiZWw7XG5cbiAgICAvKiogRGVmaW5lIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgY29sdW1uIG1vdmUgYW5ub3VuY2VtZW50LiAqL1xuICAgIEBJbnB1dCgpIGNvbHVtbk1vdmVkQW5ub3VuY2VtZW50OiAoY29sdW1uOiBzdHJpbmcgfCBDb2x1bW5QaWNrZXJHcm91cEl0ZW0sIGRlbHRhOiBudW1iZXIpID0+IHN0cmluZyA9IHRoaXMuZ2V0Q29sdW1uTW92ZWRBbm5vdW5jZW1lbnQ7XG5cbiAgICAvKiogRGVmaW5lIHNldHRpbmdzIGZvciB0aGUgZ3JvdXBlZCBkZXNlbGVjdGVkIGl0ZW1zLiAqL1xuICAgIEBJbnB1dCgpIHNldCBncm91cHMoZ3JvdXBzOiBDb2x1bW5QaWNrZXJHcm91cFtdKSB7XG4gICAgICAgIHRoaXMuX2NvbHVtblBpY2tlci5ncm91cHMgPSBncm91cHM7XG4gICAgfVxuXG4gICAgZ2V0IGdyb3VwcygpOiBDb2x1bW5QaWNrZXJHcm91cFtdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbHVtblBpY2tlci5ncm91cHM7XG4gICAgfVxuXG4gICAgLyoqIERlZmluZSBhIGNvbXBhcmF0b3IgZnVuY3Rpb24gdXNlZCBmb3Igc29ydGluZyB0aGUgZGVzZWxlY3RlZCBjb2x1bW5zLiAqL1xuICAgIEBJbnB1dCgpIHNvcnQ6IChhOiBDb2x1bW5QaWNrZXJHcm91cEl0ZW0sIGI6IENvbHVtblBpY2tlckdyb3VwSXRlbSkgPT4gbnVtYmVyO1xuXG4gICAgLyoqIERlZmluZSB0aGUgYXJpYSBsYWJlbCBmb3IgdGhlIGFkZCBjb2x1bW4gYnV0dG9uICovXG4gICAgQElucHV0KCkgYWRkQ29sdW1uQXJpYUxhYmVsOiBzdHJpbmcgPSAnQWRkIHNlbGVjdGVkIGl0ZW0nO1xuXG4gICAgLyoqIERlZmluZSB0aGUgYXJpYSBsYWJlbCBmb3IgdGhlIHJlbW92ZSBjb2x1bW4gYnV0dG9uICovXG4gICAgQElucHV0KCkgcmVtb3ZlQ29sdW1uQXJpYUxhYmVsOiBzdHJpbmcgPSAnUmVtb3ZlIHNlbGVjdGVkIGl0ZW0nO1xuXG4gICAgLyoqIERlZmluZSB0aGUgYXJpYSBsYWJlbCBmb3IgdGhlIGFkZCBhbGwgY29sdW1uIGJ1dHRvbiAqL1xuICAgIEBJbnB1dCgpIGFkZEFsbENvbHVtbnNBcmlhTGFiZWw6IHN0cmluZyA9ICdBZGQgYWxsIGl0ZW1zJztcblxuICAgIC8qKiBEZWZpbmUgdGhlIGFyaWEgbGFiZWwgZm9yIHRoZSByZW1vdmUgYWxsIGNvbHVtbiBidXR0b24gKi9cbiAgICBASW5wdXQoKSByZW1vdmVBbGxDb2x1bW5zQXJpYUxhYmVsOiBzdHJpbmcgPSAnUmVtb3ZlIGFsbCBpdGVtcyc7XG5cbiAgICAvKiogRW1pdHMgd2hlbiB0aGUgc2VsZWN0ZWQgaXRlbXMgY2hhbmdlIG9yIHRoZSBvcmRlciBvZiB0aGUgc2VsZWN0ZWQgaXRlbXMgY2hhbmdlLiAqL1xuICAgIEBPdXRwdXQoKSBzZWxlY3RlZENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8UmVhZG9ubHlBcnJheTxzdHJpbmcgfCBDb2x1bW5QaWNrZXJHcm91cEl0ZW0+PigpO1xuXG4gICAgLyoqIEVtaXRzIHdoZW4gdGhlIGRlc2VsZWN0ZWQgaXRlbXMgY2hhbmdlLiAqL1xuICAgIEBPdXRwdXQoKSBkZXNlbGVjdGVkQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxSZWFkb25seUFycmF5PHN0cmluZyB8IENvbHVtblBpY2tlckdyb3VwSXRlbT4+KCk7XG5cbiAgICAvKiogVGhlIE5lc3RlZCB0cmVlIGNvbnRyb2wgdXNlZCBmb3IgdGhlIGRlc2VsZWN0IHRyZWUgKi9cbiAgICBfdHJlZUNvbnRyb2w6IEZsYXRUcmVlQ29udHJvbDxDb2x1bW5QaWNrZXJUcmVlTm9kZT4gPSBuZXcgRmxhdFRyZWVDb250cm9sPENvbHVtblBpY2tlclRyZWVOb2RlPihcbiAgICAgICAgbm9kZSA9PiBub2RlLmxldmVsLFxuICAgICAgICBub2RlID0+IG5vZGUuZXhwYW5kYWJsZVxuICAgICk7XG5cbiAgICAvKiogQSB0cmVlLWZyaWVuZGx5IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkZXNlbGVjdGVkIGRhdGEgKi9cbiAgICBfdHJlZURhdGE6IENvbHVtblBpY2tlclRyZWVOb2RlW107XG5cbiAgICAvKiogRGF0YSBzb3VyY2Ugb2JzZXJ