@lightweightform/theme-common
Version:
Common utilities for Lightweightform themes
254 lines • 28 kB
JavaScript
import { __decorate } from "tslib";
import { Directive, Input } from '@angular/core';
import { isArrayLike } from '@lightweightform/storage';
import { makeObservable } from 'mobx';
import { computed, observable } from 'mobx-angular';
import { TableColumnContainer } from './table-column-container';
import * as i0 from "@angular/core";
/**
* Directive used to simplify the creation of table headers and manage the size
* of a table's max width, min width, and all columns. Tables using these
* functionalities should have their `table-layout` CSS property set to `fixed`.
*
* This directive provides utilities to transform the following:
* ```html
* <lf-table-header>
* <lf-table-column id="id" [fixed]="true" [minWidth]="40"></lf-table-column>
* <lf-table-column id="name">
* <lf-table-column id="first"></lf-table-column>
* <lf-table-column id="last"></lf-table-column>
* </lf-table-column>
* <lf-table-column id="age"></lf-table-column>
* </lf-table-header>
* ```
* Into a table header similar to the following diagram, where the `id` column
* has a fixed size and the remaining columns expand (with similar width) to the
* table's width.
* ```
* | | name | |
* | id |---------------------| age |
* | | first | last | |
* ```
*
* The directive provides utilities to help a table set its minimum and maximum
* widths, as well as column sizes (using `<colgroup>`) when necessary. The
* following example shows the creation of a table that uses an instance of this
* directive (named `header`) to manage width and column sizes. The example
* assumes that the table's `table-layout` CSS property is set to `fixed`:
* ```html
* <table
* [style.minWidth]="header.tableMinWidth + 'px'"
* [style.maxWidth]="header.tableMaxWidth + 'px'"
* >
* <colgroup>
* <col *ngFor="let width of header.columnWidths" [attr.width]="width"/>
* </colgroup>
*
* <thead>
* <tr *ngFor="let row of header.rows">
* <th
* *ngFor="let column of row"
* [attr.rowSpan]="column.rowSpan"
* [attr.colSpan]="column.colSpan"
* >
* {{ column.id }} <!-- Can be used to fetch a label, for example -->
* </th>
* </tr>
* </thead>
*
* <tbody><!-- ... --></tbody>
* </table>
* ```
*/
export class TableHeaderDirective extends TableColumnContainer {
constructor(elementRef) {
super(null, elementRef);
Object.defineProperty(this, "elementRef", {
enumerable: true,
configurable: true,
writable: true,
value: elementRef
});
/**
* Default min width (in `px`) of columns.
*/
Object.defineProperty(this, "defaultColumnsMinWidth", {
enumerable: true,
configurable: true,
writable: true,
value: 100
}); // Sane default
makeObservable(this);
}
/**
* Total number of rows of the header (should map to the number of `<tr>` of
* the actual header).
* @returns Number of rows of the header.
*/
get numberOfRows() {
return this.height - 1;
}
/**
* Number of (leaf) columns of the header (number of columns actually
* representing table cells/that don't have sub-columns).
* @returns Number of leaf columns of the header.
*/
get numberOfColumns() {
return this.width;
}
/**
* List of rows of the header, where each row contains a list of its columns.
* This should directly map each row to a `<tr>` of the header, and each
* column to a `<th>`. For the example depicted in the class description, this
* method would return: `[[id, name, age], [first, last]]`.
* @returns List of rows, where each row is a list of columns.
*/
get rows() {
const rows = [];
for (let i = 0; i < this.numberOfRows; ++i) {
rows.push(this.columnsOfRow(i));
}
return rows;
}
/**
* Minimum width (in pixels) that should be set on the table that contains
* this header. If the table does not have a min width, then the columns will
* collapse indefinitely, we thus provide a minimum width that amounts to the
* sum of the minimum width of all columns.
* @returns Minimum width (in pixels) that should be set on the table.
*/
get tableMinWidth() {
return this.leafColumns().reduce((sum, column) => sum + this.columnMinWidth(column), 0);
}
/**
* Maximum width (in pixels) that should be set on the table that contains
* this header. Tables where all the columns have a fixed width cannot ever
* expand, for that we must set a max width on the table, otherwise this
* method returns `Infinity`.
* @returns Maximum width (in pixels) that should be set on the table.
*/
get tableMaxWidth() {
return this.leafColumns().every((column) => column.fixed)
? this.tableMinWidth
: Infinity;
}
/**
* Width for all table columns, as they should be set in CSS (strings ending
* in `'px'` or `'%'` depending on whether the column is fixed). Each of these
* widths should be put on a `<col>` element inside a `<colgroup>` before the
* definition of the `<thead>` within a `<table>` with the `table-layout` CSS
* property set to `fixed`
* @returns List of widths of each leaf column.
*/
get columnWidths() {
const leaves = this.leafColumns();
// Columns not set as `fixed` should expand as necessary, as such we provide
// them with widths that together add up to `100%`
const dynamicMinWidthSum = leaves.reduce((sum, column) => sum + (column.fixed ? 0 : this.columnMinWidth(column)), 0);
return leaves.reduce((array, column) => {
var _a, _b;
const colSpan = (_a = column.colSpan) !== null && _a !== void 0 ? _a : 1;
// Determine the widths of each column being spanned by `column`
const colMinWidthArray = isArrayLike(column.minWidth)
? column.minWidth
: // Distribute the width amongst the columns being spanned
[...Array(colSpan)].map(() => this.columnMinWidth(column) / colSpan);
for (let i = 0; i < colSpan; ++i) {
// Columns will end up with a width of `0` when a `minWidth` array is
// provided with length smaller than `colSpan`
const colMinWidth = (_b = colMinWidthArray[i]) !== null && _b !== void 0 ? _b : 0;
array.push(column.fixed
? `${colMinWidth}px`
: `${(colMinWidth / dynamicMinWidthSum) * 100}%`);
}
return array;
}, []);
}
/**
* Method that returns the list of leaf columns: columns whose label directly
* represents a table cell/columns that contain no sub-columns. For the
* example depicted in the class description, this method would return:
* `[id, first, last, age]`.
* @param columnContainer For internal use only (to recurse over columns).
* @returns List of columns that are leaves.
*/
leafColumns(columnContainer = this) {
return columnContainer.childrenColumns.reduce((leaves, column) => leaves.concat(column.childrenColumns.length === 0
? [column]
: this.leafColumns(column)), []);
}
/**
* Method that returns the list of columns of a given row (`<tr>`) of the
* table header. For the example depicted in the class description, for row
* `0` this method would return `[id, name, age]`; for row `1` it would return
* `[first, last]`.
* @param index Index of row from which to fetch columns.
* @param columnContainer For internal use only (to recurse over columns).
* @returns List of columns of row with index `index`.
*/
columnsOfRow(index, columnContainer = this) {
return index === 0
? columnContainer.childrenColumns
: columnContainer.childrenColumns.reduce((rowColumns, column) => rowColumns.concat(this.columnsOfRow(index - 1, column)), []);
}
/**
* Minimum width of a column (or a default minimum width when none has been
* created).
* @param column Column whose minimum width we are interested in.
* @returns Minimum width of the column.
*/
columnMinWidth(column) {
var _a;
return isArrayLike(column.minWidth)
? column.minWidth.reduce((sum, width) => sum + width, 0)
: (_a = column.minWidth) !== null && _a !== void 0 ? _a : this.defaultColumnsMinWidth * column.colSpan;
}
}
Object.defineProperty(TableHeaderDirective, "\u0275fac", {
enumerable: true,
configurable: true,
writable: true,
value: i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: TableHeaderDirective, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive })
});
Object.defineProperty(TableHeaderDirective, "\u0275dir", {
enumerable: true,
configurable: true,
writable: true,
value: i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.16", type: TableHeaderDirective, selector: "lf-table-header, [lfTableHeader]", inputs: { defaultColumnsMinWidth: "defaultColumnsMinWidth" }, providers: [
{ provide: TableColumnContainer, useExisting: TableHeaderDirective },
], exportAs: ["lfTableHeader"], usesInheritance: true, ngImport: i0 })
});
__decorate([
observable
], TableHeaderDirective.prototype, "defaultColumnsMinWidth", void 0);
__decorate([
computed
], TableHeaderDirective.prototype, "numberOfRows", null);
__decorate([
computed
], TableHeaderDirective.prototype, "numberOfColumns", null);
__decorate([
computed
], TableHeaderDirective.prototype, "rows", null);
__decorate([
computed
], TableHeaderDirective.prototype, "tableMinWidth", null);
__decorate([
computed
], TableHeaderDirective.prototype, "tableMaxWidth", null);
__decorate([
computed
], TableHeaderDirective.prototype, "columnWidths", null);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: TableHeaderDirective, decorators: [{
type: Directive,
args: [{
selector: 'lf-table-header, [lfTableHeader]',
exportAs: 'lfTableHeader',
providers: [
{ provide: TableColumnContainer, useExisting: TableHeaderDirective },
],
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { defaultColumnsMinWidth: [{
type: Input
}], numberOfRows: [], numberOfColumns: [], rows: [], tableMinWidth: [], tableMaxWidth: [], columnWidths: [] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtaGVhZGVyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tb2R1bGVzL3RhYmxlLWhlYWRlci90YWJsZS1oZWFkZXIuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFjLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0QyxPQUFPLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUVwRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7QUFHaEU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNERztBQVFILE1BQU0sT0FBTyxvQkFBcUIsU0FBUSxvQkFBb0I7SUFRNUQsWUFBc0IsVUFBc0I7UUFDMUMsS0FBSyxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQzs7Ozs7bUJBREo7O1FBUHRCOztXQUVHO1FBR0g7Ozs7bUJBQWdDLEdBQUc7V0FBQyxDQUFDLGVBQWU7UUFJbEQsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7SUFFRDs7OztPQUlHO0lBRUgsSUFBVyxZQUFZO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7O09BSUc7SUFFSCxJQUFXLGVBQWU7UUFDeEIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7Ozs7O09BTUc7SUFFSCxJQUFXLElBQUk7UUFDYixNQUFNLElBQUksR0FBNkIsRUFBRSxDQUFDO1FBQzFDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFF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QW9CO2tCQVBoQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxrQ0FBa0M7b0JBQzVDLFFBQVEsRUFBRSxlQUFlO29CQUN6QixTQUFTLEVBQUU7d0JBQ1QsRUFBRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxzQkFBc0IsRUFBRTtxQkFDckU7aUJBQ0Y7aUdBT1Esc0JBQXNCO3NCQUQ1QixLQUFLO2dCQWNLLFlBQVksTUFVWixlQUFlLE1BWWYsSUFBSSxNQWdCSixhQUFhLE1BZWIsYUFBYSxNQWViLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUsIEVsZW1lbnRSZWYsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc0FycmF5TGlrZSB9IGZyb20gJ0BsaWdodHdlaWdodGZvcm0vc3RvcmFnZSc7XG5pbXBvcnQgeyBtYWtlT2JzZXJ2YWJsZSB9IGZyb20gJ21vYngnO1xuaW1wb3J0IHsgY29tcHV0ZWQsIG9ic2VydmFibGUgfSBmcm9tICdtb2J4LWFuZ3VsYXInO1xuXG5pbXBvcnQgeyBUYWJsZUNvbHVtbkNvbnRhaW5lciB9IGZyb20gJy4vdGFibGUtY29sdW1uLWNvbnRhaW5lcic7XG5pbXBvcnQgeyBUYWJsZUNvbHVtbkRpcmVjdGl2ZSB9IGZyb20gJy4vdGFibGUtY29sdW1uLmRpcmVjdGl2ZSc7XG5cbi8qKlxuICogRGlyZWN0aXZlIHVzZWQgdG8gc2ltcGxpZnkgdGhlIGNyZWF0aW9uIG9mIHRhYmxlIGhlYWRlcnMgYW5kIG1hbmFnZSB0aGUgc2l6ZVxuICogb2YgYSB0YWJsZSdzIG1heCB3aWR0aCwgbWluIHdpZHRoLCBhbmQgYWxsIGNvbHVtbnMuIFRhYmxlcyB1c2luZyB0aGVzZVxuICogZnVuY3Rpb25hbGl0aWVzIHNob3VsZCBoYXZlIHRoZWlyIGB0YWJsZS1sYXlvdXRgIENTUyBwcm9wZXJ0eSBzZXQgdG8gYGZpeGVkYC5cbiAqXG4gKiBUaGlzIGRpcmVjdGl2ZSBwcm92aWRlcyB1dGlsaXRpZXMgdG8gdHJhbnNmb3JtIHRoZSBmb2xsb3dpbmc6XG4gKiBgYGBodG1sXG4gKiA8bGYtdGFibGUtaGVhZGVyPlxuICogICA8bGYtdGFibGUtY29sdW1uIGlkPVwiaWRcIiBbZml4ZWRdPVwidHJ1ZVwiIFttaW5XaWR0aF09XCI0MFwiPjwvbGYtdGFibGUtY29sdW1uPlxuICogICA8bGYtdGFibGUtY29sdW1uIGlkPVwibmFtZVwiPlxuICogICAgIDxsZi10YWJsZS1jb2x1bW4gaWQ9XCJmaXJzdFwiPjwvbGYtdGFibGUtY29sdW1uPlxuICogICAgIDxsZi10YWJsZS1jb2x1bW4gaWQ9XCJsYXN0XCI+PC9sZi10YWJsZS1jb2x1bW4+XG4gKiAgIDwvbGYtdGFibGUtY29sdW1uPlxuICogICA8bGYtdGFibGUtY29sdW1uIGlkPVwiYWdlXCI+PC9sZi10YWJsZS1jb2x1bW4+XG4gKiA8L2xmLXRhYmxlLWhlYWRlcj5cbiAqIGBgYFxuICogSW50byBhIHRhYmxlIGhlYWRlciBzaW1pbGFyIHRvIHRoZSBmb2xsb3dpbmcgZGlhZ3JhbSwgd2hlcmUgdGhlIGBpZGAgY29sdW1uXG4gKiBoYXMgYSBmaXhlZCBzaXplIGFuZCB0aGUgcmVtYWluaW5nIGNvbHVtbnMgZXhwYW5kICh3aXRoIHNpbWlsYXIgd2lkdGgpIHRvIHRoZVxuICogdGFibGUncyB3aWR0aC5cbiAqIGBgYFxuICogfCAgICB8ICAgICAgICAgbmFtZSAgICAgICAgfCAgICAgICAgICB8XG4gKiB8IGlkIHwtLS0tLS0tLS0tLS0tLS0tLS0tLS18ICAgIGFnZSAgIHxcbiAqIHwgICAgfCAgIGZpcnN0ICB8ICAgbGFzdCAgIHwgICAgICAgICAgfFxuICogYGBgXG4gKlxuICogVGhlIGRpcmVjdGl2ZSBwcm92aWRlcyB1dGlsaXRpZXMgdG8gaGVscCBhIHRhYmxlIHNldCBpdHMgbWluaW11bSBhbmQgbWF4aW11bVxuICogd2lkdGhzLCBhcyB3ZWxsIGFzIGNvbHVtbiBzaXplcyAodXNpbmcgYDxjb2xncm91cD5gKSB3aGVuIG5lY2Vzc2FyeS4gVGhlXG4gKiBmb2xsb3dpbmcgZXhhbXBsZSBzaG93cyB0aGUgY3JlYXRpb24gb2YgYSB0YWJsZSB0aGF0IHVzZXMgYW4gaW5zdGFuY2Ugb2YgdGhpc1xuICogZGlyZWN0aXZlIChuYW1lZCBgaGVhZGVyYCkgdG8gbWFuYWdlIHdpZHRoIGFuZCBjb2x1bW4gc2l6ZXMuIFRoZSBleGFtcGxlXG4gKiBhc3N1bWVzIHRoYXQgdGhlIHRhYmxlJ3MgYHRhYmxlLWxheW91dGAgQ1NTIHByb3BlcnR5IGlzIHNldCB0byBgZml4ZWRgOlxuICogYGBgaHRtbFxuICogPHRhYmxlXG4gKiAgIFtzdHlsZS5taW5XaWR0aF09XCJoZWFkZXIudGFibGVNaW5XaWR0aCArICdweCdcIlxuICogICBbc3R5bGUubWF4V2lkdGhdPVwiaGVhZGVyLnRhYmxlTWF4V2lkdGggKyAncHgnXCJcbiAqID5cbiAqICAgPGNvbGdyb3VwPlxuICogICAgIDxjb2wgKm5nRm9yPVwibGV0IHdpZHRoIG9mIGhlYWRlci5jb2x1bW5XaWR0aHNcIiBbYXR0ci53aWR0aF09XCJ3aWR0aFwiLz5cbiAqICAgPC9jb2xncm91cD5cbiAqXG4gKiAgIDx0aGVhZD5cbiAqICAgICA8dHIgKm5nRm9yPVwibGV0IHJvdyBvZiBoZWFkZXIucm93c1wiPlxuICogICAgICAgPHRoXG4gKiAgICAgICAgICpuZ0Zvcj1cImxldCBjb2x1bW4gb2Ygcm93XCJcbiAqICAgICAgICAgW2F0dHIucm93U3Bhbl09XCJjb2x1bW4ucm93U3BhblwiXG4gKiAgICAgICAgIFthdHRyLmNvbFNwYW5dPVwiY29sdW1uLmNvbFNwYW5cIlxuICogICAgICAgPlxuICogICAgICAgICB7eyBjb2x1bW4uaWQgfX0gPCEtLSBDYW4gYmUgdXNlZCB0byBmZXRjaCBhIGxhYmVsLCBmb3IgZXhhbXBsZSAtLT5cbiAqICAgICAgIDwvdGg+XG4gKiAgICAgPC90cj5cbiAqICAgPC90aGVhZD5cbiAqXG4gKiAgIDx0Ym9keT48IS0tIC4uLiAtLT48L3Rib2R5PlxuICogPC90YWJsZT5cbiAqIGBgYFxuICovXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdsZi10YWJsZS1oZWFkZXIsIFtsZlRhYmxlSGVhZGVyXScsXG4gIGV4cG9ydEFzOiAnbGZUYWJsZUhlYWRlcicsXG4gIHByb3ZpZGVyczogW1xuICAgIHsgcHJvdmlkZTogVGFibGVDb2x1bW5Db250YWluZXIsIHVzZUV4aXN0aW5nOiBUYWJsZUhlYWRlckRpcmVjdGl2ZSB9LFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBUYWJsZUhlYWRlckRpcmVjdGl2ZSBleHRlbmRzIFRhYmxlQ29sdW1uQ29udGFpbmVyIHtcbiAgLyoqXG4gICAqIERlZmF1bHQgbWluIHdpZHRoIChpbiBgcHhgKSBvZiBjb2x1bW5zLlxuICAgKi9cbiAgQG9ic2VydmFibGVcbiAgQElucHV0KClcbiAgcHVibGljIGRlZmF1bHRDb2x1bW5zTWluV2lkdGggPSAxMDA7IC8vIFNhbmUgZGVmYXVsdFxuXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBlbGVtZW50UmVmOiBFbGVtZW50UmVmKSB7XG4gICAgc3VwZXIobnVsbCwgZWxlbWVudFJlZik7XG4gICAgbWFrZU9ic2VydmFibGUodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogVG90YWwgbnVtYmVyIG9mIHJvd3Mgb2YgdGhlIGhlYWRlciAoc2hvdWxkIG1hcCB0byB0aGUgbnVtYmVyIG9mIGA8dHI+YCBvZlxuICAgKiB0aGUgYWN0dWFsIGhlYWRlcikuXG4gICAqIEByZXR1cm5zIE51bWJlciBvZiByb3dzIG9mIHRoZSBoZWFkZXIuXG4gICAqL1xuICBAY29tcHV0ZWRcbiAgcHVibGljIGdldCBudW1iZXJPZlJvd3MoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5oZWlnaHQgLSAxO1xuICB9XG5cbiAgLyoqXG4gICAqIE51bWJlciBvZiAobGVhZikgY29sdW1ucyBvZiB0aGUgaGVhZGVyIChudW1iZXIgb2YgY29sdW1ucyBhY3R1YWxseVxuICAgKiByZXByZXNlbnRpbmcgdGFibGUgY2VsbHMvdGhhdCBkb24ndCBoYXZlIHN1Yi1jb2x1bW5zKS5cbiAgICogQHJldHVybnMgTnVtYmVyIG9mIGxlYWYgY29sdW1ucyBvZiB0aGUgaGVhZGVyLlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIHB1YmxpYyBnZXQgbnVtYmVyT2ZDb2x1bW5zKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMud2lkdGg7XG4gIH1cblxuICAvKipcbiAgICogTGlzdCBvZiByb3dzIG9mIHRoZSBoZWFkZXIsIHdoZXJlIGVhY2ggcm93IGNvbnRhaW5zIGEgbGlzdCBvZiBpdHMgY29sdW1ucy5cbiAgICogVGhpcyBzaG91bGQgZGlyZWN0bHkgbWFwIGVhY2ggcm93IHRvIGEgYDx0cj5gIG9mIHRoZSBoZWFkZXIsIGFuZCBlYWNoXG4gICAqIGNvbHVtbiB0byBhIGA8dGg+YC4gRm9yIHRoZSBleGFtcGxlIGRlcGljdGVkIGluIHRoZSBjbGFzcyBkZXNjcmlwdGlvbiwgdGhpc1xuICAgKiBtZXRob2Qgd291bGQgcmV0dXJuOiBgW1tpZCwgbmFtZSwgYWdlXSwgW2ZpcnN0LCBsYXN0XV1gLlxuICAgKiBAcmV0dXJucyBMaXN0IG9mIHJvd3MsIHdoZXJlIGVhY2ggcm93IGlzIGEgbGlzdCBvZiBjb2x1bW5zLlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIHB1YmxpYyBnZXQgcm93cygpOiBUYWJsZUNvbHVtbkRpcmVjdGl2ZVtdW10ge1xuICAgIGNvbnN0IHJvd3M6IFRhYmxlQ29sdW1uRGlyZWN0aXZlW11bXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5udW1iZXJPZlJvd3M7ICsraSkge1xuICAgICAgcm93cy5wdXNoKHRoaXMuY29sdW1uc09mUm93KGkpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJvd3M7XG4gIH1cblxuICAvKipcbiAgICogTWluaW11bSB3aWR0aCAoaW4gcGl4ZWxzKSB0aGF0IHNob3VsZCBiZSBzZXQgb24gdGhlIHRhYmxlIHRoYXQgY29udGFpbnNcbiAgICogdGhpcyBoZWFkZXIuIElmIHRoZSB0YWJsZSBkb2VzIG5vdCBoYXZlIGEgbWluIHdpZHRoLCB0aGVuIHRoZSBjb2x1bW5zIHdpbGxcbiAgICogY29sbGFwc2UgaW5kZWZpbml0ZWx5LCB3ZSB0aHVzIHByb3ZpZGUgYSBtaW5pbXVtIHdpZHRoIHRoYXQgYW1vdW50cyB0byB0aGVcbiAgICogc3VtIG9mIHRoZSBtaW5pbXVtIHdpZHRoIG9mIGFsbCBjb2x1bW5zLlxuICAgKiBAcmV0dXJucyBNaW5pbXVtIHdpZHRoIChpbiBwaXhlbHMpIHRoYXQgc2hvdWxkIGJlIHNldCBvbiB0aGUgdGFibGUuXG4gICAqL1xuICBAY29tcHV0ZWRcbiAgcHVibGljIGdldCB0YWJsZU1pbldpZHRoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMubGVhZkNvbHVtbnMoKS5yZWR1Y2UoXG4gICAgICAoc3VtLCBjb2x1bW4pID0+IHN1bSArIHRoaXMuY29sdW1uTWluV2lkdGgoY29sdW1uKSxcbiAgICAgIDBcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIE1heGltdW0gd2lkdGggKGluIHBpeGVscykgdGhhdCBzaG91bGQgYmUgc2V0IG9uIHRoZSB0YWJsZSB0aGF0IGNvbnRhaW5zXG4gICAqIHRoaXMgaGVhZGVyLiBUYWJsZXMgd2hlcmUgYWxsIHRoZSBjb2x1bW5zIGhhdmUgYSBmaXhlZCB3aWR0aCBjYW5ub3QgZXZlclxuICAgKiBleHBhbmQsIGZvciB0aGF0IHdlIG11c3Qgc2V0IGEgbWF4IHdpZHRoIG9uIHRoZSB0YWJsZSwgb3RoZXJ3aXNlIHRoaXNcbiAgICogbWV0aG9kIHJldHVybnMgYEluZmluaXR5YC5cbiAgICogQHJldHVybnMgTWF4aW11bSB3aWR0aCAoaW4gcGl4ZWxzKSB0aGF0IHNob3VsZCBiZSBzZXQgb24gdGhlIHRhYmxlLlxuICAgKi9cbiAgQGNvbXB1dGVkXG4gIHB1YmxpYyBnZXQgdGFibGVNYXhXaWR0aCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmxlYWZDb2x1bW5zKCkuZXZlcnkoKGNvbHVtbikgPT4gY29sdW1uLmZpeGVkKVxuICAgICAgPyB0aGlzLnRhYmxlTWluV2lkdGhcbiAgICAgIDogSW5maW5pdHk7XG4gIH1cblxuICAvKipcbiAgICogV2lkdGggZm9yIGFsbCB0YWJsZSBjb2x1bW5zLCBhcyB0aGV5IHNob3VsZCBiZSBzZXQgaW4gQ1NTIChzdHJpbmdzIGVuZGluZ1xuICAgKiBpbiBgJ3B4J2Agb3IgYCclJ2AgZGVwZW5kaW5nIG9uIHdoZXRoZXIgdGhlIGNvbHVtbiBpcyBmaXhlZCkuIEVhY2ggb2YgdGhlc2VcbiAgICogd2lkdGhzIHNob3VsZCBiZSBwdXQgb24gYSBgPGNvbD5gIGVsZW1lbnQgaW5zaWRlIGEgYDxjb2xncm91cD5gIGJlZm9yZSB0aGVcbiAgICogZGVmaW5pdGlvbiBvZiB0aGUgYDx0aGVhZD5gIHdpdGhpbiBhIGA8dGFibGU+YCB3aXRoIHRoZSBgdGFibGUtbGF5b3V0YCBDU1NcbiAgICogcHJvcGVydHkgc2V0IHRvIGBmaXhlZGBcbiAgICogQHJldHVybnMgTGlzdCBvZiB3aWR0aHMgb2YgZWFjaCBsZWFmIGNvbHVtbi5cbiAgICovXG4gIEBjb21wdXRlZFxuICBwdWJsaWMgZ2V0IGNvbHVtbldpZHRocygpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgbGVhdmVzID0gdGhpcy5sZWFmQ29sdW1ucygpO1xuICAgIC8vIENvbHVtbnMgbm90IHNldCBhcyBgZml4ZWRgIHNob3VsZCBleHBhbmQgYXMgbmVjZXNzYXJ5LCBhcyBzdWNoIHdlIHByb3ZpZGVcbiAgICAvLyB0aGVtIHdpdGggd2lkdGhzIHRoYXQgdG9nZXRoZXIgYWRkIHVwIHRvIGAxMDAlYFxuICAgIGNvbnN0IGR5bmFtaWNNaW5XaWR0aFN1bSA9IGxlYXZlcy5yZWR1Y2UoXG4gICAgICAoc3VtLCBjb2x1bW4pID0+IHN1bSArIChjb2x1bW4uZml4ZWQgPyAwIDogdGhpcy5jb2x1bW5NaW5XaWR0aChjb2x1bW4pKSxcbiAgICAgIDBcbiAgICApO1xuICAgIHJldHVybiBsZWF2ZXMucmVkdWNlKChhcnJheTogc3RyaW5nW10sIGNvbHVtbikgPT4ge1xuICAgICAgY29uc3QgY29sU3BhbiA9IGNvbHVtbi5jb2xTcGFuID8/IDE7XG4gICAgICAvLyBEZXRlcm1pbmUgdGhlIHdpZHRocyBvZiBlYWNoIGNvbHVtbiBiZWluZyBzcGFubmVkIGJ5IGBjb2x1bW5gXG4gICAgICBjb25zdCBjb2xNaW5XaWR0aEFycmF5ID0gaXNBcnJheUxpa2UoY29sdW1uLm1pbldpZHRoKVxuICAgICAgICA/IGNvbHVtbi5taW5XaWR0aFxuICAgICAgICA6IC8vIERpc3RyaWJ1dGUgdGhlIHdpZHRoIGFtb25nc3QgdGhlIGNvbHVtbnMgYmVpbmcgc3Bhbm5lZFxuICAgICAgICAgIFsuLi5BcnJheShjb2xTcGFuKV0ubWFwKCgpID0+IHRoaXMuY29sdW1uTWluV2lkdGgoY29sdW1uKSAvIGNvbFNwYW4pO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2xTcGFuOyArK2kpIHtcbiAgICAgICAgLy8gQ29sdW1ucyB3aWxsIGVuZCB1cCB3aXRoIGEgd2lkdGggb2YgYDBgIHdoZW4gYSBgbWluV2lkdGhgIGFycmF5IGlzXG4gICAgICAgIC8vIHByb3ZpZGVkIHdpdGggbGVuZ3RoIHNtYWxsZXIgdGhhbiBgY29sU3BhbmBcbiAgICAgICAgY29uc3QgY29sTWluV2lkdGggPSBjb2xNaW5XaWR0aEFycmF5W2ldID8/IDA7XG4gICAgICAgIGFycmF5LnB1c2goXG4gICAgICAgICAgY29sdW1uLmZpeGVkXG4gICAgICAgICAgICA/IGAke2NvbE1pbldpZHRofXB4YFxuICAgICAgICAgICAgOiBgJHsoY29sTWluV2lkdGggLyBkeW5hbWljTWluV2lkdGhTdW0pICogMTAwfSVgXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJyYXk7XG4gICAgfSwgW10pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0aGF0IHJldHVybnMgdGhlIGxpc3Qgb2YgbGVhZiBjb2x1bW5zOiBjb2x1bW5zIHdob3NlIGxhYmVsIGRpcmVjdGx5XG4gICAqIHJlcHJlc2VudHMgYSB0YWJsZSBjZWxsL2NvbHVtbnMgdGhhdCBjb250YWluIG5vIHN1Yi1jb2x1bW5zLiBGb3IgdGhlXG4gICAqIGV4YW1wbGUgZGVwaWN0ZWQgaW4gdGhlIGNsYXNzIGRlc2NyaXB0aW9uLCB0aGlzIG1ldGhvZCB3b3VsZCByZXR1cm46XG4gICAqIGBbaWQsIGZpcnN0LCBsYXN0LCBhZ2VdYC5cbiAgICogQHBhcmFtIGNvbHVtbkNvbnRhaW5lciBGb3IgaW50ZXJuYWwgdXNlIG9ubHkgKHRvIHJlY3Vyc2Ugb3ZlciBjb2x1bW5zKS5cbiAgICogQHJldHVybnMgTGlzdCBvZiBjb2x1bW5zIHRoYXQgYXJlIGxlYXZlcy5cbiAgICovXG4gIHByaXZhdGUgbGVhZkNvbHVtbnMoXG4gICAgY29sdW1uQ29udGFpbmVyOiBUYWJsZUNvbHVtbkNvbnRhaW5lciA9IHRoaXNcbiAgKTogVGFibGVDb2x1bW5EaXJlY3RpdmVbXSB7XG4gICAgcmV0dXJuIGNvbHVtbkNvbnRhaW5lci5jaGlsZHJlbkNvbHVtbnMucmVkdWNlKFxuICAgICAgKGxlYXZlczogYW55LCBjb2x1bW4pID0+XG4gICAgICAgIGxlYXZlcy5jb25jYXQoXG4gICAgICAgICAgY29sdW1uLmNoaWxkcmVuQ29sdW1ucy5sZW5ndGggPT09IDBcbiAgICAgICAgICAgID8gW2NvbHVtbl1cbiAgICAgICAgICAgIDogdGhpcy5sZWFmQ29sdW1ucyhjb2x1bW4pXG4gICAgICAgICksXG4gICAgICBbXVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRoYXQgcmV0dXJucyB0aGUgbGlzdCBvZiBjb2x1bW5zIG9mIGEgZ2l2ZW4gcm93IChgPHRyPmApIG9mIHRoZVxuICAgKiB0YWJsZSBoZWFkZXIuIEZvciB0aGUgZXhhbXBsZSBkZXBpY3RlZCBpbiB0aGUgY2xhc3MgZGVzY3JpcHRpb24sIGZvciByb3dcbiAgICogYDBgIHRoaXMgbWV0aG9kIHdvdWxkIHJldHVybiBgW2lkLCBuYW1lLCBhZ2VdYDsgZm9yIHJvdyBgMWAgaXQgd291bGQgcmV0dXJuXG4gICAqIGBbZmlyc3QsIGxhc3RdYC5cbiAgICogQHBhcmFtIGluZGV4IEluZGV4IG9mIHJvdyBmcm9tIHdoaWNoIHRvIGZldGNoIGNvbHVtbnMuXG4gICAqIEBwYXJhbSBjb2x1bW5Db250YWluZXIgRm9yIGludGVybmFsIHVzZSBvbmx5ICh0byByZWN1cnNlIG92ZXIgY29sdW1ucykuXG4gICAqIEByZXR1cm5zIExpc3Qgb2YgY29sdW1ucyBvZiByb3cgd2l0aCBpbmRleCBgaW5kZXhgLlxuICAgKi9cbiAgcHJpdmF0ZSBjb2x1bW5zT2ZSb3coXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBjb2x1bW5Db250YWluZXI6IFRhYmxlQ29sdW1uQ29udGFpbmVyID0gdGhpc1xuICApOiBUYWJsZUNvbHVtbkRpcmVjdGl2ZVtdIHtcbiAgICByZXR1cm4gaW5kZXggPT09IDBcbiAgICAgID8gY29sdW1uQ29udGFpbmVyLmNoaWxkcmVuQ29sdW1uc1xuICAgICAgOiBjb2x1bW5Db250YWluZXIuY2hpbGRyZW5Db2x1bW5zLnJlZHVjZShcbiAgICAgICAgICAocm93Q29sdW1uczogYW55LCBjb2x1bW4pID0+XG4gICAgICAgICAgICByb3dDb2x1bW5zLmNvbmNhdCh0aGlzLmNvbHVtbnNPZlJvdyhpbmRleCAtIDEsIGNvbHVtbikpLFxuICAgICAgICAgIFtdXG4gICAgICAgICk7XG4gIH1cblxuICAvKipcbiAgICogTWluaW11bSB3aWR0aCBvZiBhIGNvbHVtbiAob3IgYSBkZWZhdWx0IG1pbmltdW0gd2lkdGggd2hlbiBub25lIGhhcyBiZWVuXG4gICAqIGNyZWF0ZWQpLlxuICAgKiBAcGFyYW0gY29sdW1uIENvbHVtbiB3aG9zZSBtaW5pbXVtIHdpZHRoIHdlIGFyZSBpbnRlcmVzdGVkIGluLlxuICAgKiBAcmV0dXJucyBNaW5pbXVtIHdpZHRoIG9mIHRoZSBjb2x1bW4uXG4gICAqL1xuICBwcml2YXRlIGNvbHVtbk1pbldpZHRoKGNvbHVtbjogVGFibGVDb2x1bW5EaXJlY3RpdmUpOiBudW1iZXIge1xuICAgIHJldHVybiBpc0FycmF5TGlrZShjb2x1bW4ubWluV2lkdGgpXG4gICAgICA/IGNvbHVtbi5taW5XaWR0aC5yZWR1Y2UoKHN1bSwgd2lkdGgpID0+IHN1bSArIHdpZHRoLCAwKVxuICAgICAgOiBjb2x1bW4ubWluV2lkdGggPz8gdGhpcy5kZWZhdWx0Q29sdW1uc01pbldpZHRoICogY29sdW1uLmNvbFNwYW47XG4gIH1cbn1cbiJdfQ==