ngx-foldable
Version:
Angular library to help you build dual-screen experiences for foldable or dual-screen devices
246 lines • 25.3 kB
JavaScript
import { Directive, HostBinding, Input, } from '@angular/core';
import { ScreenSpanning } from './screen-spanning';
import * as i0 from "@angular/core";
import * as i1 from "./screen-context";
/**
* Enumeration of split layout modes values for use with
* {@link SplitLayoutDirective}.
*/
export const SplitLayoutMode = {
Flex: 'flex',
Grid: 'grid',
Absolute: 'absolute',
/**
* Checks if the given string value is a valid {@link SplitLayoutMode}.
*
* @param value The value to check.
* @return true if the value is a valid {@link SplitLayoutMode}.
*/
isValid: (value) => {
switch (value) {
case SplitLayoutMode.Flex:
case SplitLayoutMode.Grid:
case SplitLayoutMode.Absolute:
return true;
}
return false;
},
};
/**
* Enumeration of window order values for use with
* {@link SplitLayoutDirective}.
*/
export const WindowOrder = {
Normal: 'normal',
Reverse: 'reverse',
/**
* Checks if the given string value is a valid {@link WindowOrder}.
*
* @param value The value to check.
* @return true if the value is a valid {@link WindowOrder}.
*/
isValid: (value) => {
switch (value) {
case WindowOrder.Normal:
case WindowOrder.Reverse:
return true;
}
return false;
},
};
/**
* Enumeration of the text reading direction values.
*/
export const ReadingDirection = {
LeftToRight: 'ltr',
RightToLeft: 'rtl',
};
/**
* Look 'ma, CSS-in-JS with Angular! ಠ_ಠ
*
* @ignore
*/
const layoutStyles = {
[SplitLayoutMode.Flex]: {
common: {
display: 'flex',
justifyContent: 'space-between',
height: 'env(viewport-segment-bottom 0 1)',
},
[ScreenSpanning.DualHorizontal]: {
flexDirection: 'row',
},
[ScreenSpanning.DualVertical]: {
flexDirection: 'column',
},
[WindowOrder.Reverse]: {
flexDirection: 'column-reverse',
},
},
[SplitLayoutMode.Grid]: {
common: {
display: 'grid',
height: 'env(viewport-segment-bottom 0 1)',
},
[ScreenSpanning.DualHorizontal]: {
gridTemplateColumns: '1fr 1fr',
gridTemplateAreas: '"segment0 segment1"',
gridAutoFlow: 'row',
columnGap: 'calc(env(viewport-segment-left 1 0) - env(viewport-segment-right 0 0))',
},
[ScreenSpanning.DualVertical]: {
gridTemplateRows: '1fr 1fr',
gridTemplateAreas: '"segment0" "segment1"',
gridAutoFlow: 'row',
rowGap: 'calc(env(viewport-segment-top 0 1) - env(viewport-segment-bottom 0 0))',
},
[WindowOrder.Reverse]: {
gridTemplateRows: '1fr 1fr',
gridTemplateAreas: '"segment0" "segment1"',
gridAutoFlow: 'row',
rowGap: 'calc(env(viewport-segment-top 0 1) - env(viewport-segment-bottom 0 0))',
},
},
[SplitLayoutMode.Absolute]: {
common: {
position: 'relative',
height: 'env(viewport-segment-bottom 0 1)',
},
[ScreenSpanning.DualHorizontal]: {},
[ScreenSpanning.DualVertical]: {},
[WindowOrder.Reverse]: {},
},
};
/**
* Defines a parent layout container for creating a split layout on multi
* screen devices.
*
* When used on a single screen device, no layout change (CSS) is added.
* You can choose between different {@link SplitLayoutMode} to suit your
* design.
*
* This directive should be used along with {@link WindowDirective}.
*
* @example
* <div fdSplitLayout="grid">
* <section fdWindow="0">Will be displayed on first screen</section>
* <section fdWindow="1">Will be displayed on second screen (if available)</section>
* </div>
*
* In addition, you can also choose keep the same window segments order or
* reverse it when the spanning mode change from vertical to horizontal using
* a second optional parameter on the directive:
*
* @example
* <div fdSplitLayout="flex reverse">
* <section fdWindow="0">
* Will be displayed on first screen in vertical spanning mode
* and on the second screen in horizontal spanning mode.
* </section>
* <section fdWindow="1">
* Will be displayed on second screen in vertical spanning mode
* and on the first screen in horizontal spanning mode.
* </section>
* </div>
*/
export class SplitLayoutDirective {
constructor(element, screenContext) {
this.element = element;
this.screenContext = screenContext;
this.mode = SplitLayoutMode.Flex;
this.order = WindowOrder.Normal;
this.layoutStyle = {};
this.screenContextSubscription = null;
this.direction = 'ltr';
this.updateStyle();
this.screenContextSubscription = this.screenContext
.asObservable()
.subscribe(() => this.updateStyle());
}
/**
* Sets the current split layout options to use when multi screen is
* detected.
*
* @param options The split layout options to use.
* Format: `[mode] [order]`
* - The {@link SplitLayoutMode} to use (default is {@link SplitLayoutMode.Flex}).
* - The {@link WindowOrder} to use (default is {@link WindowOrder.Normal}).
*/
set fdSplitLayout(options) {
this.parseOptions(options || '');
this.updateStyle();
}
/** @ignore */
get style() {
return this.layoutStyle;
}
/**
* The current split layout mode to use when multi screen is detected.
*
* @return The current split layout mode.
*/
get layoutMode() {
return this.mode;
}
/**
* The window segments order to use when in horizontal spanning mode.
*
* @return The current window order.
*/
get windowOrder() {
return this.order;
}
/**
* The text reading direction for the host element.
*
* @return The text reading direction.
*/
get readingDirection() {
return this.direction;
}
/** @ignore */
ngOnDestroy() {
if (this.screenContextSubscription !== null) {
this.screenContextSubscription.unsubscribe();
}
}
parseOptions(options) {
let [mode, order] = options.trim().split(' ');
mode = SplitLayoutMode.isValid(mode) ? mode : SplitLayoutMode.Flex;
order = WindowOrder.isValid(order) ? order : WindowOrder.Normal;
this.mode = mode;
this.order = order;
}
updateStyle() {
const isMultiScreen = this.screenContext.isMultiScreen;
const spanning = this.screenContext.screenSpanning;
const reverse = spanning === ScreenSpanning.DualVertical &&
this.order === WindowOrder.Reverse;
this.direction =
getComputedStyle(this.element.nativeElement)
?.direction || ReadingDirection.LeftToRight;
if (isMultiScreen && spanning !== ScreenSpanning.None) {
this.layoutStyle = {
...layoutStyles[this.mode].common,
...layoutStyles[this.mode][reverse ? WindowOrder.Reverse : spanning],
};
}
else {
this.layoutStyle = {};
}
}
}
SplitLayoutDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: SplitLayoutDirective, deps: [{ token: i0.ElementRef }, { token: i1.ScreenContext }], target: i0.ɵɵFactoryTarget.Directive });
SplitLayoutDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.1", type: SplitLayoutDirective, selector: "[fdSplitLayout]", inputs: { fdSplitLayout: "fdSplitLayout" }, host: { properties: { "style": "this.style" } }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.1", ngImport: i0, type: SplitLayoutDirective, decorators: [{
type: Directive,
args: [{
selector: '[fdSplitLayout]',
}]
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.ScreenContext }]; }, propDecorators: { fdSplitLayout: [{
type: Input
}], style: [{
type: HostBinding,
args: ['style']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BsaXQtbGF5b3V0LmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2xpYi9zcmMvY29yZS9zcGxpdC1sYXlvdXQuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBRVQsV0FBVyxFQUNYLEtBQUssR0FFTixNQUFNLGVBQWUsQ0FBQztBQUl2QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7OztBQVFuRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUc7SUFDN0IsSUFBSSxFQUFFLE1BQXlCO0lBQy9CLElBQUksRUFBRSxNQUF5QjtJQUMvQixRQUFRLEVBQUUsVUFBNkI7SUFFdkM7Ozs7O09BS0c7SUFDSCxPQUFPLEVBQUUsQ0FBQyxLQUFhLEVBQVcsRUFBRTtRQUNsQyxRQUFRLEtBQUssRUFBRTtZQUNiLEtBQUssZUFBZSxDQUFDLElBQUksQ0FBQztZQUMxQixLQUFLLGVBQWUsQ0FBQyxJQUFJLENBQUM7WUFDMUIsS0FBSyxlQUFlLENBQUMsUUFBUTtnQkFDM0IsT0FBTyxJQUFJLENBQUM7U0FDZjtRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztDQUNGLENBQUM7QUFRRjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUc7SUFDekIsTUFBTSxFQUFFLFFBQXVCO0lBQy9CLE9BQU8sRUFBRSxTQUF3QjtJQUVqQzs7Ozs7T0FLRztJQUNILE9BQU8sRUFBRSxDQUFDLEtBQWEsRUFBVyxFQUFFO1FBQ2xDLFFBQVEsS0FBSyxFQUFFO1lBQ2IsS0FBSyxXQUFXLENBQUMsTUFBTSxDQUFDO1lBQ3hCLEtBQUssV0FBVyxDQUFDLE9BQU87Z0JBQ3RCLE9BQU8sSUFBSSxDQUFDO1NBQ2Y7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7Q0FDRixDQUFDO0FBTUY7O0dBRUc7QUFDSCxNQUFN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USxLQUFLLGNBQWMsQ0FBQyxZQUFZO1lBQ3hDLElBQUksQ0FBQyxLQUFLLEtBQUssV0FBVyxDQUFDLE9BQU8sQ0FBQztRQUVyQyxJQUFJLENBQUMsU0FBUztZQUNYLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDO2dCQUMzQyxFQUFFLFNBQThCLElBQUksZ0JBQWdCLENBQUMsV0FBVyxDQUFDO1FBRXJFLElBQUksYUFBYSxJQUFJLFFBQVEsS0FBSyxjQUFjLENBQUMsSUFBSSxFQUFFO1lBQ3JELElBQUksQ0FBQyxXQUFXLEdBQUc7Z0JBQ2pCLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNO2dCQUNqQyxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7YUFDckUsQ0FBQztTQUNIO2FBQU07WUFDTCxJQUFJLENBQUMsV0FBVyxHQUFHLEVBQUUsQ0FBQztTQUN2QjtJQUNILENBQUM7O2lIQW5HVSxvQkFBb0I7cUdBQXBCLG9CQUFvQjsyRkFBcEIsb0JBQW9CO2tCQUhoQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxpQkFBaUI7aUJBQzVCOzZIQWtCSyxhQUFhO3NCQURoQixLQUFLO2dCQVFGLEtBQUs7c0JBRFIsV0FBVzt1QkFBQyxPQUFPIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgRGlyZWN0aXZlLFxuICBFbGVtZW50UmVmLFxuICBIb3N0QmluZGluZyxcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTYWZlU3R5bGUgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgU2NyZWVuQ29udGV4dCB9IGZyb20gJy4vc2NyZWVuLWNvbnRleHQnO1xuaW1wb3J0IHsgU2NyZWVuU3Bhbm5pbmcgfSBmcm9tICcuL3NjcmVlbi1zcGFubmluZyc7XG5cbi8qKlxuICogRGVmaW5lcyBob3cgdGhlIHNwbGl0IGxheW91dCBjb250YWluZXIgc2hvdWxkIGJlIHJlbmRlcmVkIHdoZW4gbXVsdGkgc2NyZWVuXG4gKiBpcyBkZXRlY3RlZC5cbiAqIFNlZSB7QGxpbmsgU3BsaXRMYXlvdXREaXJlY3RpdmV9XG4gKi9cbmV4cG9ydCB0eXBlIFNwbGl0TGF5b3V0TW9kZSA9ICdmbGV4JyB8ICdncmlkJyB8ICdhYnNvbHV0ZSc7XG4vKipcbiAqIEVudW1lcmF0aW9uIG9mIHNwbGl0IGxheW91dCBtb2RlcyB2YWx1ZXMgZm9yIHVzZSB3aXRoXG4gKiB7QGxpbmsgU3BsaXRMYXlvdXREaXJlY3RpdmV9LlxuICovXG5leHBvcnQgY29uc3QgU3BsaXRMYXlvdXRNb2RlID0ge1xuICBGbGV4OiAnZmxleCcgYXMgU3BsaXRMYXlvdXRNb2RlLFxuICBHcmlkOiAnZ3JpZCcgYXMgU3BsaXRMYXlvdXRNb2RlLFxuICBBYnNvbHV0ZTogJ2Fic29sdXRlJyBhcyBTcGxpdExheW91dE1vZGUsXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gc3RyaW5nIHZhbHVlIGlzIGEgdmFsaWQge0BsaW5rIFNwbGl0TGF5b3V0TW9kZX0uXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gICAqIEByZXR1cm4gdHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYSB2YWxpZCB7QGxpbmsgU3BsaXRMYXlvdXRNb2RlfS5cbiAgICovXG4gIGlzVmFsaWQ6ICh2YWx1ZTogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gICAgc3dpdGNoICh2YWx1ZSkge1xuICAgICAgY2FzZSBTcGxpdExheW91dE1vZGUuRmxleDpcbiAgICAgIGNhc2UgU3BsaXRMYXlvdXRNb2RlLkdyaWQ6XG4gICAgICBjYXNlIFNwbGl0TGF5b3V0TW9kZS5BYnNvbHV0ZTpcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcbn07XG5cbi8qKlxuICogRGVmaW5lcyBob3cgdGhlIHNwbGl0IGxheW91dCBjb250YWluZXIgc2hvdWxkIG9yZGVyIHRoZSB3aW5kb3cgc2VnbWVudHNcbiAqIHdoZW4gaW4gaG9yaXpvbnRhbCBzcGFubmluZyBtb2RlIHZzIHZlcnRpY2FsIHNwYW5uaW5nIG1vZGUuXG4gKiBTZWUge0BsaW5rIFNwbGl0TGF5b3V0RGlyZWN0aXZlfVxuICovXG5leHBvcnQgdHlwZSBXaW5kb3dPcmRlciA9ICdub3JtYWwnIHwgJ3JldmVyc2UnO1xuLyoqXG4gKiBFbnVtZXJhdGlvbiBvZiB3aW5kb3cgb3JkZXIgdmFsdWVzIGZvciB1c2Ugd2l0aFxuICoge0BsaW5rIFNwbGl0TGF5b3V0RGlyZWN0aXZlfS5cbiAqL1xuZXhwb3J0IGNvbnN0IFdpbmRvd09yZGVyID0ge1xuICBOb3JtYWw6ICdub3JtYWwnIGFzIFdpbmRvd09yZGVyLFxuICBSZXZlcnNlOiAncmV2ZXJzZScgYXMgV2luZG93T3JkZXIsXG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gc3RyaW5nIHZhbHVlIGlzIGEgdmFsaWQge0BsaW5rIFdpbmRvd09yZGVyfS5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAgICogQHJldHVybiB0cnVlIGlmIHRoZSB2YWx1ZSBpcyBhIHZhbGlkIHtAbGluayBXaW5kb3dPcmRlcn0uXG4gICAqL1xuICBpc1ZhbGlkOiAodmFsdWU6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICAgIHN3aXRjaCAodmFsdWUpIHtcbiAgICAgIGNhc2UgV2luZG93T3JkZXIuTm9ybWFsOlxuICAgICAgY2FzZSBXaW5kb3dPcmRlci5SZXZlcnNlOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxufTtcblxuLyoqXG4gKiBEZWZpbmVzIHRoZSB0ZXh0IHJlYWRpbmcgZGlyZWN0aW9uIGZvciB0aGUgaG9zdCBlbGVtZW50LlxuICovXG5leHBvcnQgdHlwZSBSZWFkaW5nRGlyZWN0aW9uID0gJ2x0cicgfCAncnRsJztcbi8qKlxuICogRW51bWVyYXRpb24gb2YgdGhlIHRleHQgcmVhZGluZyBkaXJlY3Rpb24gdmFsdWVzLlxuICovXG5leHBvcnQgY29uc3QgUmVhZGluZ0RpcmVjdGlvbiA9IHtcbiAgTGVmdFRvUmlnaHQ6ICdsdHInIGFzIFJlYWRpbmdEaXJlY3Rpb24sXG4gIFJpZ2h0VG9MZWZ0OiAncnRsJyBhcyBSZWFkaW5nRGlyZWN0aW9uLFxufTtcblxuLyoqXG4gKiBMb29rICdtYSwgQ1NTLWluLUpTIHdpdGggQW5ndWxhciEg4LKgX+CyoFxuICpcbiAqIEBpZ25vcmVcbiAqL1xuY29uc3QgbGF5b3V0U3R5bGVzID0ge1xuICBbU3BsaXRMYXlvdXRNb2RlLkZsZXhdOiB7XG4gICAgY29tbW9uOiB7XG4gICAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgICBqdXN0aWZ5Q29udGVudDogJ3NwYWNlLWJldHdlZW4nLFxuICAgICAgaGVpZ2h0OiAnZW52KHZpZXdwb3J0LXNlZ21lbnQtYm90dG9tIDAgMSknLFxuICAgIH0sXG4gICAgW1NjcmVlblNwYW5uaW5nLkR1YWxIb3Jpem9udGFsXToge1xuICAgICAgZmxleERpcmVjdGlvbjogJ3JvdycsXG4gICAgfSxcbiAgICBbU2NyZWVuU3Bhbm5pbmcuRHVhbFZlcnRpY2FsXToge1xuICAgICAgZmxleERpcmVjdGlvbjogJ2NvbHVtbicsXG4gICAgfSxcbiAgICBbV2luZG93T3JkZXIuUmV2ZXJzZV06IHtcbiAgICAgIGZsZXhEaXJlY3Rpb246ICdjb2x1bW4tcmV2ZXJzZScsXG4gICAgfSxcbiAgfSxcbiAgW1NwbGl0TGF5b3V0TW9kZS5HcmlkXToge1xuICAgIGNvbW1vbjoge1xuICAgICAgZGlzcGxheTogJ2dyaWQnLFxuICAgICAgaGVpZ2h0OiAnZW52KHZpZXdwb3J0LXNlZ21lbnQtYm90dG9tIDAgMSknLFxuICAgIH0sXG4gICAgW1NjcmVlblNwYW5uaW5nLkR1YWxIb3Jpem9udGFsXToge1xuICAgICAgZ3JpZFRlbXBsYXRlQ29sdW1uczogJzFmciAxZnInLFxuICAgICAgZ3JpZFRlbXBsYXRlQXJlYXM6ICdcInNlZ21lbnQwIHNlZ21lbnQxXCInLFxuICAgICAgZ3JpZEF1dG9GbG93OiAncm93JyxcbiAgICAgIGNvbHVtbkdhcDogJ2NhbGMoZW52KHZpZXdwb3J0LXNlZ21lbnQtbGVmdCAxIDApIC0gZW52KHZpZXdwb3J0LXNlZ21lbnQtcmlnaHQgMCAwKSknLFxuICAgIH0sXG4gICAgW1NjcmVlblNwYW5uaW5nLkR1YWxWZXJ0aWNhbF06IHtcbiAgICAgIGdyaWRUZW1wbGF0ZVJvd3M6ICcxZnIgMWZyJyxcbiAgICAgIGdyaWRUZW1wbGF0ZUFyZWFzOiAnXCJzZWdtZW50MFwiIFwic2VnbWVudDFcIicsXG4gICAgICBncmlkQXV0b0Zsb3c6ICdyb3cnLFxuICAgICAgcm93R2FwOiAnY2FsYyhlbnYodmlld3BvcnQtc2VnbWVudC10b3AgMCAxKSAtIGVudih2aWV3cG9ydC1zZWdtZW50LWJvdHRvbSAwIDApKScsXG4gICAgfSxcbiAgICBbV2luZG93T3JkZXIuUmV2ZXJzZV06IHtcbiAgICAgIGdyaWRUZW1wbGF0ZVJvd3M6ICcxZnIgMWZyJyxcbiAgICAgIGdyaWRUZW1wbGF0ZUFyZWFzOiAnXCJzZWdtZW50MFwiIFwic2VnbWVudDFcIicsXG4gICAgICBncmlkQXV0b0Zsb3c6ICdyb3cnLFxuICAgICAgcm93R2FwOiAnY2FsYyhlbnYodmlld3BvcnQtc2VnbWVudC10b3AgMCAxKSAtIGVudih2aWV3cG9ydC1zZWdtZW50LWJvdHRvbSAwIDApKScsXG4gICAgfSxcbiAgfSxcbiAgW1NwbGl0TGF5b3V0TW9kZS5BYnNvbHV0ZV06IHtcbiAgICBjb21tb246IHtcbiAgICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuICAgICAgaGVpZ2h0OiAnZW52KHZpZXdwb3J0LXNlZ21lbnQtYm90dG9tIDAgMSknLFxuICAgIH0sXG4gICAgW1NjcmVlblNwYW5uaW5nLkR1YWxIb3Jpem9udGFsXToge30sXG4gICAgW1NjcmVlblNwYW5uaW5nLkR1YWxWZXJ0aWNhbF06IHt9LFxuICAgIFtXaW5kb3dPcmRlci5SZXZlcnNlXToge30sXG4gIH0sXG59O1xuXG4vKipcbiAqIERlZmluZXMgYSBwYXJlbnQgbGF5b3V0IGNvbnRhaW5lciBmb3IgY3JlYXRpbmcgYSBzcGxpdCBsYXlvdXQgb24gbXVsdGlcbiAqIHNjcmVlbiBkZXZpY2VzLlxuICpcbiAqIFdoZW4gdXNlZCBvbiBhIHNpbmdsZSBzY3JlZW4gZGV2aWNlLCBubyBsYXlvdXQgY2hhbmdlIChDU1MpIGlzIGFkZGVkLlxuICogWW91IGNhbiBjaG9vc2UgYmV0d2VlbiBkaWZmZXJlbnQge0BsaW5rIFNwbGl0TGF5b3V0TW9kZX0gdG8gc3VpdCB5b3VyXG4gKiBkZXNpZ24uXG4gKlxuICogVGhpcyBkaXJlY3RpdmUgc2hvdWxkIGJlIHVzZWQgYWxvbmcgd2l0aCB7QGxpbmsgV2luZG93RGlyZWN0aXZlfS5cbiAqXG4gKiBAZXhhbXBsZVxuICogPGRpdiBmZFNwbGl0TGF5b3V0PVwiZ3JpZFwiPlxuICogICAgICAgICAgICAgIDxzZWN0aW9uIGZkV2luZG93PVwiMFwiPldpbGwgYmUgZGlzcGxheWVkIG9uIGZpcnN0IHNjcmVlbjwvc2VjdGlvbj5cbiAqICAgICAgICAgICAgICA8c2VjdGlvbiBmZFdpbmRvdz1cIjFcIj5XaWxsIGJlIGRpc3BsYXllZCBvbiBzZWNvbmQgc2NyZWVuIChpZiBhdmFpbGFibGUpPC9zZWN0aW9uPlxuICogPC9kaXY+XG4gKlxuICogSW4gYWRkaXRpb24sIHlvdSBjYW4gYWxzbyBjaG9vc2Uga2VlcCB0aGUgc2FtZSB3aW5kb3cgc2VnbWVudHMgb3JkZXIgb3JcbiAqIHJldmVyc2UgaXQgd2hlbiB0aGUgc3Bhbm5pbmcgbW9kZSBjaGFuZ2UgZnJvbSB2ZXJ0aWNhbCB0byBob3Jpem9udGFsIHVzaW5nXG4gKiBhIHNlY29uZCBvcHRpb25hbCBwYXJhbWV0ZXIgb24gdGhlIGRpcmVjdGl2ZTpcbiAqXG4gKiBAZXhhbXBsZVxuICogPGRpdiBmZFNwbGl0TGF5b3V0PVwiZmxleCByZXZlcnNlXCI+XG4gKiAgICAgICAgICAgICAgPHNlY3Rpb24gZmRXaW5kb3c9XCIwXCI+XG4gKiAgICAgICAgICAgICAgICBXaWxsIGJlIGRpc3BsYXllZCBvbiBmaXJzdCBzY3JlZW4gaW4gdmVydGljYWwgc3Bhbm5pbmcgbW9kZVxuICogICAgICAgICAgICAgICAgYW5kIG9uIHRoZSBzZWNvbmQgc2NyZWVuIGluIGhvcml6b250YWwgc3Bhbm5pbmcgbW9kZS5cbiAqICAgICAgICAgICAgICA8L3NlY3Rpb24+XG4gKiAgICAgICAgICAgICAgPHNlY3Rpb24gZmRXaW5kb3c9XCIxXCI+XG4gKiAgICAgICAgICAgICAgICBXaWxsIGJlIGRpc3BsYXllZCBvbiBzZWNvbmQgc2NyZWVuIGluIHZlcnRpY2FsIHNwYW5uaW5nIG1vZGVcbiAqICAgICAgICAgICAgICAgIGFuZCBvbiB0aGUgZmlyc3Qgc2NyZWVuIGluIGhvcml6b250YWwgc3Bhbm5pbmcgbW9kZS5cbiAqICAgICAgICAgICAgICA8L3NlY3Rpb24+XG4gKiA8L2Rpdj5cbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2ZkU3BsaXRMYXlvdXRdJyxcbn0pXG5leHBvcnQgY2xhc3MgU3BsaXRMYXlvdXREaXJlY3RpdmUgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIG1vZGU6IFNwbGl0TGF5b3V0TW9kZSA9IFNwbGl0TGF5b3V0TW9kZS5GbGV4O1xuICBwcml2YXRlIG9yZGVyOiBXaW5kb3dPcmRlciA9IFdpbmRvd09yZGVyLk5vcm1hbDtcbiAgcHJpdmF0ZSBsYXlvdXRTdHlsZTogU2FmZVN0eWxlID0ge307XG4gIHByaXZhdGUgc2NyZWVuQ29udGV4dFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZGlyZWN0aW9uOiBSZWFkaW5nRGlyZWN0aW9uID0gJ2x0cic7XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGN1cnJlbnQgc3BsaXQgbGF5b3V0IG9wdGlvbnMgdG8gdXNlIHdoZW4gbXVsdGkgc2NyZWVuIGlzXG4gICAqIGRldGVjdGVkLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgc3BsaXQgbGF5b3V0IG9wdGlvbnMgdG8gdXNlLlxuICAgKiBGb3JtYXQ6IGBbbW9kZV0gW29yZGVyXWBcbiAgICogLSBUaGUge0BsaW5rIFNwbGl0TGF5b3V0TW9kZX0gdG8gdXNlIChkZWZhdWx0IGlzIHtAbGluayBTcGxpdExheW91dE1vZGUuRmxleH0pLlxuICAgKiAtIFRoZSB7QGxpbmsgV2luZG93T3JkZXJ9IHRvIHVzZSAoZGVmYXVsdCBpcyB7QGxpbmsgV2luZG93T3JkZXIuTm9ybWFsfSkuXG4gICAqL1xuICBASW5wdXQoKVxuICBzZXQgZmRTcGxpdExheW91dChvcHRpb25zOiBzdHJpbmcgfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLnBhcnNlT3B0aW9ucyhvcHRpb25zIHx8ICcnKTtcbiAgICB0aGlzLnVwZGF0ZVN0eWxlKCk7XG4gIH1cblxuICAvKiogQGlnbm9yZSAqL1xuICBASG9zdEJpbmRpbmcoJ3N0eWxlJylcbiAgZ2V0IHN0eWxlKCk6IFNhZmVTdHlsZSB7XG4gICAgcmV0dXJuIHRoaXMubGF5b3V0U3R5bGU7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgcHJpdmF0ZSBzY3JlZW5Db250ZXh0OiBTY3JlZW5Db250ZXh0XG4gICkge1xuICAgIHRoaXMudXBkYXRlU3R5bGUoKTtcbiAgICB0aGlzLnNjcmVlbkNvbnRleHRTdWJzY3JpcHRpb24gPSB0aGlzLnNjcmVlbkNvbnRleHRcbiAgICAgIC5hc09ic2VydmFibGUoKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLnVwZGF0ZVN0eWxlKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IHNwbGl0IGxheW91dCBtb2RlIHRvIHVzZSB3aGVuIG11bHRpIHNjcmVlbiBpcyBkZXRlY3RlZC5cbiAgICpcbiAgICogQHJldHVybiBUaGUgY3VycmVudCBzcGxpdCBsYXlvdXQgbW9kZS5cbiAgICovXG4gIGdldCBsYXlvdXRNb2RlKCk6IFNwbGl0TGF5b3V0TW9kZSB7XG4gICAgcmV0dXJuIHRoaXMubW9kZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgd2luZG93IHNlZ21lbnRzIG9yZGVyIHRvIHVzZSB3aGVuIGluIGhvcml6b250YWwgc3Bhbm5pbmcgbW9kZS5cbiAgICpcbiAgICogQHJldHVybiBUaGUgY3VycmVudCB3aW5kb3cgb3JkZXIuXG4gICAqL1xuICBnZXQgd2luZG93T3JkZXIoKTogV2luZG93T3JkZXIge1xuICAgIHJldHVybiB0aGlzLm9yZGVyO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB0ZXh0IHJlYWRpbmcgZGlyZWN0aW9uIGZvciB0aGUgaG9zdCBlbGVtZW50LlxuICAgKlxuICAgKiBAcmV0dXJuIFRoZSB0ZXh0IHJlYWRpbmcgZGlyZWN0aW9uLlxuICAgKi9cbiAgZ2V0IHJlYWRpbmdEaXJlY3Rpb24oKTogUmVhZGluZ0RpcmVjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuZGlyZWN0aW9uO1xuICB9XG5cbiAgLyoqIEBpZ25vcmUgKi9cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuc2NyZWVuQ29udGV4dFN1YnNjcmlwdGlvbiAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5zY3JlZW5Db250ZXh0U3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZU9wdGlvbnMob3B0aW9uczogc3RyaW5nKSB7XG4gICAgbGV0IFttb2RlLCBvcmRlcl0gPSBvcHRpb25zLnRyaW0oKS5zcGxpdCgnICcpO1xuICAgIG1vZGUgPSBTcGxpdExheW91dE1vZGUuaXNWYWxpZChtb2RlKSA/IG1vZGUgOiBTcGxpdExheW91dE1vZGUuRmxleDtcbiAgICBvcmRlciA9IFdpbmRvd09yZGVyLmlzVmFsaWQob3JkZXIpID8gb3JkZXIgOiBXaW5kb3dPcmRlci5Ob3JtYWw7XG4gICAgdGhpcy5tb2RlID0gbW9kZSBhcyBTcGxpdExheW91dE1vZGU7XG4gICAgdGhpcy5vcmRlciA9IG9yZGVyIGFzIFdpbmRvd09yZGVyO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVTdHlsZSgpIHtcbiAgICBjb25zdCBpc011bHRpU2NyZWVuID0gdGhpcy5zY3JlZW5Db250ZXh0LmlzTXVsdGlTY3JlZW47XG4gICAgY29uc3Qgc3Bhbm5pbmcgPSB0aGlzLnNjcmVlbkNvbnRleHQuc2NyZWVuU3Bhbm5pbmc7XG4gICAgY29uc3QgcmV2ZXJzZSA9XG4gICAgICBzcGFubmluZyA9PT0gU2NyZWVuU3Bhbm5pbmcuRHVhbFZlcnRpY2FsICYmXG4gICAgICB0aGlzLm9yZGVyID09PSBXaW5kb3dPcmRlci5SZXZlcnNlO1xuXG4gICAgdGhpcy5kaXJlY3Rpb24gPVxuICAgICAgKGdldENvbXB1dGVkU3R5bGUodGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQpXG4gICAgICAgID8uZGlyZWN0aW9uIGFzIFJlYWRpbmdEaXJlY3Rpb24pIHx8IFJlYWRpbmdEaXJlY3Rpb24uTGVmdFRvUmlnaHQ7XG5cbiAgICBpZiAoaXNNdWx0aVNjcmVlbiAmJiBzcGFubmluZyAhPT0gU2NyZWVuU3Bhbm5pbmcuTm9uZSkge1xuICAgICAgdGhpcy5sYXlvdXRTdHlsZSA9IHtcbiAgICAgICAgLi4ubGF5b3V0U3R5bGVzW3RoaXMubW9kZV0uY29tbW9uLFxuICAgICAgICAuLi5sYXlvdXRTdHlsZXNbdGhpcy5tb2RlXVtyZXZlcnNlID8gV2luZG93T3JkZXIuUmV2ZXJzZSA6IHNwYW5uaW5nXSxcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGF5b3V0U3R5bGUgPSB7fTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==