diff --git a/apps/web/src/app/shared/grid/grid.types.ts b/apps/web/src/app/shared/grid/grid.types.ts index 4c1ebe1..c9a845f 100644 --- a/apps/web/src/app/shared/grid/grid.types.ts +++ b/apps/web/src/app/shared/grid/grid.types.ts @@ -17,6 +17,8 @@ export interface GridColumn { key: string; title: string; width?: string; + /** Alineación del texto de la columna (encabezado y celdas); por defecto, `right` en las numéricas y `left` en el resto. */ + align?: 'left' | 'center' | 'right'; /** `number` se alinea a la derecha, se muestra con formato y se interpreta al salir de la celda. */ type?: 'text' | 'number'; /** Decimales fijos para `number` (importes: 2); sin él, hasta 3 sin ceros sobrantes. */ diff --git a/apps/web/src/app/shared/grid/lines-grid.css b/apps/web/src/app/shared/grid/lines-grid.css index b3a6368..653ba42 100644 --- a/apps/web/src/app/shared/grid/lines-grid.css +++ b/apps/web/src/app/shared/grid/lines-grid.css @@ -36,9 +36,6 @@ th { text-align: left; white-space: nowrap; } -th.num { - text-align: right; -} th.req::after { content: ' *'; color: var(--err); @@ -77,9 +74,6 @@ td.ro { border: 1px solid transparent; border-radius: var(--radius); } -.cell.num { - text-align: right; -} .cell.mono { font-family: ui-monospace, Menlo, Consolas, monospace; } diff --git a/apps/web/src/app/shared/grid/lines-grid.html b/apps/web/src/app/shared/grid/lines-grid.html index b14fccd..09994af 100644 --- a/apps/web/src/app/shared/grid/lines-grid.html +++ b/apps/web/src/app/shared/grid/lines-grid.html @@ -15,7 +15,7 @@ # @for (c of columns(); track c.key) { - {{ c.title }} + {{ c.title }} } @if (!readonly()) { Quitar @@ -35,6 +35,7 @@ type="text" autocomplete="off" [class.mono]="c.mono" + [style.text-align]="alignOf(c)" [attr.data-r]="i" [attr.data-c]="j" [attr.aria-label]="c.title + ' de la línea ' + (i + 1)" @@ -49,7 +50,7 @@ class="cell" type="text" autocomplete="off" - [class.num]="c.type === 'number'" + [style.text-align]="alignOf(c)" [class.mono]="c.mono" [readOnly]="isReadonly(line, c)" [attr.data-r]="i" diff --git a/apps/web/src/app/shared/grid/lines-grid.spec.ts b/apps/web/src/app/shared/grid/lines-grid.spec.ts index 908e66a..929bbd6 100644 --- a/apps/web/src/app/shared/grid/lines-grid.spec.ts +++ b/apps/web/src/app/shared/grid/lines-grid.spec.ts @@ -464,3 +464,29 @@ describe('LinesGrid: columnas bloqueadas', () => { expect(el.querySelector('input[data-r="0"][data-c="0"]')!.readOnly).toBe(false); }); }); + +describe('LinesGrid: alineación de las columnas', () => { + it('por defecto las numéricas van a la derecha y el resto a la izquierda; `align` lo cambia', async () => { + await TestBed.configureTestingModule({ + imports: [Host], + providers: [provideHttpClient(), provideHttpClientTesting()], + }).compileComponents(); + const fixture = TestBed.createComponent(Host); + fixture.componentInstance.columns = [ + { key: 'Texto', title: 'Texto' }, + { key: 'Cantidad', title: 'Cantidad', type: 'number' }, + { key: 'Codigo', title: 'Código', align: 'right' }, + { key: 'Centrado', title: 'Centrado', align: 'center' }, + { key: 'Importe', title: 'Importe', type: 'number', align: 'left' }, + ]; + fixture.componentInstance.lines.set([{ Texto: 'a', Cantidad: 1, Codigo: 'x', Centrado: 'c', Importe: 5 }]); + fixture.detectChanges(); + await fixture.whenStable(); + fixture.detectChanges(); + const el = fixture.nativeElement as HTMLElement; + const heads = [...el.querySelectorAll('thead th')].slice(1, -1).map((t) => t.style.textAlign); + const cells = [0, 1, 2, 3, 4].map((c) => el.querySelector(`input[data-r="0"][data-c="${c}"]`)!.style.textAlign); + expect(heads).toEqual(['left', 'right', 'right', 'center', 'left']); + expect(cells).toEqual(['left', 'right', 'right', 'center', 'left']); + }); +}); diff --git a/apps/web/src/app/shared/grid/lines-grid.ts b/apps/web/src/app/shared/grid/lines-grid.ts index 448a7ea..43bd02b 100644 --- a/apps/web/src/app/shared/grid/lines-grid.ts +++ b/apps/web/src/app/shared/grid/lines-grid.ts @@ -70,6 +70,11 @@ export class LinesGrid { }); protected readonly lookupMultiple = computed(() => !!this.lookupTarget()?.column.lookup?.multiple); + /** Alineación de una columna: la declarada o, si no, derecha para las numéricas e izquierda para las demás. */ + protected alignOf(column: GridColumn): 'left' | 'center' | 'right' { + return column.align ?? (column.type === 'number' ? 'right' : 'left'); + } + protected cellText(line: GridLine, column: GridColumn): string { if (column.format) return column.format(line); const value = line[column.key];