feat(data-table): support generics (#1954)

Co-authored-by: K.Kiyokawa <koichi20110068@gmail.com>
Co-authored-by: brunnerh <brunnerh@users.noreply.github.com>
This commit is contained in:
Eric Liu 2024-11-11 21:10:45 -08:00 committed by GitHub
commit dd43224119
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 278 additions and 132 deletions

View file

@ -1,31 +1,34 @@
import type { SvelteComponentTyped } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
export type DataTableKey = string;
export type DataTableKey<Row = DataTableRow> =
import("./DataTableTypes.d.ts").PropertyPath<Row>;
export type DataTableValue = any;
export interface DataTableEmptyHeader {
key: DataTableKey;
export interface DataTableEmptyHeader<Row = DataTableRow> {
key: DataTableKey<Row> | (string & {});
empty: boolean;
display?: (item: DataTableValue, row: DataTableRow) => DataTableValue;
display?: (item: DataTableValue, row: Row) => DataTableValue;
sort?: false | ((a: DataTableValue, b: DataTableValue) => number);
columnMenu?: boolean;
width?: string;
minWidth?: string;
}
export interface DataTableNonEmptyHeader {
key: DataTableKey;
export interface DataTableNonEmptyHeader<Row = DataTableRow> {
key: DataTableKey<Row>;
value: DataTableValue;
display?: (item: DataTableValue, row: DataTableRow) => DataTableValue;
display?: (item: DataTableValue, row: Row) => DataTableValue;
sort?: false | ((a: DataTableValue, b: DataTableValue) => number);
columnMenu?: boolean;
width?: string;
minWidth?: string;
}
export type DataTableHeader = DataTableNonEmptyHeader | DataTableEmptyHeader;
export type DataTableHeader<Row = DataTableRow> =
| DataTableNonEmptyHeader<Row>
| DataTableEmptyHeader<Row>;
export interface DataTableRow {
id: any;
@ -34,27 +37,27 @@ export interface DataTableRow {
export type DataTableRowId = any;
export interface DataTableCell {
key: DataTableKey;
export interface DataTableCell<Row = DataTableRow> {
key: DataTableKey<Row> | (string & {});
value: DataTableValue;
display?: (item: DataTableValue, row: DataTableRow) => DataTableValue;
}
type $RestProps = SvelteHTMLElements["div"];
type $Props = {
type $Props<Row> = {
/**
* Specify the data table headers
* @default []
*/
headers?: ReadonlyArray<DataTableHeader>;
headers?: ReadonlyArray<DataTableHeader<Row>>;
/**
* Specify the rows the data table should render
* keys defined in `headers` are used for the row ids
* @default []
*/
rows?: ReadonlyArray<DataTableRow>;
rows?: ReadonlyArray<Row>;
/**
* Set the size of the data table
@ -90,7 +93,7 @@ type $Props = {
* Specify the header key to sort by
* @default null
*/
sortKey?: DataTableKey;
sortKey?: DataTableKey<Row>;
/**
* Specify the sort direction
@ -181,49 +184,46 @@ type $Props = {
[key: `data-${string}`]: any;
};
export type DataTableProps = Omit<$RestProps, keyof $Props> & $Props;
export type DataTableProps<Row> = Omit<$RestProps, keyof $Props<Row>> &
$Props<Row>;
export default class DataTable extends SvelteComponentTyped<
DataTableProps,
export default class DataTable<
Row extends DataTableRow = DataTableRow,
> extends SvelteComponentTyped<
DataTableProps<Row>,
{
click: CustomEvent<{
header?: DataTableHeader;
row?: DataTableRow;
cell?: DataTableCell;
header?: DataTableHeader<Row>;
row?: Row;
cell?: DataTableCell<Row>;
}>;
["click:header--expand"]: CustomEvent<{ expanded: boolean }>;
["click:header"]: CustomEvent<{
header: DataTableHeader;
header: DataTableHeader<Row>;
sortDirection?: "ascending" | "descending" | "none";
}>;
["click:header--select"]: CustomEvent<{
indeterminate: boolean;
selected: boolean;
}>;
["click:row"]: CustomEvent<DataTableRow>;
["mouseenter:row"]: CustomEvent<DataTableRow>;
["mouseleave:row"]: CustomEvent<DataTableRow>;
["click:row--expand"]: CustomEvent<{
expanded: boolean;
row: DataTableRow;
}>;
["click:row--select"]: CustomEvent<{
selected: boolean;
row: DataTableRow;
}>;
["click:cell"]: CustomEvent<DataTableCell>;
["click:row"]: CustomEvent<Row>;
["mouseenter:row"]: CustomEvent<Row>;
["mouseleave:row"]: CustomEvent<Row>;
["click:row--expand"]: CustomEvent<{ expanded: boolean; row: Row }>;
["click:row--select"]: CustomEvent<{ selected: boolean; row: Row }>;
["click:cell"]: CustomEvent<DataTableCell<Row>>;
},
{
default: {};
cell: {
row: DataTableRow;
cell: DataTableCell;
row: Row;
cell: DataTableCell<Row>;
rowIndex: number;
cellIndex: number;
};
["cell-header"]: { header: DataTableNonEmptyHeader };
description: {};
["expanded-row"]: { row: DataTableRow };
["expanded-row"]: { row: Row };
title: {};
}
> {}

18
types/DataTable/DataTableTypes.d.ts vendored Normal file
View file

@ -0,0 +1,18 @@
type PathDepth = [never, 0, 1, 2, ...0[]];
type Join<K, P> = K extends string | number
? P extends string | number
? `${K}${"" extends P ? "" : "."}${P}`
: never
: never;
// For performance, the maximum traversal depth is 10.
export type PropertyPath<T, D extends number = 10> = [D] extends [never]
? never
: T extends object
? {
[K in keyof T]-?: K extends string | number
? `${K}` | Join<K, PropertyPath<T[K], PathDepth[D]>>
: never;
}[keyof T]
: "";