import { Component, Input, OnInit} from '@angular/core';
import { ForAngularModule } from '../../for-angular.module';
import { NgxBaseComponent } from '../../engine/NgxBaseComponent';
import { KeyValue } from '../../engine';
import { ComponentRendererComponent } from '../component-renderer/component-renderer.component';
import { ModelRendererComponent } from '../model-renderer/model-renderer.component';
import { UIMediaBreakPoints } from '@decaf-ts/ui-decorators';
/**
* @description Layout component for creating responsive grid layouts in Angular applications.
* @summary This component provides a flexible grid system that can be configured with dynamic
* rows and columns. It supports responsive breakpoints and can render child components within
* the grid structure. The component extends NgxBaseComponent to inherit common functionality
* and integrates with the model and component renderer systems.
*
* @class LayoutComponent
* @extends {NgxBaseComponent}
* @implements {OnInit}
* @memberOf LayoutComponent
*/
@Component({
selector: 'ngx-decaf-layout',
templateUrl: './layout.component.html',
styleUrls: ['./layout.component.scss'],
imports: [ForAngularModule, ModelRendererComponent, ComponentRendererComponent],
standalone: true,
})
export class LayoutComponent extends NgxBaseComponent implements OnInit {
/**
* @description Number of columns or array of column definitions for the grid layout.
* @summary Defines the column structure of the grid. When a number is provided, it creates
* that many equal-width columns. When an array is provided, each element can define specific
* column properties or sizing. This allows for flexible grid layouts that can adapt to
* different content requirements.
*
* @type {(number | string[])}
* @default 1
* @memberOf LayoutComponent
*/
@Input()
cols: number | string[] = 1;
/**
* @description Number of rows or array of row definitions for the grid layout.
* @summary Defines the row structure of the grid. When a number is provided, it creates
* that many equal-height rows. When an array is provided, each element can define specific
* row properties or sizing. This provides control over vertical spacing and content organization.
*
* @type {(number | string[])}
* @default 1
* @memberOf LayoutComponent
*/
@Input()
rows: number | KeyValue[] | string[] = 1;
/**
* @description Media breakpoint for responsive behavior.
* @summary Determines the responsive breakpoint at which the layout should adapt.
* This affects how the grid behaves on different screen sizes, allowing for
* mobile-first or desktop-first responsive design patterns. The breakpoint
* is automatically processed to ensure compatibility with the UI framework.
*
* @type {UIMediaBreakPoints}
* @default 'medium'
* @memberOf LayoutComponent
*/
@Input()
breakpoint: UIMediaBreakPoints = 'medium';
/**
* @description Array of child components or data to render within the grid.
* @summary Contains the child elements that will be distributed across the grid layout.
* Each item in the array represents content that will be rendered using the appropriate
* renderer component (ModelRenderer or ComponentRenderer). This allows for mixed content
* types within a single layout structure.
*
* @type {KeyValue[]}
* @default []
* @memberOf LayoutComponent
*/
@Input()
children: KeyValue[] = [];
/**
* @description Creates an instance of LayoutComponent.
* @summary Initializes a new LayoutComponent with the component name "LayoutComponent".
* This constructor calls the parent NgxBaseComponent constructor to set up base
* functionality and component identification.
*
* @memberOf LayoutComponent
*/
constructor() {
super("LayoutComponent")
}
/**
* @description Getter that converts columns input to an array format.
* @summary Transforms the cols input property into a standardized string array format.
* When cols is a number, it creates an array with that many empty string elements.
* When cols is already an array, it returns the array as-is. This normalization
* ensures consistent handling of column definitions in the template.
*
* @type {string[]}
* @readonly
* @memberOf LayoutComponent
*/
get _cols(): string[] {
let cols = this.cols;
if(typeof cols === "number")
cols = Array.from({length: Number(cols)}, () => ``);
return cols;
}
/**
* @description Getter that converts rows input to an array format.
* @summary Transforms the rows input property into a standardized string array format.
* When rows is a number, it creates an array with that many empty string elements.
* When rows is already an array, it returns the array as-is. This normalization
* ensures consistent handling of row definitions in the template.
*
* @type {KeyValue[]}
* @readonly
* @memberOf LayoutComponent
*/
get _rows(): KeyValue[] {
let rows = this.rows;
if(typeof rows === "number")
rows = Array.from({length: Number(rows)}, () => ({title: ''}));
return rows.map((row, index) => {
return {
title: (row as KeyValue)?.['title'],
cols: this.children.filter(child => {
if(child['row'] === index + 1)
return child;
})
};
});
}
/**
* @description Angular lifecycle hook that runs after component initialization.
* @summary Called once, after the first ngOnChanges(). This method triggers the
* component's initialization process, which includes property parsing and grid
* setup. It ensures the component is properly configured before rendering.
*
* @memberOf LayoutComponent
*/
ngOnInit(): void {
this.initialize();
}
/**
* @description Initializes the layout component with processed properties.
* @summary Overrides the base component's initialize method to set up the grid layout.
* This method processes input properties, normalizes the breakpoint value, converts
* rows and columns to their array representations, and marks the component as initialized.
* The initialization ensures all properties are in the correct format for rendering.
*
* @mermaid
* sequenceDiagram
* participant L as LayoutComponent
* participant B as NgxBaseComponent
*
* L->>B: parseProps(this)
* Note over L: Process component properties
* L->>L: Normalize breakpoint to lowercase
* L->>L: Convert rows to array format
* L->>L: Convert cols to array format
* L->>L: Set initialized = true
*
* @override
* @memberOf LayoutComponent
*/
override initialize() {
this.parseProps(this);
this.breakpoint = this.breakpoint.slice(0, 2).toLowerCase() as UIMediaBreakPoints;
this.cols = this._cols;
this.rows = this._rows;
this.initialized = true;
}
}
Source