This documentation is still work in progress, so be please patient.

# Table

Common `Table` is a dummy thing without any data bindings with improved typings and usage, then the pure one from Mantine.

## Minimal example

Recommanded bare minimum for a table is to define it's column type and item (entity) it's working with. Also you have to specify column names a table is needing as they force you to specify all of them in the implementation and allows for type-safe competition around the table.

### Code

DefaultTable.tsx

    import {
        type ITableColumn,
        Table
    } from "@leight/table-client";

    /**
     * Defined your column type
     */
    export type IDefaultTableColumn = ITableColumn<{
        /**
         * Each column must provide an ID
         */
        id: string;
        foo: string;
        number: number;
    }>;

    /**
     * Define columns you're working with; table will enforce you to specify all
     * columns by it's typings.
     *
     * That's because you can change or override columns if you wish.
     */
    export type IDefaultTableColumnKeys =
        "id"
        | "foo"
        | "number"

    export const DefaultTable = () => {
        return <Table<IDefaultTableColumn, IDefaultTableColumnKeys>
            columns={{
                /**
                 * See type in the IDE to reveal it's mysteries
                 */
                id: {
                    render: "id",
                },
                /**
                 * When you want to render the same value as it's input object,
                 * just provide the property name (typed).
                 *
                 * This structure is enforced, because if you change your mind later
                 * on and put some other properties (like width), it's much simpler to
                 * do so.
                 */
                number: {
                    width:  10,
                    render: "number",
                },
                foo:    {
                    width: 120,
                    /**
                     * Yaay! You can provide custom render method. Input is your `TItem`.
                     */
                    render: ({foo}) => {
                        return <>extended {foo}</>;
                    },
                },
            }}
            /**
             * Items you wish to render; this is the simplest example
             */
            items={[
                {id: "1", foo: "foo1", number: 1},
                {id: "2", foo: "foo2", number: 2},
                {id: "42", foo: "foo42", number: 42},
            ]}
        />;
    };

### Result

id | number | foo
--- | --- | ---
1 | 1 | extended foo1
2 | 2 | extended foo2
42 | 42 | extended foo42

## A bit advanced example

This example shows how you can change column order and override "built-in" columns provided by table. This is useful when you define default table implementation and later you want to change something without messing up with the original table internals.

### Code

BetterTable

    import {
        type ITableColumn,
        type ITableProps,
        Table
    }                from "@leight/table-client";
    import {type FC} from "react";

    /**
     * Defined your column type
     */
    export type IBetterTableColumn = ITableColumn<{
        /**
         * Each column must provide an ID
         */
        id: string;
        foo: string;
        number: number;
    }>;

    /**
     * Define columns you're working with; table will enforce you to specify all
     * columns by its typings.
     *
     * That's because you can change or override columns if you wish.
     */
    export type IBetterTableColumnKeys =
        "id"
        | "foo"
        | "number"

    /**
     * Re-export table props.
     */
    export interface IBetterTableProps extends ITableProps<IBetterTableColumn, IBetterTableColumnKeys> {
    }

    export const BetterTable: FC<IBetterTableProps> = props => {
        return <Table<IBetterTableColumn, IBetterTableColumnKeys>
            columns={{
                /**
                 * See type in the IDE to reveal its mysteries
                 */
                id: {
                    /**
                     * When you provide title, it goes through the translation, but
                     * if not found, just the title is returned (in this cas column name
                     * will be just ID)
                     *
                     * The Drawback is that you won't see the whole i18n sentence you have to add
                     * to translations.
                     */
                    title:  "ID",
                    render: "id",
                },
                /**
                 * When you want to render the same value as it's input object,
                 * just provide the property name (typed).
                 *
                 * This structure is enforced, because if you change your mind later
                 * on and put some other properties (like width), it's much simpler to
                 * do so.
                 */
                number: {
                    width:  10,
                    render: () => "nope",
                },
                foo:    {
                    width: 120,
                    /**
                     * Yaay! You can provide custom render method. Input is your `TItem`.
                     */
                    render: ({foo}) => {
                        return <>extended {foo}</>;
                    },
                },
            }}
            order={[
                "number",
                "id",
                "foo"
            ]}
            overrideColumns={{
                number: {
                    render: ({number}) => number * 2,
                },
            }}
            /**
             * Items you wish to render; this is the simplest example
             */
            items={[
                {id: "1", foo: "foo1", number: 1},
                {id: "2", foo: "foo2", number: 2},
                {id: "42", foo: "foo42", number: 42},
            ]}
            {...props}
        />;
    };

### Result

ℹ️

Notice that the first column has different values as the override is in action.

number | ID | foo
--- | --- | ---
2 | 1 | extended foo1
4 | 2 | extended foo2
84 | 42 | extended foo42

## Loading state

### Code

Same as above, but with `isLoading` prop.

### Result

number | ID | foo
--- | --- | ---
2 | 1 | extended foo1
4 | 2 | extended foo2
84 | 42 | extended foo42

Overview SourceTable