UNPKG

ngx-json-ui

Version:

This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.2.0.

752 lines (727 loc) 217 kB
import * as i0 from '@angular/core'; import { HostBinding, Input, Directive, Component, Injectable, Pipe, ViewContainerRef, ViewChild, ChangeDetectionStrategy, InjectionToken, HostListener, Inject, ViewChildren, Optional, SimpleChange, NgModule } from '@angular/core'; import * as i1$1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i1$3 from '@angular/cdk/overlay'; import { OverlayConfig, OverlayModule } from '@angular/cdk/overlay'; import { ComponentPortal } from '@angular/cdk/portal'; import * as i1 from '@angular/platform-browser'; import * as i2 from '@angular/forms'; import { FormGroup, FormArray, FormControl, ReactiveFormsModule, FormsModule } from '@angular/forms'; import { BehaviorSubject, Subject, of, takeUntil as takeUntil$1, throwError, Observable, map } from 'rxjs'; import { takeUntil, catchError, finalize } from 'rxjs/operators'; import * as i1$2 from '@angular/common/http'; import { HttpParams, provideHttpClient, HTTP_INTERCEPTORS, withInterceptorsFromDi, HttpHeaders } from '@angular/common/http'; import Inputmask from 'inputmask'; import * as Joi from 'joi'; import * as i1$4 from '@angular/router'; //implementing Json classes to overall component function convertStringArrayIntoString(defaultClassName, classList) { // If classList is undefine, null or empty or not type of string array return defaultClassName if (!classList || classList.length === 0 || !Array.isArray(classList)) return defaultClassName; // Join classList string array with help of empty string and return as string return classList.join(' '); } class BaseComponent { constructor(sanitizer) { this.sanitizer = sanitizer; /** Binds to the host element’s `class` attr */ this.hostClasses = ''; /** Binds to the host element’s `style` attr */ this.hostStyles = ''; /** Binds to the element’s `class` attr */ this.classes = ''; /** Binds to the element’s `style` attr */ this.styles = null; } /** * This method applies host configuration to the component. * It takes an object with hostClass and hostStyle properties. * It converts the hostClass to a string * and assigns it to the hostClasses property. * It also assigns the hostStyle to the hostStyles property. * @param {ComponentModel} param0 - The host configuration object. * @param {string} param0.hostClass - The class to be applied to the host element. * @param {string} param0.hostStyle - The style to be applied to the host element. * @returns {void} * @protected */ applyHostConfig({ hostClass, hostStyle }) { // Convert to string if it's an array or null/undefined // If it's a string, use it directly. If it's null/undefined, use an empty string. this.hostClasses = typeof hostClass === 'string' ? hostClass : convertStringArrayIntoString('base', hostClass ?? []); // Convert to string if it's an array or null/undefined // If it's a string, use it directly. If it's null/undefined, use an empty string. this.hostStyles = typeof hostStyle === 'string' ? hostStyle : ''; this.hostStyles = this.stringifyStyles(hostStyle) || ''; } applyHostConfigViaClassStyle(config) { // Convert to string if it's an array or null/undefined // If it's a string, use it directly. If it's null/undefined, use an empty string. this.hostClasses = typeof config.class === 'string' ? config.class : convertStringArrayIntoString('base', config.class ?? []); // Convert to string if it's an array or null/undefined // If it's a string, use it directly. If it's null/undefined, use an empty string. this.hostStyles = this.stringifyStyles(config.style) ?? ''; } /** * Converts a style‐object to a CSS string for HostBinding * This is useful for applying styles dynamically to the host element. * @param {Record<string,string> | null} [styles] - The styles to be converted to a CSS string. * @return {string} - The CSS string representation of the styles. * @private */ stringifyStyles(styles) { if (typeof styles === 'string') return styles; return styles ? Object.entries(styles) .map(([k, v]) => `${k}:${v}`) .join(';') : ''; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: BaseComponent, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.6", type: BaseComponent, isStandalone: true, inputs: { config: "config" }, host: { properties: { "class": "this.hostClasses", "style": "this.hostStyles" } }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: BaseComponent, decorators: [{ type: Directive }], ctorParameters: () => [{ type: i1.DomSanitizer }], propDecorators: { config: [{ type: Input }], hostClasses: [{ type: HostBinding, args: ['class'] }], hostStyles: [{ type: HostBinding, args: ['style'] }] } }); class TypeNotFoundComponent { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: TypeNotFoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: TypeNotFoundComponent, isStandalone: true, selector: "nju-type-not-found", inputs: { config: "config" }, ngImport: i0, template: `<div class="nju-error">Component type not found.</div>`, isInline: true }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: TypeNotFoundComponent, decorators: [{ type: Component, args: [{ selector: 'nju-type-not-found', template: `<div class="nju-error">Component type not found.</div>` }] }], propDecorators: { config: [{ type: Input }] } }); class FormSubmitBroadcastService { constructor() { // BehaviorSubject holds the latest “submitted” flag. // We start at false (form not yet submitted). this.submitted$ = new BehaviorSubject(false); } // Call this when the user clicks “Submit” notifySubmitted() { this.submitted$.next(true); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FormSubmitBroadcastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FormSubmitBroadcastService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FormSubmitBroadcastService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ClassListPipe { /** * Transforms a default class and an optional array of classes into a single string. * @param classes Array of additional class names (or string if user provided direct class). * @param defaultCls Base class to apply when array is empty or undefined. */ transform(classes, defaultCls) { if (typeof classes === 'string') { return classes; } return convertStringArrayIntoString(defaultCls, classes ?? []); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ClassListPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); } static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.6", ngImport: i0, type: ClassListPipe, isStandalone: false, name: "classList" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ClassListPipe, decorators: [{ type: Pipe, args: [{ name: 'classList', pure: true, standalone: false, }] }] }); class StyleMapPipe { /** * Ensures a style binding input is an object for ngStyle. * Accepts string (CSS text), object, null, or undefined. * @param styles CSS text or style object. * @returns Object for ngStyle or leaves string for attr.style. */ transform(styles) { if (typeof styles === 'string') { return styles; } return styles ?? {}; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: StyleMapPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); } static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.6", ngImport: i0, type: StyleMapPipe, isStandalone: false, name: "styleMap" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: StyleMapPipe, decorators: [{ type: Pipe, args: [{ name: 'styleMap', pure: true, standalone: false, }] }] }); // Import core modules class FormComponent extends BaseComponent { constructor(sanitizer, submitBroadcastService) { super(sanitizer); this.sanitizer = sanitizer; this.submitBroadcastService = submitBroadcastService; this.id = ''; // Binding id to overall component this.cid = ''; // Binding data-component-id to overall component // Subject is used to manage the lifecycle of the component and unsubscribe from observables when the component is destroyed this.destroy$ = new Subject(); // Subject to signal when the component is destroyed } // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { if (changes['config'] && this.config) { // apply host and component level styling this.applyHostConfig(this.config); this.id = this.config['id'] || ''; // Set the id based on the config or default to empty string this.cid = this.config["cid"] || ''; // Set the cid based on the config or default to empty string /* Initialize form controls based on the provided validator schema initFormControlSchema( this.config.validatorSchema, this.form, this.fb, this.joiValidatorFactoryService ); console.log('Form initialized with schema:', this.form?.value); // Render nested Json UI if(this.config.components){ this.viewContainerRef.clear(); this.componentFactoryService.loadComponents( this.config.components ?? [], this.viewContainerRef, this.form, this.config.validatorSchema ); } */ } } // Handler for form submission onSubmit() { console.log('Form contain invalid value: ', this.form.value); // 1) Mark the whole form (and all nested arrays/groups) touched first: this.form.markAllAsTouched(); this.submitBroadcastService.notifySubmitted(); // Notify that the form has been submitted if (!this.config.onSubmit?.novalidate && this.form.invalid) { console.log('Form contain invalid value: ', this.form.value); // Log all validation errors in the form and its nested structures this.getFormValidationErrors(this.form); return; } /* this.submitService .submit(this.config.onSubmit!, this.form.value) .pipe(takeUntil(this.destroy$)) .subscribe({ error: (err) => { // Global error logging, could delegate to a NotificationService console.error('Form submission error:', err); } }); */ } /** * Method to log all validation errors in the form and its nested structures * Recursively logs all validation errors in a FormGroup/FormArray */ getFormValidationErrors(control, parentKey = '') { // 1) If this group/array itself has errors, log them if (control.errors) { console.error(`Control: ${parentKey || '(root)'}, Errors:`, control.errors); } // 2) Recurse into child controls Object.keys(control.controls).forEach(name => { const child = control.get(name); const fullKey = parentKey ? `${parentKey}.${name}` : name; if (child instanceof FormGroup || child instanceof FormArray) { // recurse for nested groups/arrays this.getFormValidationErrors(child, fullKey); } else if (child.errors) { // primitive FormControl errors Object.entries(child.errors).forEach(([errorKey, errorValue]) => { console.error(`Control: ${fullKey}, KeyError: ${errorKey}, ErrorValue:`, errorValue); }); } }); } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FormComponent, deps: [{ token: i1.DomSanitizer }, { token: FormSubmitBroadcastService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: FormComponent, isStandalone: false, selector: "nju-app-form", inputs: { form: "form" }, host: { properties: { "id": "this.id", "attr.data-component-id": "this.cid" } }, viewQueries: [{ propertyName: "viewContainerRef", first: true, predicate: ["dynamicComponentGroup"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<form [formGroup]=\"form\"\r\n (ngSubmit)=\"onSubmit()\"\r\n [ngClass]=\"config.class| classList:''\"\r\n [ngStyle]=\"config.style | styleMap\">\r\n <ng-template #dynamicComponentGroup></ng-template>\r\n</form>\r\n", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: FormComponent, decorators: [{ type: Component, args: [{ selector: 'nju-app-form', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<form [formGroup]=\"form\"\r\n (ngSubmit)=\"onSubmit()\"\r\n [ngClass]=\"config.class| classList:''\"\r\n [ngStyle]=\"config.style | styleMap\">\r\n <ng-template #dynamicComponentGroup></ng-template>\r\n</form>\r\n" }] }], ctorParameters: () => [{ type: i1.DomSanitizer }, { type: FormSubmitBroadcastService }], propDecorators: { id: [{ type: HostBinding, args: ['id'] }], cid: [{ type: HostBinding, args: ['attr.data-component-id'] }], form: [{ type: Input }], viewContainerRef: [{ type: ViewChild, args: ['dynamicComponentGroup', { read: ViewContainerRef, static: true }] }] } }); function joiValidatorUtil(controlName, schemaBody, validatorFactoryService) { return (control) => { const formData = { [controlName]: control.value }; const { error } = validatorFactoryService.validateSchema({ [controlName]: schemaBody }, formData); if (error) { const errors = {}; error.details.forEach(detail => { errors[detail.context?.key || 'unknown'] = detail.message; }); return errors; } return null; }; } class ExtendedFormControl extends FormControl { constructor(formState, validatorOrOpts, asyncValidator) { super(formState, validatorOrOpts, asyncValidator); } } /** Ensures the array has at least `min` items */ function minItems(min) { return (control) => Array.isArray(control.value) && control.value.length < min ? { minItems: { required: min, actual: control.value.length } } : null; } /** Ensures the array has at most `max` items */ function maxItems(max) { return (control) => Array.isArray(control.value) && control.value.length > max ? { maxItems: { required: max, actual: control.value.length } } : null; } /** Ensures all array items are unique */ function uniqueItems() { return (control) => { const arr = control.value; if (!Array.isArray(arr)) return null; const seen = new Set(); for (const v of arr) { if (seen.has(v)) { return { uniqueItems: true }; } seen.add(v); } return null; }; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////// Main Function ///////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function initFormControlSchema(schema, parent, fb, validatorFactoryService, defaultValues = {}) { for (const key in schema) { if (schema.hasOwnProperty(key)) { const fieldSchema = schema[key]; const defaultValue = defaultValues[key] ?? fieldSchema.default ?? null; // Use provided default or schema default if (fieldSchema.type === 'object') { const objectDefaults = defaultValue && typeof defaultValue === 'object' ? defaultValue : {}; parent.addControl(key, createFormGroup(fieldSchema, fb, validatorFactoryService, objectDefaults)); } else if (fieldSchema.type === 'array') { const arrayDefaults = Array.isArray(defaultValue) ? defaultValue : []; parent.addControl(key, createFormArray(fieldSchema, fb, validatorFactoryService, arrayDefaults)); } else { parent.addControl(key, createFormControl(fieldSchema, fb, validatorFactoryService, defaultValue)); } } } } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////// Core Functions ///////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function createFormGroup(schema, fb, validatorFactoryService, defaultValues = {}) { const group = fb.group({}); if (schema.object) { initFormControlSchema(schema.object, group, fb, validatorFactoryService, defaultValues); } return group; } function createFormArray(schema, fb, validatorFactoryService, defaultValues = []) { // 0) Safety: ensure `schema.array` exists const arrDef = schema?.array; if (!arrDef) { console.warn('createFormArray: missing schema.array, returning empty FormArray'); return fb.array([], []); } // 1) Safety: ensure item definition exists const itemSchema = arrDef.items; if (!itemSchema) { console.warn('createFormArray: missing schema.array.items, cannot build children'); const fallbackValidators = []; if (arrDef.minItems != null) fallbackValidators.push(minItems(arrDef.minItems)); if (arrDef.maxItems != null) fallbackValidators.push(maxItems(arrDef.maxItems)); if (arrDef.uniqueItems) fallbackValidators.push(uniqueItems()); return fb.array([], fallbackValidators); } // 2) Safety: ensure defaultValues is an array let defaults; if (!Array.isArray(defaultValues)) { console.warn(`createFormArray: defaultValues for "${schema?.name}" is not an array, ignoring it`); defaults = []; } else { defaults = defaultValues; } // 3) Build child controls const controls = defaults.map(value => createFormItem(itemSchema, fb, validatorFactoryService, value)); // 4) Collect array‐level validators const arrayValidators = []; if (arrDef.minItems != null) arrayValidators.push(minItems(arrDef.minItems)); if (arrDef.maxItems != null) arrayValidators.push(maxItems(arrDef.maxItems)); if (arrDef.uniqueItems) arrayValidators.push(uniqueItems()); // 5) Return the configured FormArray return fb.array(controls, arrayValidators); } function createFormItem(schema, fb, validatorFactoryService, defaultValue = {}) { if (schema.type === 'object') { return createFormGroup(schema, fb, validatorFactoryService, defaultValue); } else if (schema.type === 'array') { const arrayDefaults = Array.isArray(defaultValue) ? defaultValue : schema.default ?? []; return createFormArray(schema, fb, validatorFactoryService, arrayDefaults); } else { return createFormControl(schema, fb, validatorFactoryService, defaultValue); } } function createFormControl(schema, fb, validatorFactoryService, defaultValue = null) { const validators = getValidators(schema, validatorFactoryService); // Assign default values properly const control = new ExtendedFormControl(defaultValue ?? '', validators); control.metadata = extractConstraints(schema); return control; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////// Supportive Functions ////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function getValidators(schema, validatorFactoryService) { const validators = []; if (schema) { validators.push(joiValidatorUtil('', schema, validatorFactoryService)); } return validators; } function extractConstraints(schema) { const constraints = { type: schema.type }; if (schema.string) { if (schema.string.pattern) constraints.regexPattern = schema.string.pattern; if (schema.string.min !== undefined) constraints.min = schema.string.min; if (schema.string.max !== undefined) constraints.max = schema.string.max; if (schema.string.length !== undefined) constraints.length = schema.string.length; if (schema.string.case) constraints.case = schema.string.case; if (schema.string.creditCard) constraints.maskPattern = "9999-9999-9999-9999"; if (schema.string.hostname) constraints.maskPattern = "*{1,63}.*{1,63}"; if (schema.string.ip) constraints.maskPattern = schema.string.ip.version.includes('ipv4') ? "999.999.999.999" : "9999:9999:9999:9999:9999:9999:9999:9999"; if (schema.string.email) constraints.maskPattern = "*{1,63}@*{1,63}.*{2,6}"; if (schema.string.alphanum) constraints.maskPattern = "*{1,}"; if (schema.string.insensitive) constraints.allowedValues = schema.string.insensitive; } if (schema.number) { if (schema.number.port) constraints.port = schema.number.port; if (schema.number.positive) constraints.positive = schema.number.positive; if (schema.number.multiple !== undefined) constraints.multiple = schema.number.multiple; if (schema.number.negative) constraints.negative = schema.number.negative; if (schema.number.precision !== undefined) constraints.precision = schema.number.precision; if (schema.number.less !== undefined) constraints.less = schema.number.less; if (schema.number.greater !== undefined) constraints.greater = schema.number.greater; if (schema.number.min !== undefined) constraints.min = schema.number.min; if (schema.number.max !== undefined) constraints.max = schema.number.max; } if (schema.boolean) { console.log('boolean:', schema.boolean); if (schema.boolean.truthy) constraints.truthy = schema.boolean.truthy; if (schema.boolean.falsy) constraints.falsy = schema.boolean.falsy; if (schema.boolean.sensitive) constraints.sensitive = true; } return constraints; } const COMPONENT_MAPPING_CONFIG = new InjectionToken('COMPONENT_MAPPING_CONFIG', { providedIn: 'root', factory: () => ({ useDefaultMappings: true }) // Defaults to using the built-in mappings. }); const COMPONENT_MAPPINGS = new InjectionToken('COMPONENT_MAPPINGS'); class DividerComponent extends BaseComponent { // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { if (changes['config'] && this.config) { // apply host and component level styling this.applyHostConfig(this.config); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: DividerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: DividerComponent, isStandalone: false, selector: "nju-divider", usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<hr \r\n [ngClass]=\"config.class | classList:'border-medium'\" \r\n [ngStyle]=\"config.style | styleMap\"/>", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: DividerComponent, decorators: [{ type: Component, args: [{ selector: 'nju-divider', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<hr \r\n [ngClass]=\"config.class | classList:'border-medium'\" \r\n [ngStyle]=\"config.style | styleMap\"/>" }] }] }); class SafeHtmlPipe { constructor(sanitizer) { this.sanitizer = sanitizer; } transform(html) { // default to empty string if null/undefined return this.sanitizer.bypassSecurityTrustHtml(html ?? ''); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); } static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.6", ngImport: i0, type: SafeHtmlPipe, isStandalone: false, name: "safeHtml" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: SafeHtmlPipe, decorators: [{ type: Pipe, args: [{ name: 'safeHtml', pure: true, standalone: false, }] }], ctorParameters: () => [{ type: i1.DomSanitizer }] }); class HeadlineComponent extends BaseComponent { // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { // Check if the 'config' input property has changed // If it has, and the config is defined, apply the host and component configuration if (changes['config'] && this.config) { // Set css styling variable from json schema // apply host and component level styling this.applyHostConfig(this.config); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: HeadlineComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: HeadlineComponent, isStandalone: false, selector: "nju-headline", usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ng-container [ngSwitch]=\"config['tag']\">\r\n <h1 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h1'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h1>\r\n <h2 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h2'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h2>\r\n <h3 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h3'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h3>\r\n <h4 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h4'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h4>\r\n <h5 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h5'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h5>\r\n <h6 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h6'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h6>\r\n <div [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchDefault [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></div>\r\n</ng-container>", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: HeadlineComponent, decorators: [{ type: Component, args: [{ selector: 'nju-headline', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container [ngSwitch]=\"config['tag']\">\r\n <h1 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h1'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h1>\r\n <h2 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h2'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h2>\r\n <h3 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h3'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h3>\r\n <h4 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h4'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h4>\r\n <h5 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h5'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h5>\r\n <h6 [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchCase=\"'h6'\" [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></h6>\r\n <div [ngClass]=\"config.class | classList:''\" [ngStyle]=\"config.style | styleMap\" *ngSwitchDefault [innerHTML]=\"config['text'] | safeHtml\" [attr.data-component-id]=\"config['cid']\"></div>\r\n</ng-container>" }] }] }); class LabelComponent extends BaseComponent { // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { // Check if the 'config' input property has changed // If it has, and the config is defined, apply the host and component configuration if (changes['config'] && this.config) { // Set css styling variable from json schema // apply host and component level styling this.applyHostConfig(this.config); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: LabelComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: LabelComponent, isStandalone: false, selector: "nju-label", usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<label \r\n [ngClass]=\"config.class | classList:'form-label'\"\r\n [ngStyle]=\"config.style | styleMap\" \r\n [attr.for]=\"config['controlId'] ?? null\"\r\n [innerHTML]=\"config['text'] | safeHtml\"\r\n [attr.data-component-id]=\"config['cid']\">\r\n</label>", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: LabelComponent, decorators: [{ type: Component, args: [{ selector: 'nju-label', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<label \r\n [ngClass]=\"config.class | classList:'form-label'\"\r\n [ngStyle]=\"config.style | styleMap\" \r\n [attr.for]=\"config['controlId'] ?? null\"\r\n [innerHTML]=\"config['text'] | safeHtml\"\r\n [attr.data-component-id]=\"config['cid']\">\r\n</label>" }] }] }); class ParagraphComponent extends BaseComponent { // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { // Check if the 'config' input property has changed // If it has, and the config is defined, apply the host and component configuration if (changes['config'] && this.config) { // Set css styling variable from json schema // apply host and component level styling this.applyHostConfig(this.config); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ParagraphComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: ParagraphComponent, isStandalone: false, selector: "nju-paragraph", usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<p \r\n [ngClass]=\"config.class | classList:'body-lg'\"\r\n [ngStyle]=\"config.style | styleMap\"\r\n [innerHTML]=\"config['text'] | safeHtml\"\r\n [attr.data-component-id]=\"config['cid']\"></p>", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ParagraphComponent, decorators: [{ type: Component, args: [{ selector: 'nju-paragraph', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<p \r\n [ngClass]=\"config.class | classList:'body-lg'\"\r\n [ngStyle]=\"config.style | styleMap\"\r\n [innerHTML]=\"config['text'] | safeHtml\"\r\n [attr.data-component-id]=\"config['cid']\"></p>" }] }] }); class SpanComponent extends BaseComponent { // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { // Check if the 'config' input property has changed // If it has, and the config is defined, apply the host and component configuration if (changes['config'] && this.config) { // Set css styling variable from json schema // apply host and component level styling this.applyHostConfig(this.config); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: SpanComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: SpanComponent, isStandalone: false, selector: "nju-span", usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<span \r\n [ngClass]=\"config.class | classList:''\"\r\n [ngStyle]=\"config.style | styleMap\" \r\n [innerHTML]=\"config['text'] | safeHtml\"\r\n [attr.data-component-id]=\"config['cid']\">\r\n</span>", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: SafeHtmlPipe, name: "safeHtml" }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: SpanComponent, decorators: [{ type: Component, args: [{ selector: 'nju-span', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<span \r\n [ngClass]=\"config.class | classList:''\"\r\n [ngStyle]=\"config.style | styleMap\" \r\n [innerHTML]=\"config['text'] | safeHtml\"\r\n [attr.data-component-id]=\"config['cid']\">\r\n</span>" }] }] }); class IconComponent extends BaseComponent { // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { // Check if the 'config' input property has changed // If it has, and the config is defined, apply the host and component configuration if (changes['config'] && this.config) { // Set css styling variable from json schema // apply host and component level styling this.applyHostConfig(this.config); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: IconComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: IconComponent, isStandalone: false, selector: "nju-icon", usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<i [ngClass]=\"config.class| classList:''\" [ngStyle]=\"config.style | styleMap\"></i>", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: IconComponent, decorators: [{ type: Component, args: [{ selector: 'nju-icon', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<i [ngClass]=\"config.class| classList:''\" [ngStyle]=\"config.style | styleMap\"></i>" }] }] }); class ImageComponent extends BaseComponent { // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { // Check if the 'config' input property has changed // If it has, and the config is defined, apply the host and component configuration if (changes['config'] && this.config) { // Set css styling variable from json schema // apply host and component level styling this.applyHostConfig(this.config); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ImageComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: ImageComponent, isStandalone: false, selector: "nju-image", usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<img\r\n [ngClass]=\"config.class | classList:''\" \r\n [ngStyle]=\"config.style | styleMap\"\r\n [attr.data-bs-custom-class]=\"config['tooltipCustomClass']\" \r\n [attr.data-bs-toggle]=\"'tooltip'\"\r\n [attr.data-bs-placement]=\"config['tooltipPlacement']\" \r\n [attr.title]=\"config['tooltip']\" \r\n [src]=\"config['src']\" />", dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: ClassListPipe, name: "classList" }, { kind: "pipe", type: StyleMapPipe, name: "styleMap" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ImageComponent, decorators: [{ type: Component, args: [{ selector: 'nju-image', standalone: false, changeDetection: ChangeDetectionStrategy.OnPush, template: "<img\r\n [ngClass]=\"config.class | classList:''\" \r\n [ngStyle]=\"config.style | styleMap\"\r\n [attr.data-bs-custom-class]=\"config['tooltipCustomClass']\" \r\n [attr.data-bs-toggle]=\"'tooltip'\"\r\n [attr.data-bs-placement]=\"config['tooltipPlacement']\" \r\n [attr.title]=\"config['tooltip']\" \r\n [src]=\"config['src']\" />" }] }] }); // src/lib/services/region.service.ts class RegionService { constructor() { this.regions = new Map(); } register(cid, vcr) { this.regions.set(cid, vcr); } unregister(cid) { this.regions.delete(cid); } get(cid) { return this.regions.get(cid); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: RegionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: RegionService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: RegionService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class ContainerComponent extends BaseComponent { // HostBinding decorator is used to bind properties to the host element of the component // It allows you to bind properties to the host element of the component constructor(regions, sanitizer) { super(sanitizer); this.regions = regions; this.sanitizer = sanitizer; // HostBinding decorator is used to bind properties to the host element of the component this.id = ''; // Binding id to overall component this.cid = ''; // Binding data-component-id to overall component } // ngOnChanges is a lifecycle hook that is called when any data-bound input properties change // This is where you can perform any additional logic when the input properties change // In this case, it is used to update the host classes and styles based on the component's configuration ngOnChanges(changes) { if (changes['config'] && this.config) { // apply host and component level styling this.applyHostConfigViaClassStyle(this.config); this.id = this.config['id'] || ''; // Set the id based on the config or default to empty string this.cid = this.config["cid"] || ''; // Set the cid based on the config or default to empty string const cid = this.config.cid || ''; this.regions.register(cid, this.viewContainerRef); } } ngOnDestroy() { this.regions.unregister(this.config.cid || ''); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ContainerComponent, deps: [{ token: RegionService }, { token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: ContainerComponent, isStandalone: false, selector: "nju-container", host: { properties: { "id": "this.id", "attr.data-component-id": "this.cid" } }, viewQueries: [{ propertyName: "viewContainerRef", first: true, predicate: ["dynamicComponentGroup"], descendants: true, read: ViewContainerRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: `<ng-template #dynamicComponentGroup></ng-template>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: ContainerComponent, decorators: [{ type: Component, args: [{ selector: 'nju-container', template: `<ng-template #dynamicComponentGroup></ng-template>`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, }] }], ctorParameters: () => [{ type: RegionService }, { type: i1.DomSanitizer }], propDecorators: { id: [{ type: HostBinding, args: ['id'] }], cid: [{ type: HostBinding, args: ['attr.data-component-id'] }], viewContainerRef: [{ type: ViewChild, args: ['dynamicComponentGroup', { read: ViewContainerRef, static: true }] }] } }); cla