All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
134 lines
3 KiB
TypeScript
134 lines
3 KiB
TypeScript
import React, {useContext} from "react";
|
|
import {AutoColumnContextProvider, ColumnContext, ColumnKey} from "./Column";
|
|
import {CellDefinition, CellInstance, CellLoader} from "./Cell";
|
|
import {Smartable, useTable} from "./Smartable";
|
|
import { Promisable} from "@kernelui/core";
|
|
import {CurrentRowData} from "./AsyncManager";
|
|
|
|
/**
|
|
* Smartable row cells.
|
|
*/
|
|
export type RowCells<CK extends ColumnKey, T = any> = Record<CK, Promisable<CellDefinition<T>>>;
|
|
|
|
/**
|
|
* Smartable row data.
|
|
*/
|
|
export interface RowData<CK extends ColumnKey, T = any>
|
|
{
|
|
/**
|
|
* Cells definition.
|
|
*/
|
|
cells: RowCells<CK, T>;
|
|
|
|
/**
|
|
* Rendered row element.
|
|
*/
|
|
element?: React.ReactElement;
|
|
|
|
/**
|
|
* Rendered row cell element.
|
|
*/
|
|
cellElement?: React.ReactElement;
|
|
}
|
|
|
|
/**
|
|
* Smartable row definition.
|
|
*/
|
|
export type RowDefinition<CK extends ColumnKey> = RowCells<CK>|RowData<CK>;
|
|
|
|
/**
|
|
* Normalize row definition to row data.
|
|
*/
|
|
export function normalizeRowDefinition<CK extends ColumnKey>(rowDefinition: RowDefinition<CK>): RowData<CK>
|
|
{
|
|
if (!("cells" in rowDefinition) || !Object.values(rowDefinition?.cells).some((cellData: Promisable<CellDefinition>) => (
|
|
cellData instanceof Promise || ("data" in cellData)
|
|
))) { // If the row definition doesn't form a RowData object (= it is a RowCell object), converting it.
|
|
rowDefinition = {
|
|
cells: rowDefinition as RowCells<CK>,
|
|
};
|
|
}
|
|
|
|
// Return changed row definition, or just keep the default one if it matched RowData.
|
|
return rowDefinition;
|
|
}
|
|
|
|
/**
|
|
* Table row context data.
|
|
*/
|
|
export interface RowContextData<CK extends ColumnKey, T = any> extends CurrentRowData<CK, T>
|
|
{
|
|
}
|
|
|
|
const RowContext = React.createContext<RowContextData<ColumnKey>>(undefined);
|
|
|
|
/**
|
|
* Hook to get current row data.
|
|
*/
|
|
export function useRow<CK extends ColumnKey, T = any>(smartable?: Smartable<CK>): RowContextData<CK, T>
|
|
{
|
|
return useContext(RowContext);
|
|
}
|
|
|
|
/**
|
|
* Default row component.
|
|
*/
|
|
export function Row()
|
|
{
|
|
return (
|
|
<tr>
|
|
<RowCells />
|
|
</tr>
|
|
);
|
|
}
|
|
|
|
export function RowCells()
|
|
{
|
|
// Get row data.
|
|
const row = useRow();
|
|
|
|
// Get table data.
|
|
const {columns} = useTable();
|
|
|
|
return (
|
|
Object.keys(columns).map((columnKey) => (
|
|
<AutoColumnContextProvider key={columnKey} columnKey={columnKey}>
|
|
{ // Show current cell.
|
|
row.cells?.[columnKey]
|
|
? <CellInstance cell={row.cells?.[columnKey]} />
|
|
: <CellLoader />
|
|
}
|
|
</AutoColumnContextProvider>
|
|
))
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Row instance component.
|
|
*/
|
|
export function RowInstance<CK extends ColumnKey>({row}: { row: CurrentRowData<CK> })
|
|
{
|
|
// Get table row element.
|
|
const {rowElement} = useTable();
|
|
|
|
return (
|
|
<RowContext.Provider value={row}>
|
|
{ // Trying to render row-specific element, then table-specific element, then default element.
|
|
row.element ?? rowElement ?? <Row />
|
|
}
|
|
</RowContext.Provider>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Animated row loader.
|
|
*/
|
|
export function RowLoader()
|
|
{
|
|
// Get table columns to get their count.
|
|
const {columns} = useTable();
|
|
|
|
return (
|
|
<tr><td colSpan={Object.keys(columns).length} className={"generic loader"}></td></tr>
|
|
)
|
|
}
|