118 lines
3.9 KiB
TypeScript
118 lines
3.9 KiB
TypeScript
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
|
|
|
|
import { LayoutHeight, LayoutTypeClass } from '@pi/ui';
|
|
|
|
import { ShowcaseSection } from '../showcase-section';
|
|
|
|
interface LayoutDemo {
|
|
/** Nombre corto para el título del apartado. */
|
|
name: string;
|
|
/** Constante de `LayoutTypeClass`, tal cual se aplica en el HostBinding. */
|
|
classes: string;
|
|
/** Qué hace realmente el CSS de este layout. */
|
|
description: string;
|
|
/** Bloques de relleno que se pintan dentro de la vista previa. */
|
|
blocks: string[];
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-layouts',
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
templateUrl: './layouts.page.html',
|
|
styleUrl: './layouts.page.scss',
|
|
imports: [ShowcaseSection],
|
|
})
|
|
export class LayoutsPage {
|
|
/**
|
|
* Layouts que se sostienen solos: su CSS actúa sobre el propio contenedor,
|
|
* así que la vista previa con bloques sueltos ya enseña lo que hacen.
|
|
*/
|
|
protected readonly standalone: LayoutDemo[] = [
|
|
{
|
|
name: 'Vertically centered',
|
|
classes: LayoutTypeClass.VerticallyCentered,
|
|
description:
|
|
'Columna flex centrada verticalmente (justify-content: center). Típico de login, errores o estados vacíos.',
|
|
blocks: ['Bloque centrado'],
|
|
},
|
|
{
|
|
name: 'Space between',
|
|
classes: LayoutTypeClass.SpaceBetween,
|
|
description:
|
|
'Columna flex con justify-content: space-between: empuja el primer bloque arriba y el último abajo.',
|
|
blocks: ['Cabecera', 'Pie'],
|
|
},
|
|
{
|
|
name: 'Full width auto',
|
|
classes: LayoutTypeClass.FullWidthAuto,
|
|
description:
|
|
'Añade margin: auto sobre el full width, para centrar el bloque cuando no ocupa todo el ancho.',
|
|
blocks: ['Contenido centrado'],
|
|
},
|
|
{
|
|
name: 'Pricing',
|
|
classes: LayoutTypeClass.Pricing,
|
|
description:
|
|
'Rejilla de 3 columnas (repeat(3, 1fr)) para tarifas; tiene variante 1fr 3fr con tarjeta destacada.',
|
|
blocks: ['Básico', 'Pro', 'Empresas'],
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Estos no se pueden enseñar con bloques sueltos: su CSS apunta a los
|
|
* componentes de wrapper o a estados del shell de la aplicación, así que
|
|
* fuera de esa composición no cambian nada visible.
|
|
*/
|
|
protected readonly compositional = [
|
|
{
|
|
name: 'Full width',
|
|
classes: LayoutTypeClass.FullWidth,
|
|
needs:
|
|
'Un ancestro con `aside-is-open`: los anchos máximos se calculan a partir del aside y el navbar.',
|
|
},
|
|
{
|
|
name: 'Splitted',
|
|
classes: LayoutTypeClass.Splitted,
|
|
needs:
|
|
'No parte en dos por sí solo: es una columna a 100vh y las mitades las aportan los slots izquierdo/derecho de `pi-main-wrapper`.',
|
|
},
|
|
{
|
|
name: 'Edge to edge',
|
|
classes: LayoutTypeClass.EdgeToEdge,
|
|
needs:
|
|
'Un `pi-wrapper__header` como hijo dentro de `.pi-container-layout`: lo que ajusta es su espaciado superior.',
|
|
},
|
|
{
|
|
name: 'List',
|
|
classes: LayoutTypeClass.List,
|
|
needs:
|
|
'Wrappers (`pi-wrapper`, `pi-wrapper__list`) y un `pi-data-grid`: limita sus anchos y centra la rejilla.',
|
|
},
|
|
{
|
|
name: 'List auto',
|
|
classes: LayoutTypeClass.ListAuto,
|
|
needs: 'Igual que List, para listados con scroll infinito.',
|
|
},
|
|
{
|
|
name: 'Form',
|
|
classes: LayoutTypeClass.Form,
|
|
needs:
|
|
'Ir anidado dentro de un `pi-layout__05-splitted`: solo ahí recibe padding y scrollbar propios.',
|
|
},
|
|
];
|
|
|
|
/** Alturas mínimas, aplicables sobre cualquier layout. */
|
|
protected readonly heights = [
|
|
{ label: 'small', cls: LayoutHeight.Small, hint: '33.33vh' },
|
|
{ label: 'medium', cls: LayoutHeight.Medium, hint: '40vh' },
|
|
{ label: 'large', cls: LayoutHeight.Large, hint: '75vh' },
|
|
{ label: 'full', cls: LayoutHeight.Full, hint: '100vh' },
|
|
];
|
|
|
|
/**
|
|
* Las vistas previas van recortadas: varios layouts piden `vh` y ocuparían
|
|
* pantallas enteras. Se puede soltar el recorte para verlos a tamaño real.
|
|
*/
|
|
protected readonly clipped = signal(true);
|
|
}
|