@acrodata/gui
Version:
JSON powered GUI for configurable panels.
75 lines • 15.7 kB
JavaScript
import { ChangeDetectionStrategy, Component, forwardRef, Input, ViewEncapsulation, } from '@angular/core';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { MatFormField, MatHint, MatPrefix, MatSuffix } from '@angular/material/form-field';
import { MatInput } from '@angular/material/input';
import { MtxColorpicker, MtxColorpickerInput, MtxColorpickerToggle, } from '@ng-matero/extensions/colorpicker';
import { GuiFieldLabel } from '../field-label/field-label';
import { GuiIconButtonWrapper } from '../icon-button-wrapper/icon-button-wrapper';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
export class GuiFill {
constructor(cdr) {
this.cdr = cdr;
this.config = {};
this.disabled = false;
this.value = '';
this.onChange = () => { };
this.onTouched = () => { };
}
writeValue(value) {
if (typeof value === 'string') {
this.value = value;
this.cdr.markForCheck();
}
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
this.cdr.markForCheck();
}
onValueChange() {
this.onChange(this.value);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiFill, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: GuiFill, isStandalone: true, selector: "gui-fill", inputs: { config: "config", disabled: "disabled" }, host: { classAttribute: "gui-field gui-fill" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => GuiFill),
multi: true,
},
], ngImport: i0, template: "<mat-form-field>\n <ng-container matPrefix>\n <span class=\"gui-color-block-empty\"></span>\n <span class=\"gui-color-block\" [style.background]=\"value\"></span>\n </ng-container>\n\n <input\n matInput\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"config.placeholder || ''\"\n [mtxColorpicker]=\"cp\"\n (colorChange)=\"onValueChange()\"\n />\n\n <mtx-colorpicker #cp />\n <gui-icon-button-wrapper matSuffix>\n <mtx-colorpicker-toggle [for]=\"cp\" />\n </gui-icon-button-wrapper>\n\n @if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n }\n</mat-form-field>\n", styles: [".gui-color-block,.gui-color-block-empty{position:relative;display:inline-block;width:1.5rem;height:1.5rem}.gui-color-block-empty{position:absolute;background-color:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-position:0 0,0 .25rem,.25rem -.25rem,-.25rem 0;background-size:.5rem .5rem}.gui-color-block:after{display:inline-block;width:100%;height:100%;box-sizing:border-box;border:1px solid currentColor;border-top-left-radius:var(--mdc-filled-text-field-container-shape);border-bottom-left-radius:var(--mdc-filled-text-field-container-shape);opacity:.12;content:\"\"}[dir=rtl] .gui-color-block:after{border-radius:0;border-top-right-radius:var(--mdc-filled-text-field-container-shape);border-bottom-right-radius:var(--mdc-filled-text-field-container-shape)}.gui-fill .mat-mdc-icon-button{display:inline-flex;justify-content:center;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MtxColorpickerInput, selector: "input[mtxColorpicker]", inputs: ["mtxColorpicker", "disabled", "value", "format"], outputs: ["colorChange", "colorInput"], exportAs: ["mtxColorpickerInput"] }, { kind: "component", type: MtxColorpicker, selector: "mtx-colorpicker", inputs: ["content", "disabled", "xPosition", "yPosition", "restoreFocus", "opened", "color", "format"], outputs: ["opened", "closed"], exportAs: ["mtxColorpicker"] }, { kind: "component", type: MtxColorpickerToggle, selector: "mtx-colorpicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["mtxColorpickerToggle"] }, { kind: "component", type: GuiFieldLabel, selector: "gui-field-label", inputs: ["config", "index"] }, { kind: "component", type: GuiIconButtonWrapper, selector: "gui-icon-button-wrapper" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GuiFill, decorators: [{
type: Component,
args: [{ selector: 'gui-fill', host: {
class: 'gui-field gui-fill',
}, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => GuiFill),
multi: true,
},
], standalone: true, imports: [
FormsModule,
MatFormField,
MatPrefix,
MatInput,
MatSuffix,
MatHint,
MtxColorpickerInput,
MtxColorpicker,
MtxColorpickerToggle,
GuiFieldLabel,
GuiIconButtonWrapper,
], template: "<mat-form-field>\n <ng-container matPrefix>\n <span class=\"gui-color-block-empty\"></span>\n <span class=\"gui-color-block\" [style.background]=\"value\"></span>\n </ng-container>\n\n <input\n matInput\n [(ngModel)]=\"value\"\n [disabled]=\"disabled\"\n [placeholder]=\"config.placeholder || ''\"\n [mtxColorpicker]=\"cp\"\n (colorChange)=\"onValueChange()\"\n />\n\n <mtx-colorpicker #cp />\n <gui-icon-button-wrapper matSuffix>\n <mtx-colorpicker-toggle [for]=\"cp\" />\n </gui-icon-button-wrapper>\n\n @if (config.parentType === 'inline') {\n <mat-hint>\n <gui-field-label [config]=\"config\" />\n </mat-hint>\n }\n</mat-form-field>\n", styles: [".gui-color-block,.gui-color-block-empty{position:relative;display:inline-block;width:1.5rem;height:1.5rem}.gui-color-block-empty{position:absolute;background-color:#fff;background-image:linear-gradient(45deg,#ccc 25%,transparent 25%),linear-gradient(-45deg,#ccc 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#ccc 75%),linear-gradient(-45deg,transparent 75%,#ccc 75%);background-position:0 0,0 .25rem,.25rem -.25rem,-.25rem 0;background-size:.5rem .5rem}.gui-color-block:after{display:inline-block;width:100%;height:100%;box-sizing:border-box;border:1px solid currentColor;border-top-left-radius:var(--mdc-filled-text-field-container-shape);border-bottom-left-radius:var(--mdc-filled-text-field-container-shape);opacity:.12;content:\"\"}[dir=rtl] .gui-color-block:after{border-radius:0;border-top-right-radius:var(--mdc-filled-text-field-container-shape);border-bottom-right-radius:var(--mdc-filled-text-field-container-shape)}.gui-fill .mat-mdc-icon-button{display:inline-flex;justify-content:center;align-items:center}\n"] }]
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { config: [{
type: Input
}], disabled: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2d1aS9maWxsL2ZpbGwudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9ndWkvZmlsbC9maWxsLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUV2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLEtBQUssRUFDTCxpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUF3QixXQUFXLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RixPQUFPLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDM0YsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFDTCxjQUFjLEVBQ2QsbUJBQW1CLEVBQ25CLG9CQUFvQixHQUNyQixNQUFNLG1DQUFtQyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQzs7O0FBa0NsRixNQUFNLE9BQU8sT0FBTztJQVNsQixZQUFvQixHQUFzQjtRQUF0QixRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQVJqQyxXQUFNLEdBQXdCLEVBQUUsQ0FBQztRQUNqQyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBRTFCLFVBQUssR0FBRyxFQUFFLENBQUM7UUFFSCxhQUFRLEdBQTRCLEdBQUcsRUFBRSxHQUFFLENBQUMsQ0FBQztRQUM3QyxjQUFTLEdBQWUsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDO0lBRUksQ0FBQztJQUU5QyxVQUFVLENBQUMsS0FBYTtRQUN0QixJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQzlCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1lBQ25CLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDMUIsQ0FBQztJQUNILENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxFQUEyQjtRQUMxQyxJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQsaUJBQWlCLENBQUMsRUFBYztRQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQsZ0JBQWdCLENBQUMsVUFBbUI7UUFDbEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUM7UUFDM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQsYUFBYTtRQUNYLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVCLENBQUM7K0dBakNVLE9BQU87bUdBQVAsT0FBTywySkF0QlA7WUFDVDtnQkFDRSxPQUFPLEVBQUUsaUJBQWlCO2dCQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQztnQkFDdEMsS0FBSyxFQUFFLElBQUk7YUFDWjtTQUNGLDBCQ25DSCwrcUJBMEJBLG1rQ0RZSSxXQUFXLCttQkFDWCxZQUFZLDRMQUNaLFNBQVMscUhBQ1QsUUFBUSxpVUFDUixTQUFTLHFIQUNULE9BQU8sOEVBQ1AsbUJBQW1CLHdNQUNuQixjQUFjLGlPQUNkLG9CQUFvQiwrS0FDcEIsYUFBYSx5RkFDYixvQkFBb0I7OzRGQUdYLE9BQU87a0JBL0JuQixTQUFTOytCQUNFLFVBQVUsUUFHZDt3QkFDSixLQUFLLEVBQUUsb0JBQW9CO3FCQUM1QixpQkFDYyxpQkFBaUIsQ0FBQyxJQUFJLG1CQUNwQix1QkFBdUIsQ0FBQyxNQUFNLGFBQ3BDO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQzs0QkFDdEMsS0FBSyxFQUFFLElBQUk7eUJBQ1o7cUJBQ0YsY0FDVyxJQUFJLFdBQ1A7d0JBQ1AsV0FBVzt3QkFDWCxZQUFZO3dCQUNaLFNBQVM7d0JBQ1QsUUFBUTt3QkFDUixTQUFTO3dCQUNULE9BQU87d0JBQ1AsbUJBQW1CO3dCQUNuQixjQUFjO3dCQUNkLG9CQUFvQjt3QkFDcEIsYUFBYTt3QkFDYixvQkFBb0I7cUJBQ3JCO3NGQUdRLE1BQU07c0JBQWQsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIGZvcndhcmRSZWYsXG4gIElucHV0LFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgRm9ybXNNb2R1bGUsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkLCBNYXRIaW50LCBNYXRQcmVmaXgsIE1hdFN1ZmZpeCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHsgTWF0SW5wdXQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XG5pbXBvcnQge1xuICBNdHhDb2xvcnBpY2tlcixcbiAgTXR4Q29sb3JwaWNrZXJJbnB1dCxcbiAgTXR4Q29sb3JwaWNrZXJUb2dnbGUsXG59IGZyb20gJ0BuZy1tYXRlcm8vZXh0ZW5zaW9ucy9jb2xvcnBpY2tlcic7XG5pbXBvcnQgeyBHdWlGaWVsZExhYmVsIH0gZnJvbSAnLi4vZmllbGQtbGFiZWwvZmllbGQtbGFiZWwnO1xuaW1wb3J0IHsgR3VpSWNvbkJ1dHRvbldyYXBwZXIgfSBmcm9tICcuLi9pY29uLWJ1dHRvbi13cmFwcGVyL2ljb24tYnV0dG9uLXdyYXBwZXInO1xuaW1wb3J0IHsgR3VpQ29udHJvbCB9IGZyb20gJy4uL2ludGVyZmFjZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2d1aS1maWxsJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2ZpbGwuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9maWxsLnNjc3MnLFxuICBob3N0OiB7XG4gICAgY2xhc3M6ICdndWktZmllbGQgZ3VpLWZpbGwnLFxuICB9LFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBHdWlGaWxsKSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gIF0sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBNYXRGb3JtRmllbGQsXG4gICAgTWF0UHJlZml4LFxuICAgIE1hdElucHV0LFxuICAgIE1hdFN1ZmZpeCxcbiAgICBNYXRIaW50LFxuICAgIE10eENvbG9ycGlja2VySW5wdXQsXG4gICAgTXR4Q29sb3JwaWNrZXIsXG4gICAgTXR4Q29sb3JwaWNrZXJUb2dnbGUsXG4gICAgR3VpRmllbGRMYWJlbCxcbiAgICBHdWlJY29uQnV0dG9uV3JhcHBlcixcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgR3VpRmlsbCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcbiAgQElucHV0KCkgY29uZmlnOiBQYXJ0aWFsPEd1aUNvbnRyb2w+ID0ge307XG4gIEBJbnB1dCgpIGRpc2FibGVkID0gZmFsc2U7XG5cbiAgdmFsdWUgPSAnJztcblxuICBwcml2YXRlIG9uQ2hhbmdlOiAodmFsdWU6IHN0cmluZykgPT4gdm9pZCA9ICgpID0+IHt9O1xuICBwcml2YXRlIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICB3cml0ZVZhbHVlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBzdHJpbmcpID0+IHZvaWQpIHtcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4gdm9pZCkge1xuICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gIH1cblxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pIHtcbiAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIG9uVmFsdWVDaGFuZ2UoKSB7XG4gICAgdGhpcy5vbkNoYW5nZSh0aGlzLnZhbHVlKTtcbiAgfVxufVxuIiwiPG1hdC1mb3JtLWZpZWxkPlxuICA8bmctY29udGFpbmVyIG1hdFByZWZpeD5cbiAgICA8c3BhbiBjbGFzcz1cImd1aS1jb2xvci1ibG9jay1lbXB0eVwiPjwvc3Bhbj5cbiAgICA8c3BhbiBjbGFzcz1cImd1aS1jb2xvci1ibG9ja1wiIFtzdHlsZS5iYWNrZ3JvdW5kXT1cInZhbHVlXCI+PC9zcGFuPlxuICA8L25nLWNvbnRhaW5lcj5cblxuICA8aW5wdXRcbiAgICBtYXRJbnB1dFxuICAgIFsobmdNb2RlbCldPVwidmFsdWVcIlxuICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgW3BsYWNlaG9sZGVyXT1cImNvbmZpZy5wbGFjZWhvbGRlciB8fCAnJ1wiXG4gICAgW210eENvbG9ycGlja2VyXT1cImNwXCJcbiAgICAoY29sb3JDaGFuZ2UpPVwib25WYWx1ZUNoYW5nZSgpXCJcbiAgLz5cblxuICA8bXR4LWNvbG9ycGlja2VyICNjcCAvPlxuICA8Z3VpLWljb24tYnV0dG9uLXdyYXBwZXIgbWF0U3VmZml4PlxuICAgIDxtdHgtY29sb3JwaWNrZXItdG9nZ2xlIFtmb3JdPVwiY3BcIiAvPlxuICA8L2d1aS1pY29uLWJ1dHRvbi13cmFwcGVyPlxuXG4gIEBpZiAoY29uZmlnLnBhcmVudFR5cGUgPT09ICdpbmxpbmUnKSB7XG4gICAgPG1hdC1oaW50PlxuICAgICAgPGd1aS1maWVsZC1sYWJlbCBbY29uZmlnXT1cImNvbmZpZ1wiIC8+XG4gICAgPC9tYXQtaGludD5cbiAgfVxuPC9tYXQtZm9ybS1maWVsZD5cbiJdfQ==