UNPKG

@lightweightform/theme-common

Version:

Common utilities for Lightweightform themes

254 lines 28 kB
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==