UNPKG

@ng-doc/app

Version:

<!-- PROJECT LOGO --> <br /> <div align="center"> <a href="https://github.com/ng-doc/ng-doc"> <img src="https://ng-doc.com/assets/images/ng-doc.svg?raw=true" alt="Logo" height="150px"> </a>

522 lines (514 loc) 42.8 kB
import * as i0 from '@angular/core'; import { inject, Injector, ChangeDetectorRef, ViewContainerRef, Component, ChangeDetectionStrategy, Input, ViewChild, HostBinding, EventEmitter, isDevMode, Output, Directive } from '@angular/core'; import { extractFunctionDefaults } from '@ng-doc/core/helpers/extract-function-defaults'; import { Subject, take } from 'rxjs'; import { AsyncPipe, NgIf, NgFor, KeyValuePipe } from '@angular/common'; import * as i2 from '@angular/forms'; import { FormsModule } from '@angular/forms'; import * as i1$1 from '@ng-doc/app/classes/root-page'; import { isSameObject } from '@ng-doc/core/helpers/is-same-object'; import { objectKeys } from '@ng-doc/core/helpers/object-keys'; import { NgDocSmoothResizeComponent, NgDocLetDirective, NgDocLabelComponent, NgDocTooltipDirective, NgDocTextComponent, NgDocButtonComponent, NgDocCheckboxComponent, NgDocIconComponent, NgDocTextRightDirective, NgDocBindPipe, NgDocExecutePipe, NgDocAsArrayPipe } from '@ng-doc/ui-kit'; import { __decorate } from 'tslib'; import { NgDocDemoDisplayerComponent } from '@ng-doc/app/components/demo-displayer'; import { formatHtml, isPlaygroundProperty } from '@ng-doc/app/helpers'; import { getPlaygroundDemoToken } from '@ng-doc/app/providers/playground-demo'; import { buildPlaygroundDemoPipeTemplate, buildPlaygroundDemoTemplate } from '@ng-doc/core/helpers/build-playground-demo-template'; import { stringify } from '@ng-doc/core/helpers/stringify'; import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy'; import { takeUntil, startWith, map } from 'rxjs/operators'; import * as i1 from '@angular/cdk/layout'; import { Breakpoints } from '@angular/cdk/layout'; import { getTokenForType } from '@ng-doc/app/providers/type-control'; import { extractValueOrThrow } from '@ng-doc/core/helpers/extract-value'; import { isPresent } from '@ng-doc/core/helpers/is-present'; import { NgDocSanitizeHtmlPipe } from '@ng-doc/app/pipes'; let NgDocPlaygroundDemoComponent = class NgDocPlaygroundDemoComponent { constructor() { this.id = ''; this.pipeName = ''; this.selector = ''; this.recreateDemo = false; this.expanded = false; this.code = ''; this.injector = inject(Injector); this.changeDetectorRef = inject(ChangeDetectorRef); this.unsubscribe$ = new Subject(); } async ngOnChanges({ form, id }) { if (form || id) { this.unsubscribe$.next(); const demoInjector = getPlaygroundDemoToken(this.id); if (demoInjector) { const demos = this.injector.get(demoInjector, []); this.playgroundDemo = demos.find((demo) => demo.selector === this.selector || demo.selector === this.pipeName); } await this.updateDemo(); this.form?.valueChanges .pipe(takeUntil(this.unsubscribe$), untilDestroyed(this), startWith(this.form?.value)) .subscribe((data) => this.updateDemo(data)); } } async updateDemo(data) { if (this.recreateDemo || !this.demoRef) { this.createDemo(); } if (data) { this.demoRef?.setInput('properties', data.properties ?? {}); this.demoRef?.setInput('content', data.content ?? {}); this.demoRef?.setInput('actionData', this.configuration?.data ?? {}); if (this.recreateDemo) { this.demoRef?.instance.onReattached.subscribe(() => { this.demoRef?.changeDetectorRef.detectChanges(); }); } } await this.updateCodeView(); } createDemo() { if (this.playgroundDemo) { this.demoRef?.destroy(); this.demoRef = this.demoOutlet?.createComponent(this.playgroundDemo); this.demoRef?.changeDetectorRef.markForCheck(); } } async updateCodeView() { const template = this.pipeName ? buildPlaygroundDemoPipeTemplate(this.configuration?.template ?? '', this.pipeName, this.getActiveContent(), this.getPipeActiveInputs()) : buildPlaygroundDemoTemplate(this.configuration?.template ?? '', this.selector, this.getActiveContent(), this.getActiveInputs()); this.code = await formatHtml(template); this.changeDetectorRef.markForCheck(); } getActiveContent() { const formData = this.form?.controls.content.value ?? {}; return objectKeys(formData).reduce((result, key) => { result[key] = formData[key] ? this.configuration?.content?.[key].template ?? '' : ''; return result; }, {}); } getActiveInputs() { const formData = this.form?.controls.properties.value ?? {}; return objectKeys(formData).reduce((result, key) => { const inputName = this.properties?.[key]?.inputName ?? key; const value = formData[key]; const property = this.demoRef?.instance?.defaultValues[key]; if (property !== value) { result[inputName] = stringify(value).replace(/"/g, `'`); } return result; }, {}); } getPipeActiveInputs() { const formData = this.form?.controls.properties.value ?? {}; let changedInputIndex = -1; return objectKeys(formData) .map((key, i) => { const value = formData[key]; const defaultValue = this.demoRef?.instance?.defaultValues[key]; if (defaultValue !== value) { changedInputIndex = i; } return key; }) .slice(0, changedInputIndex + 1) .reduce((result, key) => { result[key] = stringify(formData[key]).replace(/"/g, `'`); return result; }, {}); } ngOnDestroy() { this.unsubscribe$.next(); this.unsubscribe$.complete(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundDemoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: NgDocPlaygroundDemoComponent, isStandalone: true, selector: "ng-doc-playground-demo", inputs: { id: "id", pipeName: "pipeName", selector: "selector", configuration: "configuration", properties: "properties", recreateDemo: "recreateDemo", form: "form", expanded: "expanded" }, viewQueries: [{ propertyName: "demoOutlet", first: true, predicate: ["demoOutlet"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: "<ng-doc-smooth-resize [trigger]=\"code\">\n <ng-doc-demo-displayer\n [code]=\"code\"\n [border]=\"false\"\n [expanded]=\"expanded\"\n language=\"angular-html\">\n <ng-container #demoOutlet></ng-container>\n </ng-doc-demo-displayer>\n</ng-doc-smooth-resize>\n", styles: [":host{display:block;border:var(--ng-doc-demo-displayer-border);border-radius:var(--ng-doc-demo-displayer-border-radius);overflow:hidden}:host:not(:last-child){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}:host:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}\n"], dependencies: [{ kind: "component", type: NgDocDemoDisplayerComponent, selector: "ng-doc-demo-displayer", inputs: ["codeContent", "code", "language", "container", "border", "expanded"] }, { kind: "component", type: NgDocSmoothResizeComponent, selector: "ng-doc-smooth-resize", inputs: ["trigger", "animateOpacity"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } }; NgDocPlaygroundDemoComponent = __decorate([ UntilDestroy() ], NgDocPlaygroundDemoComponent); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundDemoComponent, decorators: [{ type: Component, args: [{ selector: 'ng-doc-playground-demo', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgDocDemoDisplayerComponent, AsyncPipe, NgDocSmoothResizeComponent, NgDocLetDirective], template: "<ng-doc-smooth-resize [trigger]=\"code\">\n <ng-doc-demo-displayer\n [code]=\"code\"\n [border]=\"false\"\n [expanded]=\"expanded\"\n language=\"angular-html\">\n <ng-container #demoOutlet></ng-container>\n </ng-doc-demo-displayer>\n</ng-doc-smooth-resize>\n", styles: [":host{display:block;border:var(--ng-doc-demo-displayer-border);border-radius:var(--ng-doc-demo-displayer-border-radius);overflow:hidden}:host:not(:last-child){border-bottom:0;border-bottom-left-radius:0;border-bottom-right-radius:0}:host:not(:first-child){border-top-left-radius:0;border-top-right-radius:0}\n"] }] }], propDecorators: { id: [{ type: Input }], pipeName: [{ type: Input }], selector: [{ type: Input }], configuration: [{ type: Input }], properties: [{ type: Input }], recreateDemo: [{ type: Input }], form: [{ type: Input }], expanded: [{ type: Input }], demoOutlet: [{ type: ViewChild, args: ['demoOutlet', { static: true, read: ViewContainerRef }] }] } }); class NgDocPlaygroundPropertyComponent { constructor() { this.name = ''; } ngOnChanges({ property, control, typeControl, defaultValue }) { if ((property || control || typeControl || defaultValue) && this.property && this.typeControl) { this.propertyTypeControl?.destroy(); this.propertyTypeControl = undefined; if (this.typeControl && this.propertyOutlet) { this.propertyTypeControl = this.propertyOutlet.createComponent(this.typeControl.control); this.propertyTypeControl.instance.name = this.name; this.propertyTypeControl.instance.description = this.tooltipContent; this.propertyTypeControl.instance.options = isPlaygroundProperty(this.property) ? this.property.options : undefined; this.propertyTypeControl.instance.default = this.defaultValue; this.propertyTypeControl.instance.isManual = isPlaygroundProperty(this.property) ? this.property.isManual : undefined; this.propertyTypeControl.instance.writeValue(this.control?.value); this.option = this.typeControl.options; } if (this.control) { this.control?.registerOnChange((value) => this.propertyTypeControl?.instance?.writeValue(value)); this.propertyTypeControl?.instance.registerOnChange((value) => this.control?.setValue(value)); this.propertyTypeControl?.instance.registerOnTouched(() => this.control?.markAsTouched()); } } } get hasPropertyControl() { return !!this.propertyTypeControl; } get tooltipContent() { return this.property && isPlaygroundProperty(this.property) ? this.property.description ?? '' : ''; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundPropertyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: NgDocPlaygroundPropertyComponent, isStandalone: true, selector: "ng-doc-playground-property", inputs: { name: "name", property: "property", typeControl: "typeControl", control: "control", defaultValue: "defaultValue" }, host: { properties: { "attr.data-has-property-control": "this.hasPropertyControl" } }, viewQueries: [{ propertyName: "propertyOutlet", first: true, predicate: ["propertyOutlet"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: "<label [ng-doc-label]=\"option?.hideLabel ? '' : labelContent\">\n\t<ng-template #labelContent>\n\t\t<span\n\t\t\t[ngDocTooltip]=\"tooltipTemplate\"\n\t\t\t[canOpen]=\"!!tooltipContent\"\n\t\t\t[positions]=\"['left-center', 'top-right', 'bottom-right']\"\n\t\t\t>{{ name }}</span\n\t\t>\n\t\t<ng-template #tooltipTemplate>\n\t\t\t<div [innerHTML]=\"tooltipContent | ngDocSanitizeHtml\"></div>\n\t\t</ng-template>\n\t</ng-template>\n\t<ng-container #propertyOutlet></ng-container>\n</label>\n", styles: [":host{display:block}:host[data-has-property-control=false]{display:none}\n"], dependencies: [{ kind: "component", type: NgDocLabelComponent, selector: "label[ng-doc-label]", inputs: ["ng-doc-label", "align"] }, { kind: "directive", type: NgDocTooltipDirective, selector: "[ngDocTooltip]", inputs: ["ngDocTooltip", "delay", "displayOrigin", "pointerOrigin", "positions", "canOpen", "panelClass", "minHeight", "maxHeight", "height", "minWidth", "maxWidth", "width"], outputs: ["beforeOpen", "afterOpen", "beforeClose", "afterClose"], exportAs: ["ngDocTooltip"] }, { kind: "pipe", type: NgDocSanitizeHtmlPipe, name: "ngDocSanitizeHtml" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundPropertyComponent, decorators: [{ type: Component, args: [{ selector: 'ng-doc-playground-property', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgDocLabelComponent, NgDocTooltipDirective, NgDocSanitizeHtmlPipe], template: "<label [ng-doc-label]=\"option?.hideLabel ? '' : labelContent\">\n\t<ng-template #labelContent>\n\t\t<span\n\t\t\t[ngDocTooltip]=\"tooltipTemplate\"\n\t\t\t[canOpen]=\"!!tooltipContent\"\n\t\t\t[positions]=\"['left-center', 'top-right', 'bottom-right']\"\n\t\t\t>{{ name }}</span\n\t\t>\n\t\t<ng-template #tooltipTemplate>\n\t\t\t<div [innerHTML]=\"tooltipContent | ngDocSanitizeHtml\"></div>\n\t\t</ng-template>\n\t</ng-template>\n\t<ng-container #propertyOutlet></ng-container>\n</label>\n", styles: [":host{display:block}:host[data-has-property-control=false]{display:none}\n"] }] }], propDecorators: { name: [{ type: Input }], property: [{ type: Input }], typeControl: [{ type: Input }], control: [{ type: Input }], defaultValue: [{ type: Input }], propertyOutlet: [{ type: ViewChild, args: ['propertyOutlet', { read: ViewContainerRef, static: true }] }], hasPropertyControl: [{ type: HostBinding, args: ['attr.data-has-property-control'] }] } }); class NgDocPlaygroundPropertiesComponent { constructor(breakpointObserver, injector) { this.breakpointObserver = breakpointObserver; this.injector = injector; this.ignoreInputs = []; this.hideSidePanel = false; this.recreateDemo = false; this.showResetButton = false; this.recreateDemoChange = new EventEmitter(); this.resetForm = new EventEmitter(); this.breakpoints = [Breakpoints.XSmall]; this.propertyControls = []; this.contentTypeControl = this.getControlForType('boolean'); this.observer = this.breakpointObserver .observe(this.breakpoints) .pipe(map((state) => state.matches)); } ngOnChanges({ properties }) { if (properties && this.properties) { this.propertyControls = objectKeys(this.properties) .filter((key) => this.ignoreInputs?.includes(String(key)) !== true) .map((key) => { if (this.properties) { const property = this.properties[key]; const typeControl = this.getTypeControl(property); if (typeControl) { return { propertyName: String(key), property, typeControl, }; } } return null; }) .filter(isPresent) .sort((a, b) => { const aOrder = a.typeControl.options?.order; const bOrder = b.typeControl.options?.order; if (isPresent(aOrder) && isPresent(bOrder)) { return aOrder - bOrder; } if (isPresent(aOrder)) { return -1; } if (isPresent(bOrder)) { return 1; } return a.property.inputName.localeCompare(b.property.inputName); }); } } getFormControl(controlType, key) { return this.form.get(controlType)?.get(key); } getTypeControl(property) { const type = property.type; const typeControl = this.getControlForType(type) ?? this.getControlForTypeAlias(isPlaygroundProperty(property) ? property.options : undefined, property.isManual); if (!typeControl && isDevMode()) { console.warn(`NgDocPlayground didn't find the control for the @Input "${property.inputName}", the type "${type}" was not recognized'`); } return typeControl; } getControlForType(type) { const token = getTokenForType(type); return token ? this.injector.get(token) : undefined; } getControlForTypeAlias(options, isManual) { if (options && options.length) { let optionsIsValid = true; if (!isManual) { try { // checking that all values are extractable options.forEach((item) => extractValueOrThrow(item)); } catch { optionsIsValid = false; } } if (optionsIsValid) { const token = getTokenForType('NgDocTypeAlias'); return token ? this.injector.get(token) : undefined; } } return undefined; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundPropertiesComponent, deps: [{ token: i1.BreakpointObserver }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: NgDocPlaygroundPropertiesComponent, isStandalone: true, selector: "ng-doc-playground-properties", inputs: { form: "form", properties: "properties", ignoreInputs: "ignoreInputs", dynamicContent: "dynamicContent", defaultValues: "defaultValues", hideSidePanel: "hideSidePanel", recreateDemo: "recreateDemo", showResetButton: "showResetButton" }, outputs: { recreateDemoChange: "recreateDemoChange", resetForm: "resetForm" }, usesOnChanges: true, ngImport: i0, template: "<div\n\tclass=\"ng-doc-playground-properties-wrapper\"\n\t[class.vertical]=\"observer | async\"\n\t*ngIf=\"defaultValues\">\n\t<div class=\"ng-doc-playground-demos\">\n\t\t<ng-content></ng-content>\n\t</div>\n\t<div class=\"ng-doc-playground-properties\" *ngIf=\"!hideSidePanel\">\n\t\t<div class=\"ng-doc-playground-header\">\n\t\t\t<h4 ng-doc-text>Playground</h4>\n\t\t\t<button ng-doc-button color=\"alert\" (click)=\"resetForm.emit()\" *ngIf=\"showResetButton\">\n\t\t\t\tReset\n\t\t\t</button>\n\t\t</div>\n\t\t<div class=\"ng-doc-playground-setting\">\n\t\t\t<ng-doc-checkbox [(ngModel)]=\"recreateDemo\" (ngModelChange)=\"recreateDemoChange.emit($event)\">\n\t\t\t\t<span\n\t\t\t\t\tng-doc-text\n\t\t\t\t\t[ngDocTooltip]=\"'Recreates demo everytime\\none of the input has changed'\"\n\t\t\t\t\t[positions]=\"['bottom-right', 'left-center']\">\n\t\t\t\t\tRecreate\n\t\t\t\t\t<ng-doc-icon icon=\"info\" ngDocTextRight></ng-doc-icon>\n\t\t\t\t</span>\n\t\t\t</ng-doc-checkbox>\n\t\t</div>\n\t\t<div class=\"ng-doc-playground-divider\"></div>\n\t\t<ng-container *ngIf=\"propertyControls.length\">\n\t\t\t<h5 class=\"ng-doc-title\" ng-doc-text>Settings</h5>\n\t\t\t<ng-doc-playground-property\n\t\t\t\t*ngFor=\"let propertyControl of propertyControls\"\n\t\t\t\t[name]=\"propertyControl.property.inputName\"\n\t\t\t\t[property]=\"propertyControl.property\"\n\t\t\t\t[typeControl]=\"propertyControl.typeControl\"\n\t\t\t\t[defaultValue]=\"defaultValues[propertyControl.propertyName]\"\n\t\t\t\t[control]=\"\n\t\t\t\t\tgetFormControl | bind: this | execute: 'properties':propertyControl.propertyName\n\t\t\t\t\">\n\t\t\t</ng-doc-playground-property>\n\t\t</ng-container>\n\n\t\t<ng-container *ngIf=\"(dynamicContent | keyvalue)?.length\">\n\t\t\t<h5 class=\"ng-doc-title\" ng-doc-text>Content</h5>\n\t\t\t<ng-doc-playground-property\n\t\t\t\t*ngFor=\"let content of dynamicContent | keyvalue\"\n\t\t\t\t[name]=\"content.value.label\"\n\t\t\t\t[property]=\"content.value\"\n\t\t\t\t[typeControl]=\"contentTypeControl\"\n\t\t\t\t[control]=\"getFormControl | bind: this | execute: 'content':content.key\">\n\t\t\t</ng-doc-playground-property>\n\t\t</ng-container>\n\t</div>\n</div>\n", styles: [":host .ng-doc-playground-properties-wrapper{position:relative;display:flex;align-items:flex-start;gap:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper.vertical{flex-direction:column}:host .ng-doc-playground-properties-wrapper.vertical .ng-doc-playground-demos{margin-right:0;margin-bottom:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper.vertical .ng-doc-playground-properties{width:100%}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-demos{position:sticky;display:flex;flex-direction:column;width:100%;min-width:0;z-index:4;top:calc(var(--ng-doc-page-sticky-offset) + var(--ng-doc-base-gutter))}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties{flex-shrink:0;align-self:normal;width:300px;padding:calc(var(--ng-doc-base-gutter) * 2) calc(var(--ng-doc-base-gutter) * 3);background-color:var(--ng-doc-base-1);border-radius:var(--ng-doc-base-gutter);border:1px solid var(--ng-doc-border-color)}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties ng-doc-playground-property:not(:last-child){margin-bottom:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-controls{display:flex;justify-content:flex-end}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-header{display:flex;align-items:center;justify-content:space-between;height:40px;margin-bottom:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-header h4{margin:0}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-setting{display:flex;flex-direction:column}:host .ng-doc-playground-properties-wrapper .ng-doc-title{margin-top:0;margin-bottom:calc(var(--ng-doc-base-gutter) + var(--ng-doc-base-gutter) / 2)}:host .ng-doc-playground-divider{margin:calc(var(--ng-doc-base-gutter) * 2) 0;height:1px;background-color:var(--ng-doc-base-2)}\n"], dependencies: [{ kind: "component", type: NgDocTextComponent, selector: "[ng-doc-text]", inputs: ["size", "color", "align", "absoluteContent"] }, { kind: "component", type: NgDocButtonComponent, selector: "button[ng-doc-button], a[ng-doc-button], button[ng-doc-button-flat], a[ng-doc-button-flat], button[ng-doc-button-text], a[ng-doc-button-text]", inputs: ["size", "color", "rounded"] }, { kind: "component", type: NgDocCheckboxComponent, selector: "ng-doc-checkbox", inputs: ["color"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgDocTooltipDirective, selector: "[ngDocTooltip]", inputs: ["ngDocTooltip", "delay", "displayOrigin", "pointerOrigin", "positions", "canOpen", "panelClass", "minHeight", "maxHeight", "height", "minWidth", "maxWidth", "width"], outputs: ["beforeOpen", "afterOpen", "beforeClose", "afterClose"], exportAs: ["ngDocTooltip"] }, { kind: "component", type: NgDocIconComponent, selector: "ng-doc-icon", inputs: ["icon", "customIcon", "size"] }, { kind: "directive", type: NgDocTextRightDirective, selector: "[ngDocTextRight]" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: NgDocPlaygroundPropertyComponent, selector: "ng-doc-playground-property", inputs: ["name", "property", "typeControl", "control", "defaultValue"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: NgDocBindPipe, name: "bind" }, { kind: "pipe", type: NgDocExecutePipe, name: "execute" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundPropertiesComponent, decorators: [{ type: Component, args: [{ selector: 'ng-doc-playground-properties', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ NgDocTextComponent, NgDocButtonComponent, NgDocCheckboxComponent, FormsModule, NgDocTooltipDirective, NgDocIconComponent, NgDocTextRightDirective, NgIf, NgFor, NgDocPlaygroundPropertyComponent, AsyncPipe, KeyValuePipe, NgDocBindPipe, NgDocExecutePipe, ], template: "<div\n\tclass=\"ng-doc-playground-properties-wrapper\"\n\t[class.vertical]=\"observer | async\"\n\t*ngIf=\"defaultValues\">\n\t<div class=\"ng-doc-playground-demos\">\n\t\t<ng-content></ng-content>\n\t</div>\n\t<div class=\"ng-doc-playground-properties\" *ngIf=\"!hideSidePanel\">\n\t\t<div class=\"ng-doc-playground-header\">\n\t\t\t<h4 ng-doc-text>Playground</h4>\n\t\t\t<button ng-doc-button color=\"alert\" (click)=\"resetForm.emit()\" *ngIf=\"showResetButton\">\n\t\t\t\tReset\n\t\t\t</button>\n\t\t</div>\n\t\t<div class=\"ng-doc-playground-setting\">\n\t\t\t<ng-doc-checkbox [(ngModel)]=\"recreateDemo\" (ngModelChange)=\"recreateDemoChange.emit($event)\">\n\t\t\t\t<span\n\t\t\t\t\tng-doc-text\n\t\t\t\t\t[ngDocTooltip]=\"'Recreates demo everytime\\none of the input has changed'\"\n\t\t\t\t\t[positions]=\"['bottom-right', 'left-center']\">\n\t\t\t\t\tRecreate\n\t\t\t\t\t<ng-doc-icon icon=\"info\" ngDocTextRight></ng-doc-icon>\n\t\t\t\t</span>\n\t\t\t</ng-doc-checkbox>\n\t\t</div>\n\t\t<div class=\"ng-doc-playground-divider\"></div>\n\t\t<ng-container *ngIf=\"propertyControls.length\">\n\t\t\t<h5 class=\"ng-doc-title\" ng-doc-text>Settings</h5>\n\t\t\t<ng-doc-playground-property\n\t\t\t\t*ngFor=\"let propertyControl of propertyControls\"\n\t\t\t\t[name]=\"propertyControl.property.inputName\"\n\t\t\t\t[property]=\"propertyControl.property\"\n\t\t\t\t[typeControl]=\"propertyControl.typeControl\"\n\t\t\t\t[defaultValue]=\"defaultValues[propertyControl.propertyName]\"\n\t\t\t\t[control]=\"\n\t\t\t\t\tgetFormControl | bind: this | execute: 'properties':propertyControl.propertyName\n\t\t\t\t\">\n\t\t\t</ng-doc-playground-property>\n\t\t</ng-container>\n\n\t\t<ng-container *ngIf=\"(dynamicContent | keyvalue)?.length\">\n\t\t\t<h5 class=\"ng-doc-title\" ng-doc-text>Content</h5>\n\t\t\t<ng-doc-playground-property\n\t\t\t\t*ngFor=\"let content of dynamicContent | keyvalue\"\n\t\t\t\t[name]=\"content.value.label\"\n\t\t\t\t[property]=\"content.value\"\n\t\t\t\t[typeControl]=\"contentTypeControl\"\n\t\t\t\t[control]=\"getFormControl | bind: this | execute: 'content':content.key\">\n\t\t\t</ng-doc-playground-property>\n\t\t</ng-container>\n\t</div>\n</div>\n", styles: [":host .ng-doc-playground-properties-wrapper{position:relative;display:flex;align-items:flex-start;gap:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper.vertical{flex-direction:column}:host .ng-doc-playground-properties-wrapper.vertical .ng-doc-playground-demos{margin-right:0;margin-bottom:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper.vertical .ng-doc-playground-properties{width:100%}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-demos{position:sticky;display:flex;flex-direction:column;width:100%;min-width:0;z-index:4;top:calc(var(--ng-doc-page-sticky-offset) + var(--ng-doc-base-gutter))}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties{flex-shrink:0;align-self:normal;width:300px;padding:calc(var(--ng-doc-base-gutter) * 2) calc(var(--ng-doc-base-gutter) * 3);background-color:var(--ng-doc-base-1);border-radius:var(--ng-doc-base-gutter);border:1px solid var(--ng-doc-border-color)}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties ng-doc-playground-property:not(:last-child){margin-bottom:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-controls{display:flex;justify-content:flex-end}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-header{display:flex;align-items:center;justify-content:space-between;height:40px;margin-bottom:calc(var(--ng-doc-base-gutter) * 2)}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-header h4{margin:0}:host .ng-doc-playground-properties-wrapper .ng-doc-playground-properties .ng-doc-playground-setting{display:flex;flex-direction:column}:host .ng-doc-playground-properties-wrapper .ng-doc-title{margin-top:0;margin-bottom:calc(var(--ng-doc-base-gutter) + var(--ng-doc-base-gutter) / 2)}:host .ng-doc-playground-divider{margin:calc(var(--ng-doc-base-gutter) * 2) 0;height:1px;background-color:var(--ng-doc-base-2)}\n"] }] }], ctorParameters: () => [{ type: i1.BreakpointObserver }, { type: i0.Injector }], propDecorators: { form: [{ type: Input }], properties: [{ type: Input }], ignoreInputs: [{ type: Input }], dynamicContent: [{ type: Input }], defaultValues: [{ type: Input }], hideSidePanel: [{ type: Input }], recreateDemo: [{ type: Input }], showResetButton: [{ type: Input }], recreateDemoChange: [{ type: Output }], resetForm: [{ type: Output }] } }); class NgDocPlaygroundComponent { constructor(rootPage, formBuilder) { this.rootPage = rootPage; this.formBuilder = formBuilder; this.id = ''; this.pipeName = ''; this.selectors = []; this.options = {}; this.recreateDemo = false; this.defaultProperties = {}; this.defaultContent = {}; } ngOnChanges({ options }) { if (options) { // Join configuration with options this.configuration = Object.assign({}, this.rootPage.page?.playgrounds?.[this.id], this.options); } } ngAfterViewInit() { this.defaultProperties = this.getPropertiesFormValues(); this.defaultContent = this.getContentFormValues(); const propertiesForm = this.formBuilder.group(this.defaultProperties); const contentForm = this.formBuilder.group(this.defaultContent); this.formGroup = this.formBuilder.group({ properties: propertiesForm, content: contentForm, }); // `patchValue` is needed to set `undefined` values, otherwise they will be ignored by the Angular form this.formGroup.patchValue({ properties: Object.assign({}, this.defaultProperties, this.configuration.inputs), content: this.defaultContent, }); } isDefaultState() { if (!this.formGroup) { return false; } return (isSameObject(this.formGroup.value.properties ?? {}, this.defaultValues ?? {}) && isSameObject(this.formGroup.value.content ?? {}, this.defaultContent ?? {})); } getPropertiesFormValues() { const formValues = objectKeys(this.properties ?? {}).reduce((controls, key) => { if (this.properties) { controls[key] = this.defaultValues ? this.defaultValues[key] : undefined; } return controls; }, {}); return Object.assign({}, formValues, this.configuration.defaults); } getContentFormValues() { return objectKeys(this.configuration?.content ?? {}).reduce((controls, key) => { if (this.configuration?.content) { controls[key] = false; } return controls; }, {}); } resetForm() { this.formGroup.reset({}, { emitEvent: false }); this.formGroup?.patchValue({ properties: this.defaultProperties, content: this.defaultContent, }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundComponent, deps: [{ token: i1$1.NgDocRootPage }, { token: i2.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.0.3", type: NgDocPlaygroundComponent, isStandalone: true, selector: "ng-doc-playground", inputs: { id: "id", pipeName: "pipeName", selectors: "selectors", properties: "properties", options: "options" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"configuration\">\n <ng-doc-playground-properties\n [form]=\"formGroup\"\n [properties]=\"properties\"\n [ignoreInputs]=\"configuration.hiddenInputs\"\n [dynamicContent]=\"configuration.content\"\n [hideSidePanel]=\"configuration.hideSidePanel ?? false\"\n [defaultValues]=\"defaultValues\"\n [showResetButton]=\"!isDefaultState()\"\n [(recreateDemo)]=\"recreateDemo\"\n (resetForm)=\"resetForm()\">\n <ng-doc-playground-demo\n *ngFor=\"let selector of configuration.selectors ?? selectors | asArray\"\n [id]=\"id\"\n [selector]=\"selector\"\n [properties]=\"properties\"\n [configuration]=\"configuration\"\n [recreateDemo]=\"recreateDemo\"\n [form]=\"formGroup\"\n [expanded]=\"configuration.expanded ?? false\">\n </ng-doc-playground-demo>\n\n <ng-doc-playground-demo\n *ngIf=\"pipeName\"\n [id]=\"id\"\n [pipeName]=\"pipeName\"\n [properties]=\"properties\"\n [configuration]=\"configuration\"\n [recreateDemo]=\"recreateDemo\"\n [form]=\"formGroup\">\n </ng-doc-playground-demo>\n </ng-doc-playground-properties>\n</ng-container>\n", styles: [":host{display:block;margin:var(--ng-doc-playground-margin)}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: NgDocPlaygroundPropertiesComponent, selector: "ng-doc-playground-properties", inputs: ["form", "properties", "ignoreInputs", "dynamicContent", "defaultValues", "hideSidePanel", "recreateDemo", "showResetButton"], outputs: ["recreateDemoChange", "resetForm"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: NgDocPlaygroundDemoComponent, selector: "ng-doc-playground-demo", inputs: ["id", "pipeName", "selector", "configuration", "properties", "recreateDemo", "form", "expanded"] }, { kind: "pipe", type: NgDocAsArrayPipe, name: "asArray" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocPlaygroundComponent, decorators: [{ type: Component, args: [{ selector: 'ng-doc-playground', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ NgIf, NgDocPlaygroundPropertiesComponent, NgFor, NgDocPlaygroundDemoComponent, NgDocAsArrayPipe, ], template: "<ng-container *ngIf=\"configuration\">\n <ng-doc-playground-properties\n [form]=\"formGroup\"\n [properties]=\"properties\"\n [ignoreInputs]=\"configuration.hiddenInputs\"\n [dynamicContent]=\"configuration.content\"\n [hideSidePanel]=\"configuration.hideSidePanel ?? false\"\n [defaultValues]=\"defaultValues\"\n [showResetButton]=\"!isDefaultState()\"\n [(recreateDemo)]=\"recreateDemo\"\n (resetForm)=\"resetForm()\">\n <ng-doc-playground-demo\n *ngFor=\"let selector of configuration.selectors ?? selectors | asArray\"\n [id]=\"id\"\n [selector]=\"selector\"\n [properties]=\"properties\"\n [configuration]=\"configuration\"\n [recreateDemo]=\"recreateDemo\"\n [form]=\"formGroup\"\n [expanded]=\"configuration.expanded ?? false\">\n </ng-doc-playground-demo>\n\n <ng-doc-playground-demo\n *ngIf=\"pipeName\"\n [id]=\"id\"\n [pipeName]=\"pipeName\"\n [properties]=\"properties\"\n [configuration]=\"configuration\"\n [recreateDemo]=\"recreateDemo\"\n [form]=\"formGroup\">\n </ng-doc-playground-demo>\n </ng-doc-playground-properties>\n</ng-container>\n", styles: [":host{display:block;margin:var(--ng-doc-playground-margin)}\n"] }] }], ctorParameters: () => [{ type: i1$1.NgDocRootPage }, { type: i2.FormBuilder }], propDecorators: { id: [{ type: Input, args: [{ required: true }] }], pipeName: [{ type: Input }], selectors: [{ type: Input }], properties: [{ type: Input }], options: [{ type: Input }] } }); /** * Base class for playgrounds components. */ class NgDocBasePlayground { static { this.selector = 'unknown'; } constructor(playgroundInstance) { this.playgroundInstance = playgroundInstance; this.properties = {}; this.actionData = {}; this.content = {}; this.defaultValues = {}; this.reattached = new Subject(); this.playgroundContainer = inject(NgDocPlaygroundComponent); this.changeDetectorRef = inject(ChangeDetectorRef); this.changeDetectorRef.detach(); } get onReattached() { return this.reattached.pipe(take(1)); } ngOnInit() { /* * Extract default values from playground properties. We do this in `ngOnInit` because in this case * input values provided from the template are not initialized yet, and we can read default values instead. */ if (this.playground) { this.defaultValues = Object.keys(this.playground).reduce((values, key) => { if (this.playground) { try { values[key] = // @ts-expect-error we do not know the type of the playground typeof this.playground[key] === 'function' ? // @ts-expect-error we do not know the type of the playground this.playground[key]() : // @ts-expect-error we do not know the type of the playground this.playground[key]; } catch (e) { // we do catch here because some of the playground properties can be getters and throw an error } } return values; }, {}); } else if (this.playgroundInstance) { const defaults = extractFunctionDefaults(this.playgroundInstance.prototype.transform); this.defaultValues = Object.keys(this.playgroundContainer.properties ?? {}).reduce((def, key, i) => { // we do +1 because the first argument is the `value` of the transform function def[key] = defaults[i + 1]; return def; }, {}); } else { throw new Error('Playground is not defined or initialized'); } if (!this.playgroundContainer.defaultValues) { this.playgroundContainer.defaultValues = this.defaultValues; } /* This is a hack just to wait for the playground container to be initialized and only then attach the change detector to have correct inputs values. */ Promise.resolve().then(() => { this.changeDetectorRef.reattach(); this.reattached.next(); }); } get data() { return Object.assign({}, this.configData, this.actionData); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocBasePlayground, deps: "invalid", target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.3", type: NgDocBasePlayground, isStandalone: true, inputs: { properties: "properties", actionData: "actionData", content: "content" }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: NgDocBasePlayground, decorators: [{ type: Directive }], ctorParameters: () => [{ type: undefined }], propDecorators: { properties: [{ type: Input }], actionData: [{ type: Input }], content: [{ type: Input }] } }); /** * Generated bundle index. Do not edit. */ export { NgDocBasePlayground, NgDocPlaygroundComponent, NgDocPlaygroundDemoComponent, NgDocPlaygroundPropertiesComponent, NgDocPlaygroundPropertyComponent }; //# sourceMappingURL=ng-doc-app-components-playground.mjs.map