refactor(web): filas de formulario con varios controles combinables
El mockup muestra que una fila es etiqueta + uno o varios controles en la misma línea (Cliente = input + "...", Canal / Zona = dos mitades, Serie + Número = 72 px + resto, select + número + botón) y que la cabecera tiene a lo sumo 2 columnas. Los campos de un solo control no lo permitían. - Controles sin etiqueta combinables dentro de sbo-field: sbo-input, sbo-textarea, sbo-number, sbo-date, sbo-select y el botón .sbo-btn; ocupan el espacio sobrante o un width fijo. - El primer control de la fila toma el id de la etiqueta (claimId); los demás se nombran con ariaLabel. El error de la fila marca todos sus controles (aria-invalid / aria-describedby). - Los campos con etiqueta (sbo-text-field, sbo-number-field, ..., sbo-lookup-field) pasan a ser atajos de un solo control con la misma API. - CSS global: .sbo-group y .sbo-btn reemplazan a .sbo-pick/.sbo-pair. - CLAUDE.md apunta al mockup renombrado (tools/oferta_venta.html). - Verificado en Chrome contra SAP real, con una cabecera que reproduce las filas compuestas del mockup. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
aa2c483723
commit
68caf401a7
16 files changed
+531
-298
No files matched your search
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
type ElementRef,
|
||||
booleanAttribute,
|
||||
input,
|
||||
model,
|
||||
@@ -11,6 +10,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import { ValueHelp } from '../value-help/value-help';
|
||||
import type { VhLookup, VhRow } from '../value-help/value-help.types';
|
||||
import { TextInput } from './controls';
|
||||
import { FieldBase } from './field-base';
|
||||
import { SboField } from './sbo-field';
|
||||
|
||||
@@ -21,42 +21,34 @@ import { SboField } from './sbo-field';
|
||||
@Component({
|
||||
selector: 'sbo-lookup-field',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [SboField, ValueHelp],
|
||||
imports: [SboField, TextInput, ValueHelp],
|
||||
template: `
|
||||
<sbo-field
|
||||
[label]="label()"
|
||||
[for]="id"
|
||||
[required]="required()"
|
||||
[error]="error()"
|
||||
action
|
||||
[linkable]="linkable()"
|
||||
(labelClick)="linkClick.emit()"
|
||||
>
|
||||
<div class="sbo-pick">
|
||||
<input
|
||||
#box
|
||||
class="sbo-in"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
[id]="id"
|
||||
[value]="value()"
|
||||
[readOnly]="readOnly()"
|
||||
[disabled]="disabled()"
|
||||
[required]="required()"
|
||||
[attr.aria-invalid]="error() ? 'true' : null"
|
||||
(input)="value.set($any($event.target).value)"
|
||||
(keydown.f4)="$event.preventDefault(); openList()"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
title="Lista de valores (F4)"
|
||||
[attr.aria-label]="'Abrir la lista de ' + label()"
|
||||
[disabled]="readOnly() || disabled()"
|
||||
(click)="openList()"
|
||||
>
|
||||
…
|
||||
</button>
|
||||
</div>
|
||||
<sbo-input
|
||||
#box
|
||||
[(value)]="value"
|
||||
[readonly]="readOnly()"
|
||||
[disabled]="disabled()"
|
||||
[required]="required()"
|
||||
(keydown.f4)="$event.preventDefault(); openList()"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="sbo-btn"
|
||||
title="Lista de valores (F4)"
|
||||
[attr.aria-label]="'Abrir la lista de ' + label()"
|
||||
[disabled]="readOnly() || disabled()"
|
||||
(click)="openList()"
|
||||
>
|
||||
…
|
||||
</button>
|
||||
</sbo-field>
|
||||
<sbo-value-help
|
||||
[open]="listOpen()"
|
||||
@@ -81,7 +73,7 @@ export class LookupField extends FieldBase {
|
||||
readonly linkClick = output<void>();
|
||||
|
||||
protected readonly listOpen = signal(false);
|
||||
private readonly box = viewChild.required<ElementRef<HTMLInputElement>>('box');
|
||||
private readonly box = viewChild.required<TextInput>('box');
|
||||
|
||||
protected openList(): void {
|
||||
if (!this.readOnly() && !this.disabled()) this.listOpen.set(true);
|
||||
@@ -89,7 +81,7 @@ export class LookupField extends FieldBase {
|
||||
|
||||
protected closeList(): void {
|
||||
this.listOpen.set(false);
|
||||
this.box().nativeElement.focus();
|
||||
this.box().focus();
|
||||
}
|
||||
|
||||
protected onPicked(rows: VhRow[]): void {
|
||||
|
||||
Reference in new issue
Block a user