juvo-rafa-library
Version:
A comprehensive Angular component library featuring real-world components and validators extracted from the Juvo Rafa backoffice application. Now with improved select components and bug fixes.
223 lines • 33.6 kB
JavaScript
import { Component, Input, Output, EventEmitter, forwardRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NG_VALUE_ACCESSOR, ReactiveFormsModule, FormsModule } from '@angular/forms';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/forms";
/**
* Input Component
*
* @description
* A comprehensive input component supporting various input types and form integration.
* Includes support for text, email, password, number, textarea, and select inputs.
* Originally designed for backoffice applications with extensive form requirements.
*
* @example
* ```html
* <!-- Basic text input -->
* <juvo-input
* label="Full Name"
* placeholder="Enter your full name"
* [(ngModel)]="name">
* </juvo-input>
*
* <!-- Email input with validation -->
* <juvo-input
* type="email"
* label="Email Address"
* placeholder="user@example.com"
* [required]="true"
* [error]="emailError"
* [(ngModel)]="email">
* </juvo-input>
*
* <!-- Select dropdown -->
* <juvo-input
* type="select"
* label="Country"
* [options]="countryOptions"
* [(ngModel)]="selectedCountry">
* </juvo-input>
*
* <!-- Textarea -->
* <juvo-input
* type="textarea"
* label="Description"
* [rows]="4"
* placeholder="Enter description..."
* [(ngModel)]="description">
* </juvo-input>
* ```
*
* @selector juvo-input
* @since 2.1.0
* @author Juvo Rafa Team
*/
export class JuvoInputComponent {
constructor() {
/** Input placeholder text */
this.placeholder = '';
/** Input type @default "text" */
this.type = 'text';
/** Input size @default "medium" */
this.size = 'medium';
/** Whether input is disabled @default false */
this.disabled = false;
/** Whether input is readonly @default false */
this.readonly = false;
/** Whether input is required @default false */
this.required = false;
/** Number of rows for textarea @default 3 */
this.rows = 3;
/** Options for select input */
this.options = [];
/** Whether to show character counter @default false */
this.showCounter = false;
/** Emitted when value changes */
this.valueChange = new EventEmitter();
/** Emitted when input receives focus */
this.onFocus = new EventEmitter();
/** Emitted when input loses focus */
this.onBlur = new EventEmitter();
this._value = '';
this._onChange = (value) => { };
this._onTouched = () => { };
}
get value() {
return this._value;
}
set value(val) {
if (val !== this._value) {
this._value = val;
this._onChange(val);
this.valueChange.emit(val);
}
}
/**
* Gets CSS classes for the input container
* @returns Combined CSS classes
*/
get containerClasses() {
let classes = `input-container input-${this.size}`;
if (this.disabled)
classes += ' disabled';
if (this.error)
classes += ' error';
if (this.readonly)
classes += ' readonly';
return classes;
}
/**
* Gets CSS classes for the input element
* @returns Combined CSS classes
*/
get inputClasses() {
let classes = 'input-element';
if (this.prefix)
classes += ' has-prefix';
if (this.suffix)
classes += ' has-suffix';
return classes;
}
/**
* Handles input value changes
*/
onInput(event) {
const target = event.target;
this.value = target.value;
}
/**
* Handles input focus
*/
handleFocus() {
this.onFocus.emit();
}
/**
* Handles input blur
*/
handleBlur() {
this._onTouched();
this.onBlur.emit();
}
/**
* Gets the character count for display
* @returns Current character count
*/
get characterCount() {
return this.value ? this.value.toString().length : 0;
}
// ControlValueAccessor implementation
writeValue(value) {
this._value = value || '';
}
registerOnChange(fn) {
this._onChange = fn;
}
registerOnTouched(fn) {
this._onTouched = fn;
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: JuvoInputComponent, isStandalone: true, selector: "juvo-input", inputs: { label: "label", placeholder: "placeholder", type: "type", size: "size", disabled: "disabled", readonly: "readonly", required: "required", error: "error", hint: "hint", maxLength: "maxLength", min: "min", max: "max", step: "step", rows: "rows", options: "options", prefix: "prefix", suffix: "suffix", showCounter: "showCounter" }, outputs: { valueChange: "valueChange", onFocus: "onFocus", onBlur: "onBlur" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => JuvoInputComponent),
multi: true
}
], ngImport: i0, template: "<div [class]=\"containerClasses\">\n <!-- Label -->\n <label class=\"input-label\" *ngIf=\"label\">\n {{ label }}\n <span class=\"required-indicator\" *ngIf=\"required\">*</span>\n </label>\n\n <!-- Input wrapper -->\n <div class=\"input-wrapper\">\n <!-- Prefix -->\n <span class=\"input-prefix\" *ngIf=\"prefix\">{{ prefix }}</span>\n\n <!-- Text Input -->\n <input\n *ngIf=\"type !== 'textarea' && type !== 'select'\"\n [class]=\"inputClasses\"\n [type]=\"type\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.maxlength]=\"maxLength\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n />\n\n <!-- Textarea -->\n <textarea\n *ngIf=\"type === 'textarea'\"\n [class]=\"inputClasses\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.maxlength]=\"maxLength\"\n [rows]=\"rows\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\">\n </textarea>\n\n <!-- Select -->\n <select\n *ngIf=\"type === 'select'\"\n [class]=\"inputClasses\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n [value]=\"value\"\n (change)=\"onInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\">\n <option value=\"\" disabled *ngIf=\"placeholder\">{{ placeholder }}</option>\n <option \n *ngFor=\"let option of options\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n </select>\n\n <!-- Suffix -->\n <span class=\"input-suffix\" *ngIf=\"suffix\">{{ suffix }}</span>\n </div>\n\n <!-- Footer -->\n <div class=\"input-footer\" *ngIf=\"error || hint || (showCounter && maxLength)\">\n <!-- Error message -->\n <div class=\"input-error\" *ngIf=\"error\">\n {{ error }}\n </div>\n \n <!-- Hint text -->\n <div class=\"input-hint\" *ngIf=\"hint && !error\">\n {{ hint }}\n </div>\n \n <!-- Character counter -->\n <div class=\"input-counter\" *ngIf=\"showCounter && maxLength && !error\">\n {{ characterCount }}/{{ maxLength }}\n </div>\n </div>\n</div> ", styles: [".input-container{display:flex;flex-direction:column;gap:.5rem;width:100%}.input-label{display:block;font-weight:500;color:#374151;font-size:.875rem}.required-indicator{color:#ef4444;margin-left:.25rem}.input-wrapper{position:relative;display:flex;align-items:center}.input-element{width:100%;border:1px solid #d1d5db;border-radius:.375rem;transition:all .15s;font-size:.875rem;background:#fff}.input-element:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.input-element:disabled{background:#f9fafb;color:#9ca3af;cursor:not-allowed}.input-element:readonly{background:#f9fafb;color:#6b7280}.input-small .input-element{padding:.5rem .75rem;font-size:.8125rem}.input-medium .input-element{padding:.625rem .875rem;font-size:.875rem}.input-large .input-element{padding:.75rem 1rem;font-size:1rem}.input-element.has-prefix{padding-left:2.5rem}.input-element.has-suffix{padding-right:2.5rem}.input-prefix,.input-suffix{position:absolute;color:#6b7280;font-size:.875rem;pointer-events:none}.input-prefix{left:.75rem}.input-suffix{right:.75rem}select.input-element{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem}select.input-element::-ms-expand{display:none}textarea.input-element{resize:vertical;min-height:80px}.input-container.error .input-element{border-color:#ef4444}.input-container.error .input-element:focus{border-color:#ef4444;box-shadow:0 0 0 3px #ef44441a}.input-container.disabled{opacity:.6}.input-container.readonly .input-element{border-color:#e5e7eb}.input-footer{display:flex;justify-content:space-between;align-items:flex-start;gap:.5rem;min-height:1.25rem}.input-error{color:#ef4444;font-size:.75rem;flex:1}.input-hint{color:#6b7280;font-size:.75rem;flex:1}.input-counter{color:#9ca3af;font-size:.75rem;flex-shrink:0}@media (max-width: 640px){.input-label{font-size:.8125rem}.input-large .input-element{padding:.625rem .875rem;font-size:.875rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "ngmodule", type: FormsModule }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoInputComponent, decorators: [{
type: Component,
args: [{ selector: 'juvo-input', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule], providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => JuvoInputComponent),
multi: true
}
], template: "<div [class]=\"containerClasses\">\n <!-- Label -->\n <label class=\"input-label\" *ngIf=\"label\">\n {{ label }}\n <span class=\"required-indicator\" *ngIf=\"required\">*</span>\n </label>\n\n <!-- Input wrapper -->\n <div class=\"input-wrapper\">\n <!-- Prefix -->\n <span class=\"input-prefix\" *ngIf=\"prefix\">{{ prefix }}</span>\n\n <!-- Text Input -->\n <input\n *ngIf=\"type !== 'textarea' && type !== 'select'\"\n [class]=\"inputClasses\"\n [type]=\"type\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.maxlength]=\"maxLength\"\n [min]=\"min\"\n [max]=\"max\"\n [step]=\"step\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n />\n\n <!-- Textarea -->\n <textarea\n *ngIf=\"type === 'textarea'\"\n [class]=\"inputClasses\"\n [placeholder]=\"placeholder\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [required]=\"required\"\n [attr.maxlength]=\"maxLength\"\n [rows]=\"rows\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\">\n </textarea>\n\n <!-- Select -->\n <select\n *ngIf=\"type === 'select'\"\n [class]=\"inputClasses\"\n [disabled]=\"disabled\"\n [required]=\"required\"\n [value]=\"value\"\n (change)=\"onInput($event)\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\">\n <option value=\"\" disabled *ngIf=\"placeholder\">{{ placeholder }}</option>\n <option \n *ngFor=\"let option of options\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n </select>\n\n <!-- Suffix -->\n <span class=\"input-suffix\" *ngIf=\"suffix\">{{ suffix }}</span>\n </div>\n\n <!-- Footer -->\n <div class=\"input-footer\" *ngIf=\"error || hint || (showCounter && maxLength)\">\n <!-- Error message -->\n <div class=\"input-error\" *ngIf=\"error\">\n {{ error }}\n </div>\n \n <!-- Hint text -->\n <div class=\"input-hint\" *ngIf=\"hint && !error\">\n {{ hint }}\n </div>\n \n <!-- Character counter -->\n <div class=\"input-counter\" *ngIf=\"showCounter && maxLength && !error\">\n {{ characterCount }}/{{ maxLength }}\n </div>\n </div>\n</div> ", styles: [".input-container{display:flex;flex-direction:column;gap:.5rem;width:100%}.input-label{display:block;font-weight:500;color:#374151;font-size:.875rem}.required-indicator{color:#ef4444;margin-left:.25rem}.input-wrapper{position:relative;display:flex;align-items:center}.input-element{width:100%;border:1px solid #d1d5db;border-radius:.375rem;transition:all .15s;font-size:.875rem;background:#fff}.input-element:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.input-element:disabled{background:#f9fafb;color:#9ca3af;cursor:not-allowed}.input-element:readonly{background:#f9fafb;color:#6b7280}.input-small .input-element{padding:.5rem .75rem;font-size:.8125rem}.input-medium .input-element{padding:.625rem .875rem;font-size:.875rem}.input-large .input-element{padding:.75rem 1rem;font-size:1rem}.input-element.has-prefix{padding-left:2.5rem}.input-element.has-suffix{padding-right:2.5rem}.input-prefix,.input-suffix{position:absolute;color:#6b7280;font-size:.875rem;pointer-events:none}.input-prefix{left:.75rem}.input-suffix{right:.75rem}select.input-element{cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e\");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem}select.input-element::-ms-expand{display:none}textarea.input-element{resize:vertical;min-height:80px}.input-container.error .input-element{border-color:#ef4444}.input-container.error .input-element:focus{border-color:#ef4444;box-shadow:0 0 0 3px #ef44441a}.input-container.disabled{opacity:.6}.input-container.readonly .input-element{border-color:#e5e7eb}.input-footer{display:flex;justify-content:space-between;align-items:flex-start;gap:.5rem;min-height:1.25rem}.input-error{color:#ef4444;font-size:.75rem;flex:1}.input-hint{color:#6b7280;font-size:.75rem;flex:1}.input-counter{color:#9ca3af;font-size:.75rem;flex-shrink:0}@media (max-width: 640px){.input-label{font-size:.8125rem}.input-large .input-element{padding:.625rem .875rem;font-size:.875rem}}\n"] }]
}], propDecorators: { label: [{
type: Input
}], placeholder: [{
type: Input
}], type: [{
type: Input
}], size: [{
type: Input
}], disabled: [{
type: Input
}], readonly: [{
type: Input
}], required: [{
type: Input
}], error: [{
type: Input
}], hint: [{
type: Input
}], maxLength: [{
type: Input
}], min: [{
type: Input
}], max: [{
type: Input
}], step: [{
type: Input
}], rows: [{
type: Input
}], options: [{
type: Input
}], prefix: [{
type: Input
}], suffix: [{
type: Input
}], showCounter: [{
type: Input
}], valueChange: [{
type: Output
}], onFocus: [{
type: Output
}], onBlur: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianV2by1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS1jb21wb25lbnRzL3NyYy9saWIvanV2by1pbnB1dC9qdXZvLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpLWNvbXBvbmVudHMvc3JjL2xpYi9qdXZvLWlucHV0L2p1dm8taW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUEyQjNHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnREc7QUFlSCxNQUFNLE9BQU8sa0JBQWtCO0lBZC9CO1FBa0JFLDZCQUE2QjtRQUNwQixnQkFBVyxHQUFXLEVBQUUsQ0FBQztRQUVsQyxpQ0FBaUM7UUFDeEIsU0FBSSxHQUFjLE1BQU0sQ0FBQztRQUVsQyxtQ0FBbUM7UUFDMUIsU0FBSSxHQUFjLFFBQVEsQ0FBQztRQUVwQywrQ0FBK0M7UUFDdEMsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUVuQywrQ0FBK0M7UUFDdEMsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUVuQywrQ0FBK0M7UUFDdEMsYUFBUSxHQUFZLEtBQUssQ0FBQztRQW9CbkMsNkNBQTZDO1FBQ3BDLFNBQUksR0FBVyxDQUFDLENBQUM7UUFFMUIsK0JBQStCO1FBQ3RCLFlBQU8sR0FBbUIsRUFBRSxDQUFDO1FBUXRDLHVEQUF1RDtRQUM5QyxnQkFBVyxHQUFZLEtBQUssQ0FB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dGVyLCBmb3J3YXJkUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SLCBSZWFjdGl2ZUZvcm1zTW9kdWxlLCBGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuLyoqXG4gKiBJbnB1dCB0eXBlcyBzdXBwb3J0ZWQgYnkgSnV2b0lucHV0Q29tcG9uZW50XG4gKiBAdHlwZSBJbnB1dFR5cGVcbiAqIEBzaW5jZSAyLjEuMFxuICovXG5leHBvcnQgdHlwZSBJbnB1dFR5cGUgPSAndGV4dCcgfCAnZW1haWwnIHwgJ3Bhc3N3b3JkJyB8ICdudW1iZXInIHwgJ3RlbCcgfCAndXJsJyB8ICdzZWFyY2gnIHwgJ3RleHRhcmVhJyB8ICdzZWxlY3QnO1xuXG4vKipcbiAqIElucHV0IHNpemVzXG4gKiBAdHlwZSBJbnB1dFNpemVcbiAqIEBzaW5jZSAyLjEuMFxuICovXG5leHBvcnQgdHlwZSBJbnB1dFNpemUgPSAnc21hbGwnIHwgJ21lZGl1bScgfCAnbGFyZ2UnO1xuXG4vKipcbiAqIFNlbGVjdCBvcHRpb24gaW50ZXJmYWNlXG4gKiBAaW50ZXJmYWNlIFNlbGVjdE9wdGlvblxuICogQHNpbmNlIDIuMS4wXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VsZWN0T3B0aW9uIHtcbiAgbGFiZWw6IHN0cmluZztcbiAgdmFsdWU6IGFueTtcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIElucHV0IENvbXBvbmVudFxuICogXG4gKiBAZGVzY3JpcHRpb25cbiAqIEEgY29tcHJlaGVuc2l2ZSBpbnB1dCBjb21wb25lbnQgc3VwcG9ydGluZyB2YXJpb3VzIGlucHV0IHR5cGVzIGFuZCBmb3JtIGludGVncmF0aW9uLlxuICogSW5jbHVkZXMgc3VwcG9ydCBmb3IgdGV4dCwgZW1haWwsIHBhc3N3b3JkLCBudW1iZXIsIHRleHRhcmVhLCBhbmQgc2VsZWN0IGlucHV0cy5cbiAqIE9yaWdpbmFsbHkgZGVzaWduZWQgZm9yIGJhY2tvZmZpY2UgYXBwbGljYXRpb25zIHdpdGggZXh0ZW5zaXZlIGZvcm0gcmVxdWlyZW1lbnRzLlxuICogXG4gKiBAZXhhbXBsZVxuICogYGBgaHRtbFxuICogPCEtLSBCYXNpYyB0ZXh0IGlucHV0IC0tPlxuICogPGp1dm8taW5wdXRcbiAqICAgbGFiZWw9XCJGdWxsIE5hbWVcIlxuICogICBwbGFjZWhvbGRlcj1cIkVudGVyIHlvdXIgZnVsbCBuYW1lXCJcbiAqICAgWyhuZ01vZGVsKV09XCJuYW1lXCI+XG4gKiA8L2p1dm8taW5wdXQ+XG4gKiBcbiAqIDwhLS0gRW1haWwgaW5wdXQgd2l0aCB2YWxpZGF0aW9uIC0tPlxuICogPGp1dm8taW5wdXRcbiAqICAgdHlwZT1cImVtYWlsXCJcbiAqICAgbGFiZWw9XCJFbWFpbCBBZGRyZXNzXCJcbiAqICAgcGxhY2Vob2xkZXI9XCJ1c2VyQGV4YW1wbGUuY29tXCJcbiAqICAgW3JlcXVpcmVkXT1cInRydWVcIlxuICogICBbZXJyb3JdPVwiZW1haWxFcnJvclwiXG4gKiAgIFsobmdNb2RlbCldPVwiZW1haWxcIj5cbiAqIDwvanV2by1pbnB1dD5cbiAqIFxuICogPCEtLSBTZWxlY3QgZHJvcGRvd24gLS0+XG4gKiA8anV2by1pbnB1dFxuICogICB0eXBlPVwic2VsZWN0XCJcbiAqICAgbGFiZWw9XCJDb3VudHJ5XCJcbiAqICAgW29wdGlvbnNdPVwiY291bnRyeU9wdGlvbnNcIlxuICogICBbKG5nTW9kZWwpXT1cInNlbGVjdGVkQ291bnRyeVwiPlxuICogPC9qdXZvLWlucHV0PlxuICogXG4gKiA8IS0tIFRleHRhcmVhIC0tPlxuICogPGp1dm8taW5wdXRcbiAqICAgdHlwZT1cInRleHRhcmVhXCJcbiAqICAgbGFiZWw9XCJEZXNjcmlwdGlvblwiXG4gKiAgIFtyb3dzXT1cIjRcIlxuICogICBwbGFjZWhvbGRlcj1cIkVudGVyIGRlc2NyaXB0aW9uLi4uXCJcbiAqICAgWyhuZ01vZGVsKV09XCJkZXNjcmlwdGlvblwiPlxuICogPC9qdXZvLWlucHV0PlxuICogYGBgXG4gKiBcbiAqIEBzZWxlY3RvciBqdXZvLWlucHV0XG4gKiBAc2luY2UgMi4xLjBcbiAqIEBhdXRob3IgSnV2byBSYWZhIFRlYW1cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnanV2by1pbnB1dCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGUsIEZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2p1dm8taW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vanV2by1pbnB1dC5jb21wb25lbnQuY3NzJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBKdXZvSW5wdXRDb21wb25lbnQpLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9XG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgSnV2b0lucHV0Q29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuICAvKiogSW5wdXQgbGFiZWwgKi9cbiAgQElucHV0KCkgbGFiZWw/OiBzdHJpbmc7XG4gIFxuICAvKiogSW5wdXQgcGxhY2Vob2xkZXIgdGV4dCAqL1xuICBASW5wdXQoKSBwbGFjZWhvbGRlcjogc3RyaW5nID0gJyc7XG4gIFxuICAvKiogSW5wdXQgdHlwZSBAZGVmYXVsdCBcInRleHRcIiAqL1xuICBASW5wdXQoKSB0eXBlOiBJbnB1dFR5cGUgPSAndGV4dCc7XG4gIFxuICAvKiogSW5wdXQgc2l6ZSBAZGVmYXVsdCBcIm1lZGl1bVwiICovXG4gIEBJbnB1dCgpIHNpemU6IElucHV0U2l6ZSA9ICdtZWRpdW0nO1xuICBcbiAgLyoqIFdoZXRoZXIgaW5wdXQgaXMgZGlzYWJsZWQgQGRlZmF1bHQgZmFsc2UgKi9cbiAgQElucHV0KCkgZGlzYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgXG4gIC8qKiBXaGV0aGVyIGlucHV0IGlzIHJlYWRvbmx5IEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIHJlYWRvbmx5OiBib29sZWFuID0gZmFsc2U7XG4gIFxuICAvKiogV2hldGhlciBpbnB1dCBpcyByZXF1aXJlZCBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSByZXF1aXJlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBcbiAgLyoqIEVycm9yIG1lc3NhZ2UgdG8gZGlzcGxheSAqL1xuICBASW5wdXQoKSBlcnJvcj86IHN0cmluZztcbiAgXG4gIC8qKiBIaW50IHRleHQgdG8gZGlzcGxheSAqL1xuICBASW5wdXQoKSBoaW50Pzogc3RyaW5nO1xuICBcbiAgLyoqIE1heGltdW0gbGVuZ3RoIGZvciB0ZXh0IGlucHV0cyAqL1xuICBASW5wdXQoKSBtYXhMZW5ndGg/OiBudW1iZXI7XG4gIFxuICAvKiogTWluaW11bSB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cyAqL1xuICBASW5wdXQoKSBtaW4/OiBudW1iZXI7XG4gIFxuICAvKiogTWF4aW11bSB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cyAqL1xuICBASW5wdXQoKSBtYXg/OiBudW1iZXI7XG4gIFxuICAvKiogU3RlcCB2YWx1ZSBmb3IgbnVtYmVyIGlucHV0cyAqL1xuICBASW5wdXQoKSBzdGVwPzogbnVtYmVyO1xuICBcbiAgLyoqIE51bWJlciBvZiByb3dzIGZvciB0ZXh0YXJlYSBAZGVmYXVsdCAzICovXG4gIEBJbnB1dCgpIHJvd3M6IG51bWJlciA9IDM7XG4gIFxuICAvKiogT3B0aW9ucyBmb3Igc2VsZWN0IGlucHV0ICovXG4gIEBJbnB1dCgpIG9wdGlvbnM6IFNlbGVjdE9wdGlvbltdID0gW107XG4gIFxuICAvKiogUHJlZml4IHRleHQgb3IgaWNvbiAqL1xuICBASW5wdXQoKSBwcmVmaXg/OiBzdHJpbmc7XG4gIFxuICAvKiogU3VmZml4IHRleHQgb3IgaWNvbiAqL1xuICBASW5wdXQoKSBzdWZmaXg/OiBzdHJpbmc7XG4gIFxuICAvKiogV2hldGhlciB0byBzaG93IGNoYXJhY3RlciBjb3VudGVyIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIHNob3dDb3VudGVyOiBib29sZWFuID0gZmFsc2U7XG4gIFxuICAvKiogRW1pdHRlZCB3aGVuIHZhbHVlIGNoYW5nZXMgKi9cbiAgQE91dHB1dCgpIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIFxuICAvKiogRW1pdHRlZCB3aGVuIGlucHV0IHJlY2VpdmVzIGZvY3VzICovXG4gIEBPdXRwdXQoKSBvbkZvY3VzID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICBcbiAgLyoqIEVtaXR0ZWQgd2hlbiBpbnB1dCBsb3NlcyBmb2N1cyAqL1xuICBAT3V0cHV0KCkgb25CbHVyID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIHByaXZhdGUgX3ZhbHVlOiBhbnkgPSAnJztcbiAgcHJpdmF0ZSBfb25DaGFuZ2UgPSAodmFsdWU6IGFueSkgPT4ge307XG4gIHByaXZhdGUgX29uVG91Y2hlZCA9ICgpID0+IHt9O1xuXG4gIGdldCB2YWx1ZSgpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLl92YWx1ZTtcbiAgfVxuXG4gIHNldCB2YWx1ZSh2YWw6IGFueSkge1xuICAgIGlmICh2YWwgIT09IHRoaXMuX3ZhbHVlKSB7XG4gICAgICB0aGlzLl92YWx1ZSA9IHZhbDtcbiAgICAgIHRoaXMuX29uQ2hhbmdlKHZhbCk7XG4gICAgICB0aGlzLnZhbHVlQ2hhbmdlLmVtaXQodmFsKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBDU1MgY2xhc3NlcyBmb3IgdGhlIGlucHV0IGNvbnRhaW5lclxuICAgKiBAcmV0dXJucyBDb21iaW5lZCBDU1MgY2xhc3Nlc1xuICAgKi9cbiAgZ2V0IGNvbnRhaW5lckNsYXNzZXMoKTogc3RyaW5nIHtcbiAgICBsZXQgY2xhc3NlcyA9IGBpbnB1dC1jb250YWluZXIgaW5wdXQtJHt0aGlzLnNpemV9YDtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkgY2xhc3NlcyArPSAnIGRpc2FibGVkJztcbiAgICBpZiAodGhpcy5lcnJvcikgY2xhc3NlcyArPSAnIGVycm9yJztcbiAgICBpZiAodGhpcy5yZWFkb25seSkgY2xhc3NlcyArPSAnIHJlYWRvbmx5JztcbiAgICByZXR1cm4gY2xhc3NlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIENTUyBjbGFzc2VzIGZvciB0aGUgaW5wdXQgZWxlbWVudFxuICAgKiBAcmV0dXJucyBDb21iaW5lZCBDU1MgY2xhc3Nlc1xuICAgKi9cbiAgZ2V0IGlucHV0Q2xhc3NlcygpOiBzdHJpbmcge1xuICAgIGxldCBjbGFzc2VzID0gJ2lucHV0LWVsZW1lbnQnO1xuICAgIGlmICh0aGlzLnByZWZpeCkgY2xhc3NlcyArPSAnIGhhcy1wcmVmaXgnO1xuICAgIGlmICh0aGlzLnN1ZmZpeCkgY2xhc3NlcyArPSAnIGhhcy1zdWZmaXgnO1xuICAgIHJldHVybiBjbGFzc2VzO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgaW5wdXQgdmFsdWUgY2hhbmdlc1xuICAgKi9cbiAgb25JbnB1dChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCB8IEhUTUxUZXh0QXJlYUVsZW1lbnQgfCBIVE1MU2VsZWN0RWxlbWVudDtcbiAgICB0aGlzLnZhbHVlID0gdGFyZ2V0LnZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgaW5wdXQgZm9jdXNcbiAgICovXG4gIGhhbmRsZUZvY3VzKCk6IHZvaWQge1xuICAgIHRoaXMub25Gb2N1cy5lbWl0KCk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyBpbnB1dCBibHVyXG4gICAqL1xuICBoYW5kbGVCbHVyKCk6IHZvaWQge1xuICAgIHRoaXMuX29uVG91Y2hlZCgpO1xuICAgIHRoaXMub25CbHVyLmVtaXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBjaGFyYWN0ZXIgY291bnQgZm9yIGRpc3BsYXlcbiAgICogQHJldHVybnMgQ3VycmVudCBjaGFyYWN0ZXIgY291bnRcbiAgICovXG4gIGdldCBjaGFyYWN0ZXJDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnZhbHVlID8gdGhpcy52YWx1ZS50b1N0cmluZygpLmxlbmd0aCA6IDA7XG4gIH1cblxuICAvLyBDb250cm9sVmFsdWVBY2Nlc3NvciBpbXBsZW1lbnRhdGlvblxuICB3cml0ZVZhbHVlKHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLl92YWx1ZSA9IHZhbHVlIHx8ICcnO1xuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBhbnkpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLl9vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLl9vblRvdWNoZWQgPSBmbjtcbiAgfVxuXG4gIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuZGlzYWJsZWQgPSBpc0Rpc2FibGVkO1xuICB9XG59ICIsIjxkaXYgW2NsYXNzXT1cImNvbnRhaW5lckNsYXNzZXNcIj5cbiAgPCEtLSBMYWJlbCAtLT5cbiAgPGxhYmVsIGNsYXNzPVwiaW5wdXQtbGFiZWxcIiAqbmdJZj1cImxhYmVsXCI+XG4gICAge3sgbGFiZWwgfX1cbiAgICA8c3BhbiBjbGFzcz1cInJlcXVpcmVkLWluZGljYXRvclwiICpuZ0lmPVwicmVxdWlyZWRcIj4qPC9zcGFuPlxuICA8L2xhYmVsPlxuXG4gIDwhLS0gSW5wdXQgd3JhcHBlciAtLT5cbiAgPGRpdiBjbGFzcz1cImlucHV0LXdyYXBwZXJcIj5cbiAgICA8IS0tIFByZWZpeCAtLT5cbiAgICA8c3BhbiBjbGFzcz1cImlucHV0LXByZWZpeFwiICpuZ0lmPVwicHJlZml4XCI+e3sgcHJlZml4IH19PC9zcGFuPlxuXG4gICAgPCEtLSBUZXh0IElucHV0IC0tPlxuICAgIDxpbnB1dFxuICAgICAgKm5nSWY9XCJ0eXBlICE9PSAndGV4dGFyZWEnICYmIHR5cGUgIT09ICdzZWxlY3QnXCJcbiAgICAgIFtjbGFzc109XCJpbnB1dENsYXNzZXNcIlxuICAgICAgW3R5cGVdPVwidHlwZVwiXG4gICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgIFtyZWFkb25seV09XCJyZWFkb25seVwiXG4gICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxuICAgICAgW2F0dHIubWF4bGVuZ3RoXT1cIm1heExlbmd0aFwiXG4gICAgICBbbWluXT1cIm1pblwiXG4gICAgICBbbWF4XT1cIm1heFwiXG4gICAgICBbc3RlcF09XCJzdGVwXCJcbiAgICAgIFt2YWx1ZV09XCJ2YWx1ZVwiXG4gICAgICAoaW5wdXQpPVwib25JbnB1dCgkZXZlbnQpXCJcbiAgICAgIChmb2N1cyk9XCJoYW5kbGVGb2N1cygpXCJcbiAgICAgIChibHVyKT1cImhhbmRsZUJsdXIoKVwiXG4gICAgLz5cblxuICAgIDwhLS0gVGV4dGFyZWEgLS0+XG4gICAgPHRleHRhcmVhXG4gICAgICAqbmdJZj1cInR5cGUgPT09ICd0ZXh0YXJlYSdcIlxuICAgICAgW2NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiXG4gICAgICBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIlxuICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgIFtyZWFkb25seV09XCJyZWFkb25seVwiXG4gICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxuICAgICAgW2F0dHIubWF4bGVuZ3RoXT1cIm1heExlbmd0aFwiXG4gICAgICBbcm93c109XCJyb3dzXCJcbiAgICAgIFt2YWx1ZV09XCJ2YWx1ZVwiXG4gICAgICAoaW5wdXQpPVwib25JbnB1dCgkZXZlbnQpXCJcbiAgICAgIChmb2N1cyk9XCJoYW5kbGVGb2N1cygpXCJcbiAgICAgIChibHVyKT1cImhhbmRsZUJsdXIoKVwiPlxuICAgIDwvdGV4dGFyZWE+XG5cbiAgICA8IS0tIFNlbGVjdCAtLT5cbiAgICA8c2VsZWN0XG4gICAgICAqbmdJZj1cInR5cGUgPT09ICdzZWxlY3QnXCJcbiAgICAgIFtjbGFzc109XCJpbnB1dENsYXNzZXNcIlxuICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgIFtyZXF1aXJlZF09XCJyZXF1aXJlZFwiXG4gICAgICBbdmFsdWVdPVwidmFsdWVcIlxuICAgICAgKGNoYW5nZSk9XCJvbklucHV0KCRldmVudClcIlxuICAgICAgKGZvY3VzKT1cImhhbmRsZUZvY3VzKClcIlxuICAgICAgKGJsdXIpPVwiaGFuZGxlQmx1cigpXCI+XG4gICAgICA8b3B0aW9uIHZhbHVlPVwiXCIgZGlzYWJsZWQgKm5nSWY9XCJwbGFjZWhvbGRlclwiPnt7IHBsYWNlaG9sZGVyIH19PC9vcHRpb24+XG4gICAgICA8b3B0aW9uIFxuICAgICAgICAqbmdGb3I9XCJsZXQgb3B0aW9uIG9mIG9wdGlvbnNcIlxuICAgICAgICBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIm9wdGlvbi5kaXNhYmxlZFwiPlxuICAgICAgICB7eyBvcHRpb24ubGFiZWwgfX1cbiAgICAgIDwvb3B0aW9uPlxuICAgIDwvc2VsZWN0PlxuXG4gICAgPCEtLSBTdWZmaXggLS0+XG4gICAgPHNwYW4gY2xhc3M9XCJpbnB1dC1zdWZmaXhcIiAqbmdJZj1cInN1ZmZpeFwiPnt7IHN1ZmZpeCB9fTwvc3Bhbj5cbiAgPC9kaXY+XG5cbiAgPCEtLSBGb290ZXIgLS0+XG4gIDxkaXYgY2xhc3M9XCJpbnB1dC1mb290ZXJcIiAqbmdJZj1cImVycm9yIHx8IGhpbnQgfHwgKHNob3dDb3VudGVyICYmIG1heExlbmd0aClcIj5cbiAgICA8IS0tIEVycm9yIG1lc3NhZ2UgLS0+XG4gICAgPGRpdiBjbGFzcz1cImlucHV0LWVycm9yXCIgKm5nSWY9XCJlcnJvclwiPlxuICAgICAge3sgZXJyb3IgfX1cbiAgICA8L2Rpdj5cbiAgICBcbiAgICA8IS0tIEhpbnQgdGV4dCAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtaGludFwiICpuZ0lmPVwiaGludCAmJiAhZXJyb3JcIj5cbiAgICAgIHt7IGhpbnQgfX1cbiAgICA8L2Rpdj5cbiAgICBcbiAgICA8IS0tIENoYXJhY3RlciBjb3VudGVyIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1jb3VudGVyXCIgKm5nSWY9XCJzaG93Q291bnRlciAmJiBtYXhMZW5ndGggJiYgIWVycm9yXCI+XG4gICAgICB7eyBjaGFyYWN0ZXJDb3VudCB9fS97eyBtYXhMZW5ndGggfX1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj4gIl19