fix components
This commit is contained in:
@@ -1,11 +1,4 @@
|
||||
<header class="page-header">
|
||||
<h1>@pi/ui</h1>
|
||||
<p>
|
||||
Catálogo de la librería migrada a Angular 22: componentes standalone,
|
||||
señales, OnPush y Signal Forms.
|
||||
</p>
|
||||
<span class="event">Último evento: {{ lastEvent() }}</span>
|
||||
</header>
|
||||
<span class="event">Último evento: {{ lastEvent() }}</span>
|
||||
|
||||
<main>
|
||||
<div class="col">
|
||||
@@ -48,6 +41,18 @@
|
||||
|
||||
<pi-search-field [formField]="f.search" placeholder="Buscar…" />
|
||||
|
||||
<pi-icon-field [formField]="f.website" icon="globe">
|
||||
<pi-label>Web</pi-label>
|
||||
</pi-icon-field>
|
||||
|
||||
<pi-phone-field [formField]="f.phone">
|
||||
<pi-label>Teléfono</pi-label>
|
||||
</pi-phone-field>
|
||||
|
||||
<pi-number-field [formField]="f.weight">
|
||||
<pi-label>Peso (kg)</pi-label>
|
||||
</pi-number-field>
|
||||
|
||||
<label class="inline">
|
||||
<span>Newsletter</span>
|
||||
<pi-slide-toggle [formField]="f.newsletter" />
|
||||
@@ -59,6 +64,45 @@
|
||||
label="Volumen"
|
||||
[maxValue]="100"
|
||||
/>
|
||||
|
||||
<div class="range-slider-caption">
|
||||
<span
|
||||
>Rango de precio (pi-range-slider no pinta su propia etiqueta)</span
|
||||
>
|
||||
<pi-range-slider
|
||||
[formField]="f.priceRange"
|
||||
unit="€"
|
||||
[minValue]="0"
|
||||
[maxValue]="100"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<pi-date-field [formField]="f.birthDate">
|
||||
<pi-label>Fecha de nacimiento</pi-label>
|
||||
</pi-date-field>
|
||||
|
||||
<pi-radio-group
|
||||
[formField]="f.shipping"
|
||||
[options]="shippingOptions"
|
||||
[columns]="1"
|
||||
/>
|
||||
|
||||
<pi-checkbox [formField]="f.terms" label="Acepto los términos" />
|
||||
|
||||
<pi-file-upload
|
||||
[formField]="f.attachments"
|
||||
[multiple]="true"
|
||||
accept="image/*,.pdf"
|
||||
[maxSizeBytes]="2097152"
|
||||
[maxFiles]="3"
|
||||
label="Arrastra ficheros o pulsa para elegir"
|
||||
hint="Imágenes o PDF · máx. 2 MB · hasta 3"
|
||||
(rejected)="log('rechazados: ' + $event.length)"
|
||||
/>
|
||||
|
||||
<button pi-primary w100 (click)="submitForm()">
|
||||
Enviar (muestra los errores)
|
||||
</button>
|
||||
</div>
|
||||
</app-section>
|
||||
</div>
|
||||
@@ -87,6 +131,24 @@
|
||||
<pi-chevron-button (toggle)="log('chevron')" />
|
||||
<pi-close-button (toggle)="log('close')" />
|
||||
<pi-hamburger (toggle)="log('hamburger')" />
|
||||
<pi-radio-button
|
||||
[isActive]="radioActive()"
|
||||
[isDisabled]="false"
|
||||
(execute)="radioActive.set(!radioActive())"
|
||||
/>
|
||||
<pi-switch-button
|
||||
[content]="['Mensual', 'Anual']"
|
||||
contentType="text"
|
||||
[(isActive)]="switchActive"
|
||||
(toggledTo)="log('switch ' + $event)"
|
||||
/>
|
||||
<pi-toggle-button
|
||||
text="Favorito"
|
||||
icon="star-fill"
|
||||
[isActive]="toggleActive()"
|
||||
[isDisabled]="false"
|
||||
(execute)="toggleActive.set(!toggleActive())"
|
||||
/>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Iconos y texto">
|
||||
@@ -99,10 +161,58 @@
|
||||
appearance="fill"
|
||||
[isStroked]="true"
|
||||
/>
|
||||
<pi-icon
|
||||
icon="info"
|
||||
color="primary"
|
||||
size="large"
|
||||
pi-tooltip
|
||||
tooltipText="Esto usa PiTooltipDirective"
|
||||
tooltipPosition="above"
|
||||
/>
|
||||
<pi-text-viewer value="Texto con el visor" fontSize="m" color="black" />
|
||||
<pi-divider color="primary" width="large" label="Separador" />
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Cabecera y listado"
|
||||
hint="pi-headline para portadas de sección, pi-list-item para filas de listado. pi-headline resuelve pathImg contra un CDN externo fijo, así que la ilustración solo carga con red."
|
||||
>
|
||||
<div class="stack full">
|
||||
<pi-headline pathImg="404.svg" alt="Ilustración">
|
||||
<pi-headline-label-content>
|
||||
<h4>Bienvenido</h4>
|
||||
</pi-headline-label-content>
|
||||
<pi-headline-description-content>
|
||||
<p>Gestiona tu cuenta desde aquí.</p>
|
||||
</pi-headline-description-content>
|
||||
</pi-headline>
|
||||
|
||||
<pi-list-item borderType="bottom" color="white" [isClickable]="true">
|
||||
<pi-list-item-left-icon>
|
||||
<pi-icon icon="user" color="primary" />
|
||||
</pi-list-item-left-icon>
|
||||
<pi-list-item-left-content>
|
||||
<span>Perfil</span>
|
||||
</pi-list-item-left-content>
|
||||
<pi-list-item-right-icon>
|
||||
<pi-icon icon="chevron-forward" color="grey" />
|
||||
</pi-list-item-right-icon>
|
||||
</pi-list-item>
|
||||
|
||||
<pi-list-item borderType="bottom" color="white" [isClickable]="true">
|
||||
<pi-list-item-left-icon>
|
||||
<pi-icon icon="notification-on" color="primary" />
|
||||
</pi-list-item-left-icon>
|
||||
<pi-list-item-left-content>
|
||||
<span>Notificaciones</span>
|
||||
</pi-list-item-left-content>
|
||||
<pi-list-item-right-content>
|
||||
<pi-chip-status status="pending" label="3" />
|
||||
</pi-list-item-right-content>
|
||||
</pi-list-item>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Chips">
|
||||
<pi-chip label="Etiqueta" color="primary" />
|
||||
<pi-chip-status status="success" label="Correcto" />
|
||||
@@ -114,6 +224,359 @@
|
||||
[isActive]="true"
|
||||
(execute)="log('chip-action')"
|
||||
/>
|
||||
<pi-chip-time
|
||||
date="2026-07-28"
|
||||
time="2026-07-28T09:30:00Z"
|
||||
[isActive]="false"
|
||||
/>
|
||||
<pi-chip-date date="2026-07-28" [isActive]="false" />
|
||||
<pi-tile label="Ingresos" value="12.4K €" icon="coin" />
|
||||
</app-section>
|
||||
|
||||
<app-section title="Card">
|
||||
<pi-card
|
||||
alignment="flex-start"
|
||||
gap="m"
|
||||
innerPadding="l"
|
||||
context="public"
|
||||
[isClickable]="true"
|
||||
(execute)="log('card')"
|
||||
>
|
||||
<pi-card-top-content>
|
||||
<h4>Título de la tarjeta</h4>
|
||||
</pi-card-top-content>
|
||||
<pi-card-center-content>
|
||||
<p>Contenido de ejemplo para pi-card.</p>
|
||||
</pi-card-center-content>
|
||||
</pi-card>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Panel"
|
||||
hint="pi-expansion-panel[type=form] usa Reactive Forms clásico, no Signal Forms."
|
||||
>
|
||||
<div class="stack full">
|
||||
<pi-panel
|
||||
title="Resumen"
|
||||
subtitle="Últimos 30 días"
|
||||
height="medium"
|
||||
outline="grey"
|
||||
status=""
|
||||
innerPadding="l"
|
||||
>
|
||||
<pi-panel-center-content>
|
||||
<p>Contenido central del panel.</p>
|
||||
</pi-panel-center-content>
|
||||
<pi-panel-bottom-content>
|
||||
<button pi-ghost (click)="log('panel bottom action')">
|
||||
Ver más
|
||||
</button>
|
||||
</pi-panel-bottom-content>
|
||||
</pi-panel>
|
||||
|
||||
<pi-expansion-panel
|
||||
type="form"
|
||||
title="Datos de contacto"
|
||||
height="small"
|
||||
outline="grey"
|
||||
status=""
|
||||
innerPadding="l"
|
||||
[(isCollapsed)]="isPanelCollapsed"
|
||||
(edit)="log('expansion-panel edit')"
|
||||
>
|
||||
<pi-panel-center-content>
|
||||
<p>{{ f.contactEmail().value() || 'Sin email' }}</p>
|
||||
</pi-panel-center-content>
|
||||
<pi-panel-expandable-content>
|
||||
<input
|
||||
[formField]="f.contactEmail"
|
||||
placeholder="email@ejemplo.com"
|
||||
/>
|
||||
</pi-panel-expandable-content>
|
||||
</pi-expansion-panel>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Accordion">
|
||||
<div class="stack full">
|
||||
<pi-accordion
|
||||
color="primary"
|
||||
appearance="outline"
|
||||
[(expandedItemIndex)]="expandedAccordionIndex"
|
||||
>
|
||||
<pi-accordion-item
|
||||
title="Facturación"
|
||||
subtitle="Datos de pago"
|
||||
status="info"
|
||||
statusLabel="Pendiente"
|
||||
>
|
||||
<ng-template pi-accordion-item-expandable-content>
|
||||
<p>Contenido expandible del ítem 1.</p>
|
||||
</ng-template>
|
||||
</pi-accordion-item>
|
||||
<pi-accordion-item
|
||||
title="Envío"
|
||||
status="success"
|
||||
statusLabel="Completo"
|
||||
>
|
||||
<ng-template pi-accordion-item-expandable-content>
|
||||
<p>Detalles de envío.</p>
|
||||
</ng-template>
|
||||
</pi-accordion-item>
|
||||
</pi-accordion>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Tab">
|
||||
<div class="stack full">
|
||||
<pi-tab
|
||||
[tabButtons]="tabs"
|
||||
[isSmallDevice]="false"
|
||||
(tabChange)="log('tab ' + $event)"
|
||||
>
|
||||
<ng-template pi-tab-content
|
||||
>Contenido de la pestaña General.</ng-template
|
||||
>
|
||||
<ng-template pi-tab-content
|
||||
>Contenido de la pestaña Facturación.</ng-template
|
||||
>
|
||||
<ng-template pi-tab-content
|
||||
>Contenido de la pestaña Avanzado.</ng-template
|
||||
>
|
||||
</pi-tab>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Banner">
|
||||
<div class="stack full">
|
||||
<pi-banner
|
||||
mode="dark"
|
||||
title="Nueva funcionalidad"
|
||||
message="Descubre el nuevo panel de control."
|
||||
buttonText="Ver más"
|
||||
pathImg="404.svg"
|
||||
extension="svg"
|
||||
(execute)="log('banner')"
|
||||
/>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Note">
|
||||
<div class="stack full">
|
||||
<pi-note
|
||||
title="Aviso"
|
||||
text="Tu suscripción caduca pronto."
|
||||
status="pending"
|
||||
gap="s"
|
||||
>
|
||||
<pi-note-action-content>
|
||||
<button pi-ghost (click)="log('note action')">Renovar</button>
|
||||
</pi-note-action-content>
|
||||
</pi-note>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Select"
|
||||
hint="pi-select* usa Signal Forms como el resto: [formField] enlaza el valor completo de la opción elegida. #optionTemplate/#selectedTemplate son content children obligatorios de la librería; sin ellos, Angular lanza NG0951."
|
||||
>
|
||||
<div class="stack full">
|
||||
<pi-select
|
||||
[formField]="f.country"
|
||||
keyIdProperty="id"
|
||||
label="País"
|
||||
placeholder="Selecciona un país"
|
||||
[options]="countries"
|
||||
>
|
||||
<ng-template #optionTemplate let-option>
|
||||
<pi-select-option [id]="option.id" [label]="option.name" />
|
||||
</ng-template>
|
||||
<ng-template #selectedTemplate></ng-template>
|
||||
</pi-select>
|
||||
|
||||
<pi-select-multiple
|
||||
[formField]="f.tags"
|
||||
keyIdProperty="id"
|
||||
label="Etiquetas"
|
||||
placeholder="Selecciona etiquetas"
|
||||
[options]="tags"
|
||||
[hasSelectAllOptions]="true"
|
||||
selectAllLabel="Todas"
|
||||
>
|
||||
<ng-template #optionTemplate let-option>
|
||||
<pi-select-option
|
||||
type="multiple"
|
||||
[id]="option.id"
|
||||
[label]="option.name"
|
||||
/>
|
||||
</ng-template>
|
||||
<ng-template #selectedTemplate></ng-template>
|
||||
</pi-select-multiple>
|
||||
|
||||
<pi-select-period
|
||||
[formField]="f.period"
|
||||
keyIdProperty="id"
|
||||
label="Periodo"
|
||||
placeholder="Selecciona un periodo"
|
||||
[options]="countries"
|
||||
>
|
||||
<ng-template #optionTemplate let-option>
|
||||
<pi-select-option [id]="option.id" [label]="option.name" />
|
||||
</ng-template>
|
||||
<ng-template #selectedTemplate></ng-template>
|
||||
</pi-select-period>
|
||||
|
||||
<pi-select-carousel
|
||||
[formField]="f.plan"
|
||||
keyIdProperty="id"
|
||||
[options]="plans"
|
||||
[itemsDesktop]="3"
|
||||
[device]="device"
|
||||
>
|
||||
<ng-template #optionTemplate let-option>
|
||||
<pi-select-option
|
||||
[id]="option.id"
|
||||
[label]="option.name"
|
||||
[description]="option.description"
|
||||
flexDirection="column"
|
||||
/>
|
||||
</ng-template>
|
||||
<ng-template #selectedTemplate></ng-template>
|
||||
</pi-select-carousel>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Modal y notificaciones"
|
||||
hint="pi-modal y pi-snack-bar no se usan como etiquetas: se abren desde TypeScript vía MatDialog y NotificationService."
|
||||
>
|
||||
<button pi-primary (click)="openDemoModal()">Abrir modal</button>
|
||||
<button pi-outline (click)="showSuccessNotification()">
|
||||
Notificación de éxito
|
||||
</button>
|
||||
<button pi-outline (click)="showErrorNotification()">
|
||||
Notificación de error
|
||||
</button>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Data grid">
|
||||
<div class="stack full">
|
||||
<pi-data-grid
|
||||
[data]="employees"
|
||||
[columns]="3"
|
||||
[rows]="1"
|
||||
[index]="0"
|
||||
[isActive]="false"
|
||||
mode="list"
|
||||
dataDirection="column"
|
||||
(clickItem)="log('data-grid item')"
|
||||
>
|
||||
<ng-template #valuesTemplate let-value let-i="index">
|
||||
<span pi-cell [index]="i">{{ value.name }} — {{ value.role }}</span>
|
||||
</ng-template>
|
||||
</pi-data-grid>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Data table">
|
||||
<div class="stack full">
|
||||
<pi-base-data-table dataDirection="row" type="header">
|
||||
<pi-data-table-item
|
||||
heading="Concepto"
|
||||
[values]="['Cliente', 'Importe', 'Fecha']"
|
||||
>
|
||||
<ng-template #item let-value="value">
|
||||
<pi-cell-type type="text" [display]="value" />
|
||||
</ng-template>
|
||||
</pi-data-table-item>
|
||||
</pi-base-data-table>
|
||||
|
||||
@for (row of invoiceRows; track row) {
|
||||
<pi-base-data-table dataDirection="row" type="data">
|
||||
<pi-data-table-item [values]="row">
|
||||
<ng-template #item let-value="value" let-i="index">
|
||||
<pi-cell-type
|
||||
[type]="i === 1 ? 'amount' : 'text'"
|
||||
[display]="value"
|
||||
/>
|
||||
</ng-template>
|
||||
</pi-data-table-item>
|
||||
</pi-base-data-table>
|
||||
}
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Chart">
|
||||
<div class="stack full">
|
||||
<pi-chart
|
||||
type="line"
|
||||
[device]="device"
|
||||
[xAxisMarks]="['Ene', 'Feb', 'Mar', 'Abr']"
|
||||
[datasets]="chartDatasets"
|
||||
/>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section title="Carousel">
|
||||
<div class="stack full">
|
||||
<pi-carousel
|
||||
[itemsDesktop]="3"
|
||||
[itemsTablet]="2"
|
||||
[itemsMobile]="1"
|
||||
[hideSwipeButtons]="false"
|
||||
[device]="device"
|
||||
color="primary"
|
||||
(itemChanged)="log('carousel ' + $event)"
|
||||
>
|
||||
@for (item of carouselItems; track item.id) {
|
||||
<ng-template pi-carousel-item>
|
||||
<div class="demo-card">{{ item.label }}</div>
|
||||
</ng-template>
|
||||
}
|
||||
</pi-carousel>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Stepper"
|
||||
hint="Cubre WrapperTypeClass.Steps, que estaba declarado sin componente ni CSS."
|
||||
>
|
||||
<div class="stack full">
|
||||
<pi-stepper
|
||||
#stepper
|
||||
[steps]="steps"
|
||||
[(selectedIndex)]="stepperIndex"
|
||||
(stepChange)="log('paso ' + $event)"
|
||||
/>
|
||||
<div class="inline">
|
||||
<button pi-ghost small (click)="stepper.previous()">Anterior</button>
|
||||
<button pi-ghost small (click)="stepper.next()">Siguiente</button>
|
||||
</div>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Dynamic menu"
|
||||
hint="ComponentFamilyClass ya declaraba la familia dynamic-menu y util/menu traía la clase base; faltaba el componente."
|
||||
>
|
||||
<div class="stack full">
|
||||
<pi-dynamic-menu
|
||||
label="Navegación"
|
||||
[menuItems]="menuEntries"
|
||||
(selectEntry)="log('menú: ' + $any($event).label)"
|
||||
/>
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Skeleton"
|
||||
hint="Resuelve el TODO que quedaba en pi-data-grid; también es el respaldo cuando no se pasa plantilla."
|
||||
>
|
||||
<div class="stack full">
|
||||
<pi-skeleton [lines]="3" />
|
||||
<pi-skeleton shape="block" width="100%" height="4rem" />
|
||||
<pi-skeleton shape="circle" width="3rem" />
|
||||
</div>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
@@ -130,5 +593,14 @@
|
||||
(changePage)="log('página ' + $event)"
|
||||
/>
|
||||
</app-section>
|
||||
|
||||
<app-section
|
||||
title="Página no encontrada"
|
||||
hint="pi-not-found: página completa (pi-headline + botón volver), no un widget en línea."
|
||||
>
|
||||
<div class="not-found-frame">
|
||||
<pi-not-found />
|
||||
</div>
|
||||
</app-section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user