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
JavaScript
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