From b8d7657708f27e3ab0045f74fcc371c3de173f83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20R=C3=B8ed?= Date: Wed, 23 Sep 2026 01:08:38 +0200 Subject: [PATCH] Add AnyColumn and AnyTable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The args of a Cell are the args of a function, so a column that carries them is not a column that carries none. Code that only reads a column — a column menu, an export, a reordering helper — had to name those args and then ignore them, in every signature it has. These two say "any args" instead, and carry the row type and the column meta such code does read. Cowritten by Claude --- .../-private/-type-tests/any-column.test.ts | 37 +++++++++++++++++++ table/src/-private/any.ts | 32 ++++++++++++++++ table/src/index.ts | 1 + 3 files changed, 70 insertions(+) create mode 100644 table/src/-private/-type-tests/any-column.test.ts create mode 100644 table/src/-private/any.ts diff --git a/table/src/-private/-type-tests/any-column.test.ts b/table/src/-private/-type-tests/any-column.test.ts new file mode 100644 index 0000000..4eeb933 --- /dev/null +++ b/table/src/-private/-type-tests/any-column.test.ts @@ -0,0 +1,37 @@ +import { headlessTable } from '../../index.ts'; + +import type { AnyColumn, AnyTable, CellContext } from '../../index.ts'; +import type { ComponentLike } from '@glint/template'; + +interface Person { + name: string; +} +declare const people: Person[]; +interface MenuMeta { + hidingDisabled?: boolean; +} + +declare const GroupedCell: ComponentLike< + CellContext & { groupBy: 'day' | 'week' } +>; + +const table = headlessTable( + {}, + { + columns: () => [ + { key: 'name', Cell: GroupedCell, meta: { hidingDisabled: true } }, + ], + data: () => people, + }, +); + +// Code that reads a column, whatever its Cells ask for, and names no args. +function isLocked(column: AnyColumn) { + return column.meta?.hidingDisabled ?? false; +} +function columnCount(table: AnyTable) { + return table.columns.length; +} + +isLocked(table.columns[0]!); +columnCount(table); diff --git a/table/src/-private/any.ts b/table/src/-private/any.ts new file mode 100644 index 0000000..cc075fe --- /dev/null +++ b/table/src/-private/any.ts @@ -0,0 +1,32 @@ +import type { Column } from './column.ts'; +import type { Table } from './table.ts'; + +/** + * A column of any table, for code that reads a column without rendering its Cell. + * + * The args of a `Cell` are the args of a function, so a column that carries them + * is not a column that carries none. Code that only reads `key`, `name` or `meta` + * would have to name those args and then ignore them. This says "any args" instead. + * + * ```ts + * function widthOf(column: AnyColumn) { + * return column.meta?.width; + * } + * ``` + */ +export type AnyColumn = Column< + T, + ColumnMeta, + any, + any +>; + +/** + * A table of any shape, the counterpart of `AnyColumn`. + */ +export type AnyTable = Table< + T, + ColumnMeta, + any, + any +>; diff --git a/table/src/index.ts b/table/src/index.ts index af8b79b..475894c 100644 --- a/table/src/index.ts +++ b/table/src/index.ts @@ -11,6 +11,7 @@ export { deserializeSorts, serializeSorts } from './utils.ts'; * Public Types *******************************/ export type { Column } from './-private/column.ts'; +export type { AnyColumn, AnyTable } from './-private/any.ts'; export type { CellContext, ColumnConfig,