Table 10.17.2

ARIA
RTL

A component for displaying large amounts of data in rows and columns. Based on TanStack Table v8.

Default

First Name
Last Name
Age
Visits
Progress
Activity
Status
TestTest00000
TestTest30100100100100
TestTest60200200200200
TestTest90300300300300
TestTest120400400400400
"use client";

import { useCallback, useMemo } from "react";
import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
import type { ColumnDef } from "@heathmont/moon-table-v8-tw/lib/es/private/types";

type DefaultHelper = {
  firstName: string;
  lastName: string;
  age: string;
  visits: string;
  progress: string;
  status: number;
  activity: number;
};

const Example = () => {
  const makeData = useCallback((length: number) => {
    return Array.from("_".repeat(length)).map((_, index) => {
      return {
        firstName: "Test",
        lastName: "Test",
        age: <span>{Math.floor(index * 30)}</span>,
        visits: <span>{Math.floor(index * 100)}</span>,
        progress: <span>{Math.floor(index * 100)}</span>,
        status: Math.floor(index * 100),
        activity: Math.floor(index * 100),
      };
    });
  }, []);

  const columns = useMemo<ColumnDef<{}, DefaultHelper>[]>(
    () => [
      {
        id: "firstName",
        header: () => "First Name",
        accessorKey: "firstName",
      },
      {
        id: "lastName",
        header: () => "Last Name",
        accessorKey: "lastName",
      },
      {
        id: "age",
        header: () => "Age",
        accessorKey: "age",
        cell: (props) => props.getValue(),
      },
      {
        id: "visits",
        header: () => "Visits",
        accessorKey: "visits",
        cell: (props) => props.getValue(),
      },
      {
        id: "progress",
        header: () => "Progress",
        accessorKey: "progress",
        cell: (props) => props.getValue(),
      },
      {
        id: "activity",
        header: () => "Activity",
        accessorKey: "activity",
      },
      {
        id: "status",
        header: () => "Status",
        accessorKey: "status",
      },
    ],
    [],
  );
  const data = useMemo(() => makeData(5), [makeData]);

  return (
    <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
      <Table columns={columns} data={data} />
    </div>
  );
};

export default Example;

    Different row gaps

    Examples with gap values of: 0, 2px (default), 4px, 8px and 12px.

    First Name
    Last Name
    Age
    Visits
    Progress
    Activity
    Status
    TestTest00000
    TestTest30100100100100
    First Name
    Last Name
    Age
    Visits
    Progress
    Activity
    Status
    TestTest00000
    TestTest30100100100100
    First Name
    Last Name
    Age
    Visits
    Progress
    Activity
    Status
    TestTest00000
    TestTest30100100100100
    First Name
    Last Name
    Age
    Visits
    Progress
    Activity
    Status
    TestTest00000
    TestTest30100100100100
    First Name
    Last Name
    Age
    Visits
    Progress
    Activity
    Status
    TestTest00000
    TestTest30100100100100
    "use client";
    
    import { useCallback, useMemo } from "react";
    import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
    import type { ColumnDef } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
    
    type DefaultHelper = {
      firstName: string;
      lastName: string;
      age: string;
      visits: string;
      progress: string;
      status: number;
      activity: number;
    };
    
    const Example = () => {
      const makeData = useCallback((length: number) => {
        return Array.from("_".repeat(length)).map((_, index) => {
          return {
            firstName: "Test",
            lastName: "Test",
            age: <span>{Math.floor(index * 30)}</span>,
            visits: <span>{Math.floor(index * 100)}</span>,
            progress: <span>{Math.floor(index * 100)}</span>,
            status: Math.floor(index * 100),
            activity: Math.floor(index * 100),
          };
        });
      }, []);
    
      const columns = useMemo<ColumnDef<{}, DefaultHelper>[]>(
        () => [
          {
            id: "firstName",
            header: () => "First Name",
            accessorKey: "firstName",
          },
          {
            id: "lastName",
            header: () => "Last Name",
            accessorKey: "lastName",
          },
          {
            id: "age",
            header: () => "Age",
            accessorKey: "age",
            cell: (props) => props.getValue(),
          },
          {
            id: "visits",
            header: () => "Visits",
            accessorKey: "visits",
            cell: (props) => props.getValue(),
          },
          {
            id: "progress",
            header: () => "Progress",
            accessorKey: "progress",
            cell: (props) => props.getValue(),
          },
          {
            id: "activity",
            header: () => "Activity",
            accessorKey: "activity",
          },
          {
            id: "status",
            header: () => "Status",
            accessorKey: "status",
          },
        ],
        [],
      );
      const data = useMemo(() => makeData(2), [makeData]);
    
      return (
        <>
          <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
            <Table columns={columns} data={data} rowGap="0" />
          </div>
          <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
            <Table columns={columns} data={data} />
          </div>
          <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
            <Table columns={columns} data={data} rowGap="4px" />
          </div>
          <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
            <Table columns={columns} data={data} rowGap="8px" />
          </div>
          <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
            <Table columns={columns} data={data} rowGap="12px" />
          </div>
        </>
      );
    };
    
    export default Example;
    

      Different row sizes

      First Name
      Last Name
      Age
      Visits
      Progress
      Activity
      Status
      TestTest00000
      TestTest30100100100100
      First Name
      Last Name
      Age
      Visits
      Progress
      Activity
      Status
      TestTest00000
      TestTest30100100100100
      First Name
      Last Name
      Age
      Visits
      Progress
      Activity
      Status
      TestTest00000
      TestTest30100100100100
      First Name
      Last Name
      Age
      Visits
      Progress
      Activity
      Status
      TestTest00000
      TestTest30100100100100
      First Name
      Last Name
      Age
      Visits
      Progress
      Activity
      Status
      TestTest00000
      TestTest30100100100100
      First Name
      Last Name
      Age
      Visits
      Progress
      Activity
      Status
      TestTest00000
      TestTest30100100100100
      "use client";
      
      import { useCallback, useMemo } from "react";
      import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
      import type { ColumnDef } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
      
      type DefaultHelper = {
        firstName: string;
        lastName: string;
        age: string;
        visits: string;
        progress: string;
        status: number;
        activity: number;
      };
      
      const Example = () => {
        const makeData = useCallback((length: number) => {
          return Array.from("_".repeat(length)).map((_, index) => {
            return {
              firstName: "Test",
              lastName: "Test",
              age: <span>{Math.floor(index * 30)}</span>,
              visits: <span>{Math.floor(index * 100)}</span>,
              progress: <span>{Math.floor(index * 100)}</span>,
              status: Math.floor(index * 100),
              activity: Math.floor(index * 100),
            };
          });
        }, []);
      
        const columns = useMemo<ColumnDef<{}, DefaultHelper>[]>(
          () => [
            {
              id: "firstName",
              header: () => "First Name",
              accessorKey: "firstName",
            },
            {
              id: "lastName",
              header: () => "Last Name",
              accessorKey: "lastName",
            },
            {
              id: "age",
              header: () => "Age",
              accessorKey: "age",
              cell: (props) => props.getValue(),
            },
            {
              id: "visits",
              header: () => "Visits",
              accessorKey: "visits",
              cell: (props) => props.getValue(),
            },
            {
              id: "progress",
              header: () => "Progress",
              accessorKey: "progress",
              cell: (props) => props.getValue(),
            },
            {
              id: "activity",
              header: () => "Activity",
              accessorKey: "activity",
            },
            {
              id: "status",
              header: () => "Status",
              accessorKey: "status",
            },
          ],
          [],
        );
        const data = useMemo(() => makeData(2), [makeData]);
      
        return (
          <>
            <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
              <Table columns={columns} data={data} rowSize="xs" />
            </div>
            <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
              <Table columns={columns} data={data} rowSize="sm" />
            </div>
            <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
              <Table columns={columns} data={data} />
            </div>
            <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
              <Table columns={columns} data={data} rowSize="lg" />
            </div>
            <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
              <Table columns={columns} data={data} rowSize="xl" />
            </div>
            <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
              <Table columns={columns} data={data} rowSize="2xl" />
            </div>
          </>
        );
      };
      
      export default Example;
      

        Cell borders

        First Name
        Last Name
        Age
        Visits
        Progress
        Activity
        Status
        Test
        Test
        0
        0
        0
        0
        0
        Test
        Test
        30
        100
        100
        100
        100
        Test
        Test
        60
        200
        200
        200
        200
        Test
        Test
        90
        300
        300
        300
        300
        Test
        Test
        120
        400
        400
        400
        400
        "use client";
        
        import { useMemo, useCallback } from "react";
        import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
        import type { ColumnDef } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
        
        type DefaultHelper = {
          firstName: string;
          lastName: string;
          age: string;
          visits: string;
          progress: string;
          status: number;
          activity: number;
        };
        
        const Example = () => {
          const makeData = useCallback((length: number) => {
            return Array.from("_".repeat(length)).map((_, index) => {
              return {
                firstName: "Test",
                lastName: "Test",
                age: <span>{Math.floor(index * 30)}</span>,
                visits: <span>{Math.floor(index * 100)}</span>,
                progress: <span>{Math.floor(index * 100)}</span>,
                status: Math.floor(index * 100),
                activity: Math.floor(index * 100),
              };
            });
          }, []);
        
          const columns = useMemo<ColumnDef<{}, DefaultHelper>[]>(
            () => [
              {
                id: "firstName",
                header: () => "First Name",
                accessorKey: "firstName",
              },
              {
                id: "lastName",
                header: () => "Last Name",
                accessorKey: "lastName",
              },
              {
                id: "age",
                header: () => "Age",
                accessorKey: "age",
                cell: (props) => props.getValue(),
              },
              {
                id: "visits",
                header: () => "Visits",
                accessorKey: "visits",
                cell: (props) => props.getValue(),
              },
              {
                id: "progress",
                header: () => "Progress",
                accessorKey: "progress",
                cell: (props) => props.getValue(),
              },
              {
                id: "activity",
                header: () => "Activity",
                accessorKey: "activity",
              },
              {
                id: "status",
                header: () => "Status",
                accessorKey: "status",
              },
            ],
            [],
          );
          const data = useMemo(() => makeData(5), [makeData]);
        
          return (
            <div className="w-full max-w-screen-lg border border-beerus rounded-lg overflow-hidden">
              <Table
                columns={columns}
                data={data}
                layout="stretched-auto"
                isResizable
                withCellBorder
              />
            </div>
          );
        };
        
        export default Example;
        

          Clickable rows

          This example demonstrates the capabilities of a table with clickable rows.


          Use the mouse wheel or the arrow keys on the keyboard to scroll the data up and down.


          Watch the result of clicking on the rows in the browser console.

          First Name
          Last Name
          Age
          Visits
          Progress
          Activity
          Status
          TestTest00000
          TestTest30100100100100
          TestTest60200200200200
          TestTest90300300300300
          TestTest120400400400400
          TestTest150500500500500
          TestTest180600600600600
          TestTest210700700700700
          TestTest240800800800800
          TestTest270900900900900
          TestTest3001000100010001000
          TestTest3301100110011001100
          TestTest3601200120012001200
          TestTest3901300130013001300
          TestTest4201400140014001400
          TestTest4501500150015001500
          TestTest4801600160016001600
          TestTest5101700170017001700
          TestTest5401800180018001800
          TestTest5701900190019001900
          "use client";
          
          import { useCallback, useMemo, useState } from "react";
          import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
          import type {
            ColumnDef,
            Row,
          } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
          
          type DataTypeHelper = {
            firstName: string;
            lastName: string;
            age: string;
            visits: string;
            progress: string;
            status: number;
            activity: number;
          };
          
          const Example = () => {
            const makeData = useCallback((length: number) => {
              return Array.from("_".repeat(length)).map((_, index) => {
                return {
                  firstName: "Test",
                  lastName: "Test",
                  age: <span>{Math.floor(index * 30)}</span>,
                  visits: <span>{Math.floor(index * 100)}</span>,
                  progress: <span>{Math.floor(index * 100)}</span>,
                  status: Math.floor(index * 100),
                  activity: Math.floor(index * 100),
                };
              });
            }, []);
          
            const [data, setData] = useState(makeData(20));
          
            const columns = useMemo<ColumnDef<{}, DataTypeHelper>[]>(
              () => [
                {
                  header: () => "First Name",
                  accessorKey: "firstName",
                },
                {
                  header: () => "Last Name",
                  accessorKey: "lastName",
                },
                {
                  header: () => "Age",
                  accessorKey: "age",
                  cell: (props) => props.getValue(),
                },
                {
                  header: () => "Visits",
                  accessorKey: "visits",
                  cell: (props) => props.getValue(),
                },
                {
                  header: () => "Progress",
                  accessorKey: "progress",
                  cell: (props) => props.getValue(),
                },
                {
                  header: () => "Activity",
                  accessorKey: "activity",
                },
                {
                  header: () => "Status",
                  accessorKey: "status",
                },
              ],
              [],
            );
          
            return (
              <div className="border border-beerus rounded-lg overflow-hidden">
                <Table
                  columns={columns}
                  data={data}
                  width={800}
                  height={400}
                  layout="stretched-auto"
                  rowActiveColor="goku"
                  rowHoverColor="beerus"
                  isSelectable={true}
                  getOnRowClickHandler={(row: Row<{}>) => () => {
                    console.log(`You clicked row with ID - ${row.id}`);
                  }}
                />
              </div>
            );
          };
          
          export default Example;
          

            Expandable rows

            This example demonstrates the capabilities of a table with pre-set expandable rows.


            Use the mouse wheel or the arrow keys on the keyboard to scroll the data up and down.

            Name
            Info
            Actions
            More Info
            First Name
            Last Name
            Age
            Visits
            Status
            Profile Progress
            Actions
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            FirstName
            LastName401000complicated100
            Name
            Info
            Actions
            "use client";
            
            import { useCallback, useMemo, useState } from "react";
            import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
            import {
              ArrowsRefreshRound,
              ControlsChevronDown,
              ControlsChevronRight,
            } from "@heathmont/moon-icons-tw";
            import { Chip, Tooltip } from "@heathmont/moon-core-tw";
            import type DataHelper from "@heathmont/moon-table-v8-tw/lib/es/private/types/DataHelper";
            import type {
              ExpandedState,
              ColumnDef,
            } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
            
            interface Person extends DataHelper {
              firstName: string;
              lastName: string;
              age: number;
              visits: number;
              progress: number;
              status: "relationship" | "complicated" | "single";
              actions: JSX.Element;
              subRows?: Person[];
            }
            
            const Example = () => {
              const range = useCallback((len: number) => {
                const arr = [];
                for (let i = 0; i < len; i++) {
                  arr.push(i);
                }
                return arr;
              }, []);
            
              const tooltip = useMemo(
                () => (
                  <Tooltip>
                    <Tooltip.Trigger className="max-h-6">
                      <Chip
                        variant="ghost"
                        iconOnly={<ArrowsRefreshRound className="text-moon-24 max-h-6" />}
                        onClick={() => {
                          window.location.reload();
                        }}
                      />
                    </Tooltip.Trigger>
                    <Tooltip.Content position="top-start" className="z-[2]">
                      Reload page
                      <Tooltip.Arrow />
                    </Tooltip.Content>
                  </Tooltip>
                ),
                [],
              );
            
              const newPerson = useMemo((): Person => {
                return {
                  firstName: "FirstName",
                  lastName: "LastName",
                  age: 40,
                  visits: 1000,
                  progress: 100,
                  status: "complicated",
                  actions: tooltip,
                };
              }, [tooltip]);
            
              const makeData = useCallback(
                (...lens: number[]) => {
                  const makeDataLevel = (depth = 0): Person[] => {
                    const len = lens[depth]!;
                    return range(len).map((d): Person => {
                      return {
                        ...newPerson,
                        subRows: lens[depth + 1] ? makeDataLevel(depth + 1) : undefined,
                      };
                    });
                  };
            
                  return makeDataLevel();
                },
                [newPerson, range],
              );
            
              const columns = useMemo<ColumnDef<{}, Person>[]>(
                () => [
                  {
                    header: "Name",
                    footer: "Name",
                    columns: [
                      {
                        accessorKey: "firstName",
                        header: ({ table }) => (
                          <>
                            <button onClick={table.getToggleAllRowsExpandedHandler()}>
                              {table.getIsAllRowsExpanded() ? (
                                <ControlsChevronDown />
                              ) : (
                                <ControlsChevronRight />
                              )}
                            </button>{" "}
                            First Name
                          </>
                        ),
                        cell: ({ row, getValue }) => (
                          <div
                            style={{
                              paddingLeft: `${row.depth * 2}rem`,
                            }}
                            className="flex gap-x-1"
                          >
                            <>
                              {row.getCanExpand() ? (
                                <button
                                  className="cursor-pointer"
                                  onClick={row.getToggleExpandedHandler()}
                                >
                                  {row.getIsExpanded() ? (
                                    <ControlsChevronDown />
                                  ) : (
                                    <ControlsChevronRight />
                                  )}
                                </button>
                              ) : null}
                              {getValue()}
                            </>
                          </div>
                        ),
                      },
                      {
                        accessorFn: (row: Person) => row.lastName,
                        id: "lastName",
                        cell: (info) => info.getValue(),
                        header: () => <span>Last Name</span>,
                      },
                    ],
                  },
                  {
                    header: "Info",
                    footer: "Info",
                    columns: [
                      {
                        accessorKey: "age",
                        header: "Age",
                      },
                      {
                        header: "More Info",
                        columns: [
                          {
                            accessorKey: "visits",
                            header: () => <span>Visits</span>,
                          },
                          {
                            accessorKey: "status",
                            header: "Status",
                          },
                          {
                            accessorKey: "progress",
                            header: "Profile Progress",
                          },
                        ],
                      },
                    ],
                  },
                  {
                    id: "actions",
                    header: "Actions",
                    footer: (props) => "Actions",
                    columns: [
                      {
                        header: "Actions",
                        accessorKey: "actions",
                        cell: (props) => props.getValue(),
                      },
                    ],
                  },
                ],
                [],
              );
            
              const preset: ExpandedState = {
                "0": true,
                "0.2": true,
                "0.2.1": true,
              };
            
              const [expanded, setExpanded] = useState<ExpandedState>(preset);
              const [data, setData] = useState(makeData(10, 5, 3));
            
              const getSubRows = useCallback(
                ({ subRows }: DataHelper) => subRows as DataHelper[],
                [],
              );
            
              return (
                <div className="border border-beerus rounded-lg overflow-hidden">
                  <Table
                    columns={columns}
                    data={data}
                    width={800}
                    height={600}
                    layout="stretched-auto"
                    state={{ expanded }}
                    getSubRows={getSubRows}
                    onExpandedChange={setExpanded}
                    withFooter={true}
                  />
                </div>
              );
            };
            
            export default Example;
            

              Selectable rows

              This example demonstrates the capabilities of a table with pre-set selectable rows.


              Use the mouse wheel or the arrow keys on the keyboard to scroll the data up and down.


              Watch the result of the row selection in the browser console.

              First Name
              Last Name
              Age
              Visits
              Progress
              Activity
              Status
              Actions
              TestTest
              0
              0
              0
              00
              TestTest
              30
              100
              100
              100100
              TestTest
              60
              200
              200
              200200
              TestTest
              90
              300
              300
              300300
              TestTest
              120
              400
              400
              400400
              TestTest
              150
              500
              500
              500500
              TestTest
              180
              600
              600
              600600
              TestTest
              210
              700
              700
              700700
              TestTest
              240
              800
              800
              800800
              TestTest
              270
              900
              900
              900900
              TestTest
              300
              1000
              1000
              10001000
              TestTest
              330
              1100
              1100
              11001100
              TestTest
              360
              1200
              1200
              12001200
              TestTest
              390
              1300
              1300
              13001300
              TestTest
              420
              1400
              1400
              14001400
              TestTest
              450
              1500
              1500
              15001500
              TestTest
              480
              1600
              1600
              16001600
              TestTest
              510
              1700
              1700
              17001700
              TestTest
              540
              1800
              1800
              18001800
              TestTest
              570
              1900
              1900
              19001900
              "use client";
              
              import { ReactNode, useCallback, useMemo, useState } from "react";
              import { Chip, Tooltip } from "@heathmont/moon-core-tw";
              import { ArrowsRefreshRound } from "@heathmont/moon-icons-tw";
              import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
              import type {
                ColumnDef,
                Row,
                RowSelectionState,
              } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
              
              type DataTypeHelper = {
                firstName: string;
                lastName: string;
                age: string;
                visits: string;
                progress: string;
                status: number;
                activity: number;
                actions: () => void;
              };
              
              const preset: RowSelectionState = {
                1: true,
                3: true,
                4: true,
                11: true,
                16: true,
              };
              
              const Example = () => {
                const tooltip = useMemo(
                  () => (
                    <Tooltip>
                      <Tooltip.Trigger className="max-h-6">
                        <Chip
                          variant="ghost"
                          iconOnly={<ArrowsRefreshRound className="text-moon-24 max-h-6" />}
                          onClick={() => {
                            window.location.reload();
                          }}
                        />
                      </Tooltip.Trigger>
                      <Tooltip.Content position="top-start" className="z-[2]">
                        Reload page
                        <Tooltip.Arrow />
                      </Tooltip.Content>
                    </Tooltip>
                  ),
                  [],
                );
              
                const makeData = useCallback(
                  (length: number) => {
                    return Array.from("_".repeat(length)).map((_, index) => {
                      return {
                        firstName: "Test",
                        lastName: "Test",
                        age: <span>{Math.floor(index * 30)}</span>,
                        visits: <span>{Math.floor(index * 100)}</span>,
                        progress: <span>{Math.floor(index * 100)}</span>,
                        status: Math.floor(index * 100),
                        activity: Math.floor(index * 100),
                        actions: tooltip,
                      };
                    });
                  },
                  [tooltip],
                );
              
                const [rowSelection, setRowSelection] = useState<RowSelectionState>(preset);
                const [data, setData] = useState(makeData(20));
              
                const columns = useMemo<ColumnDef<{}, DataTypeHelper>[]>(
                  () => [
                    {
                      header: () => "First Name",
                      accessorKey: "firstName",
                    },
                    {
                      header: () => "Last Name",
                      accessorKey: "lastName",
                    },
                    {
                      header: () => "Age",
                      accessorKey: "age",
                      cell: (props) => (
                        <div onClick={props.row.getToggleSelectedHandler()}>
                          {props.getValue() as unknown as ReactNode}
                        </div>
                      ),
                    },
                    {
                      header: () => "Visits",
                      accessorKey: "visits",
                      cell: (props) => (
                        <div onClick={props.row.getToggleSelectedHandler()}>
                          {props.getValue() as unknown as ReactNode}
                        </div>
                      ),
                    },
                    {
                      header: () => "Progress",
                      accessorKey: "progress",
                      cell: (props) => (
                        <div onClick={props.row.getToggleSelectedHandler()}>
                          {props.getValue() as unknown as ReactNode}
                        </div>
                      ),
                    },
                    {
                      header: () => "Activity",
                      accessorKey: "activity",
                    },
                    {
                      header: () => "Status",
                      accessorKey: "status",
                    },
                    {
                      header: () => "Actions",
                      accessorKey: "actions",
                      cell: (props) => props.getValue(),
                    },
                  ],
                  [],
                );
              
                return (
                  <div className="border border-beerus rounded-lg overflow-hidden">
                    <Table
                      columns={columns}
                      data={data}
                      width={800}
                      height={400}
                      layout="stretched-auto"
                      state={{ rowSelection }}
                      onRowSelectionChange={setRowSelection}
                      isSelectable={true}
                      getOnRowSelectHandler={() => (rows: Row<{}>[]) => {
                        console.log(
                          `IDs of selected rows - ${rows.map((row: Row<{}>) => row.id)}`,
                        );
                      }}
                    />
                  </div>
                );
              };
              
              export default Example;
              

                Selectable rows with checkboxes

                This example demonstrates the capabilities of a table with pre-set checkboxes in the selectable rows.


                Use the mouse wheel or the arrow keys on the keyboard to scroll the data up and down.


                Watch the result of the row selection in the browser console.

                First Name
                Last Name
                Age
                Visits
                Progress
                Activity
                Status
                Actions
                TestTest00000
                TestTest30100100100100
                TestTest60200200200200
                TestTest90300300300300
                TestTest120400400400400
                TestTest150500500500500
                TestTest180600600600600
                TestTest210700700700700
                TestTest240800800800800
                TestTest270900900900900
                TestTest3001000100010001000
                TestTest3301100110011001100
                TestTest3601200120012001200
                TestTest3901300130013001300
                TestTest4201400140014001400
                TestTest4501500150015001500
                TestTest4801600160016001600
                TestTest5101700170017001700
                TestTest5401800180018001800
                TestTest5701900190019001900
                "use client";
                
                import { useCallback, useMemo, useState } from "react";
                import { Checkbox, Chip, Tooltip } from "@heathmont/moon-core-tw";
                import { ArrowsRefreshRound } from "@heathmont/moon-icons-tw";
                import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
                import type {
                  ColumnDef,
                  Row,
                  RowSelectionState,
                } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
                
                type DataTypeHelper = {
                  firstName: string;
                  lastName: string;
                  age: string;
                  visits: string;
                  progress: string;
                  status: number;
                  activity: number;
                  actions: () => void;
                };
                
                const preset: RowSelectionState = {
                  1: true,
                  3: true,
                  4: true,
                  11: true,
                  16: true,
                };
                
                const Example = () => {
                  const tooltip = useMemo(
                    () => (
                      <Tooltip>
                        <Tooltip.Trigger className="max-h-6">
                          <Chip
                            variant="ghost"
                            iconOnly={<ArrowsRefreshRound className="text-moon-24 max-h-6" />}
                            onClick={() => {
                              window.location.reload();
                            }}
                          />
                        </Tooltip.Trigger>
                        <Tooltip.Content position="top-start" className="z-[2]">
                          Reload page
                          <Tooltip.Arrow />
                        </Tooltip.Content>
                      </Tooltip>
                    ),
                    [],
                  );
                
                  const makeData = useCallback(
                    (length: number) => {
                      return Array.from("_".repeat(length)).map((_, index) => {
                        return {
                          firstName: "Test",
                          lastName: "Test",
                          age: <span>{Math.floor(index * 30)}</span>,
                          visits: <span>{Math.floor(index * 100)}</span>,
                          progress: <span>{Math.floor(index * 100)}</span>,
                          status: Math.floor(index * 100),
                          activity: Math.floor(index * 100),
                          actions: tooltip,
                        };
                      });
                    },
                    [tooltip],
                  );
                
                  const [rowSelection, setRowSelection] = useState<RowSelectionState>(preset);
                  const [data, setData] = useState(makeData(20));
                
                  const columns = useMemo<ColumnDef<{}, DataTypeHelper>[]>(
                    () => [
                      {
                        id: "select",
                        header: ({ table }) => (
                          <div className="w-8 px-1">
                            <Checkbox
                              checked={table.getIsAllRowsSelected()}
                              indeterminate={table.getIsSomeRowsSelected()}
                              onChange={table.getToggleAllRowsSelectedHandler()}
                            />
                          </div>
                        ),
                        cell: ({ row }) => (
                          <div className="w-8 px-1">
                            <Checkbox
                              checked={row.getIsSelected()}
                              disabled={!row.getCanSelect()}
                              onChange={row.getToggleSelectedHandler()}
                            />
                          </div>
                        ),
                      },
                      {
                        header: () => "First Name",
                        accessorKey: "firstName",
                      },
                      {
                        header: () => "Last Name",
                        accessorKey: "lastName",
                      },
                      {
                        header: () => "Age",
                        accessorKey: "age",
                        cell: (props) => props.getValue(),
                      },
                      {
                        header: () => "Visits",
                        accessorKey: "visits",
                        cell: (props) => props.getValue(),
                      },
                      {
                        header: () => "Progress",
                        accessorKey: "progress",
                        cell: (props) => props.getValue(),
                      },
                      {
                        header: () => "Activity",
                        accessorKey: "activity",
                      },
                      {
                        header: () => "Status",
                        accessorKey: "status",
                      },
                      {
                        header: () => "Actions",
                        accessorKey: "actions",
                        cell: (props) => props.getValue(),
                      },
                    ],
                    [],
                  );
                
                  return (
                    <div className="border border-beerus rounded-lg overflow-hidden">
                      <Table
                        columns={columns}
                        data={data}
                        width={800}
                        height={400}
                        layout="stretched-auto"
                        state={{ rowSelection }}
                        onRowSelectionChange={setRowSelection}
                        preventSelectionByRowClick={true}
                        isSelectable={true}
                        getOnRowSelectHandler={() => (rows: Row<{}>[]) => {
                          console.log(
                            `IDs of selected rows - ${rows.map((row: Row<{}>) => row.id)}`,
                          );
                        }}
                      />
                    </div>
                  );
                };
                
                export default Example;
                

                  Expandable/Selectable rows

                  This example is a combination of expandable and selectable tables with pre-set parameters.


                  Use the mouse wheel or the arrow keys on the keyboard to scroll the data up and down.

                  Expand/Select
                  Name
                  Info
                  Actions
                  First Name
                  Age
                  Visits
                  Activity
                  Status
                  Profile Progress
                  Actions
                  Lvl13650541920
                  Sub lvl296823972
                  Sub lvl36382465259
                  Sub lvl3643556578
                  Sub lvl312459844
                  Sub lvl27452861
                  Sub lvl38998432454
                  Sub lvl35225359725
                  Sub lvl35554335624
                  Sub lvl2536334824
                  Sub lvl34653434436
                  Sub lvl34945435454
                  "use client";
                  
                  import { useCallback, useMemo, useState } from "react";
                  import {
                    Checkbox,
                    Chip,
                    Tooltip,
                    mergeClassnames,
                  } from "@heathmont/moon-core-tw";
                  import {
                    ArrowsRefreshRound,
                    ControlsChevronDown,
                    ControlsChevronRight,
                  } from "@heathmont/moon-icons-tw";
                  import { Table } from "@heathmont/moon-table-v8-tw/lib/es";
                  import type DataHelper from "@heathmont/moon-table-v8-tw/lib/es/private/types/DataHelper";
                  import type {
                    ColumnDef,
                    ExpandedState,
                    Row,
                    RowSelectionState,
                    TableInterface,
                  } from "@heathmont/moon-table-v8-tw/lib/es/private/types";
                  
                  interface DataTypeHelper extends DataHelper {
                    firstName: string;
                    lastName: string;
                    age: string;
                    visits: string;
                    progress: string;
                    status: number;
                    actions: () => void;
                    subRows?: DataTypeHelper[];
                  }
                  
                  const columnShift = (depth: number) => {
                    const shiftMap: { [key: number]: string } = ["ps-0", "ps-6", "ps-12"];
                  
                    return shiftMap[depth];
                  };
                  
                  const preset: RowSelectionState = {
                    0: true,
                    "0.1": true,
                    "0.1.0": true,
                    "0.1.1": true,
                  };
                  
                  const Example = () => {
                    const tooltip = useMemo(
                      () => (
                        <Tooltip>
                          <Tooltip.Trigger className="max-h-6">
                            <Chip
                              variant="ghost"
                              iconOnly={<ArrowsRefreshRound className="text-moon-24 max-h-6" />}
                              onClick={() => {
                                window.location.reload();
                              }}
                            />
                          </Tooltip.Trigger>
                          <Tooltip.Content position="top-start" className="z-[2]">
                            Reload page
                            <Tooltip.Arrow />
                          </Tooltip.Content>
                        </Tooltip>
                      ),
                      [],
                    );
                  
                    const makeData = useMemo(
                      () => [
                        {
                          firstName: "Lvl1",
                          age: <span>36</span>,
                          visits: <span>50</span>,
                          progress: <span>20</span>,
                          status: 19,
                          activity: 54,
                          actions: tooltip,
                          subRows: [
                            {
                              firstName: "Sub lvl2",
                              age: <span>96</span>,
                              visits: <span>8</span>,
                              progress: <span>2</span>,
                              status: 97,
                              activity: 23,
                              actions: tooltip,
                              subRows: [
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>63</span>,
                                  visits: <span>82</span>,
                                  progress: <span>59</span>,
                                  status: 52,
                                  activity: 46,
                                  actions: tooltip,
                                },
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>64</span>,
                                  visits: <span>35</span>,
                                  progress: <span>78</span>,
                                  status: 65,
                                  activity: 5,
                                  actions: tooltip,
                                },
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>12</span>,
                                  visits: <span>4</span>,
                                  progress: <span>44</span>,
                                  status: 98,
                                  activity: 5,
                                  actions: tooltip,
                                },
                              ],
                            },
                            {
                              firstName: "Sub lvl2",
                              age: <span>74</span>,
                              visits: <span>5</span>,
                              progress: <span>1</span>,
                              status: 86,
                              activity: 2,
                              actions: tooltip,
                              subRows: [
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>89</span>,
                                  visits: <span>98</span>,
                                  progress: <span>54</span>,
                                  status: 24,
                                  activity: 43,
                                  actions: tooltip,
                                },
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>52</span>,
                                  visits: <span>25</span>,
                                  progress: <span>25</span>,
                                  status: 97,
                                  activity: 35,
                                  actions: tooltip,
                                },
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>55</span>,
                                  visits: <span>54</span>,
                                  progress: <span>24</span>,
                                  status: 56,
                                  activity: 33,
                                  actions: tooltip,
                                },
                              ],
                            },
                            {
                              firstName: "Sub lvl2",
                              age: <span>53</span>,
                              visits: <span>63</span>,
                              progress: <span>24</span>,
                              status: 48,
                              activity: 3,
                              actions: tooltip,
                              subRows: [
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>4</span>,
                                  visits: <span>653</span>,
                                  progress: <span>36</span>,
                                  status: 44,
                                  activity: 43,
                                  actions: tooltip,
                                },
                                {
                                  firstName: "Sub lvl3",
                                  age: <span>49</span>,
                                  visits: <span>45</span>,
                                  progress: <span>454</span>,
                                  status: 35,
                                  activity: 4,
                                  actions: tooltip,
                                },
                              ],
                            },
                          ],
                        },
                      ],
                      [tooltip],
                    );
                  
                    const [rowSelection, setRowSelection] = useState<RowSelectionState>(preset);
                    const [expanded, setExpanded] = useState<ExpandedState>(true);
                    const [data, setData] = useState(makeData);
                  
                    const trackCheckState = (row: Row<{}>, table: TableInterface<{}>) => {
                      let parentRowId = row.parentId;
                      while (parentRowId) {
                        const nodeRow = table.getRow(parentRowId);
                        if (nodeRow.getIsAllSubRowsSelected() && !nodeRow.getIsSelected()) {
                          setRowSelection({ ...rowSelection, [nodeRow.id]: true });
                        } else if (
                          !nodeRow.getIsAllSubRowsSelected() &&
                          nodeRow.getIsSelected()
                        ) {
                          setRowSelection(
                            Object.keys(rowSelection)
                              .filter((rowId) => rowId !== nodeRow.id)
                              .reduce((acc: RowSelectionState, rowId: string) => {
                                acc[rowId] = true;
                                return acc;
                              }, {}),
                          );
                        }
                        parentRowId = nodeRow.parentId;
                      }
                  
                      return row.getIsSelected();
                    };
                  
                    const trackIndeterminateState = (row: Row<{}>) => {
                      const match = new RegExp(`(^${row.id}[\\.]|^${row.id}$)`, "");
                      const matches = Object.keys(rowSelection).filter(
                        (rowId) => match.test(rowId) && rowId !== row.id,
                      );
                  
                      return (
                        !row.getIsAllSubRowsSelected() &&
                        matches.some((rowId) => rowSelection[rowId] === true)
                      );
                    };
                  
                    const columns = useMemo<ColumnDef<{}, DataTypeHelper>[]>(
                      () => [
                        {
                          id: "expand/select",
                          header: () => "Expand/Select",
                          columns: [
                            {
                              id: "select",
                              header: ({ table }) => (
                                <div className="flex px-0 gap-x-1">
                                  <Checkbox
                                    checked={table.getIsAllRowsSelected()}
                                    indeterminate={table.getIsSomeRowsSelected()}
                                    onChange={table.getToggleAllRowsSelectedHandler()}
                                  />
                                  <button onClick={table.getToggleAllRowsExpandedHandler()}>
                                    {table.getIsAllRowsExpanded() ? (
                                      <ControlsChevronDown />
                                    ) : (
                                      <ControlsChevronRight />
                                    )}
                                  </button>
                                </div>
                              ),
                              cell: ({ row, table }) => (
                                <div
                                  className={mergeClassnames(
                                    "flex gap-x-1",
                                    columnShift(row.depth),
                                  )}
                                >
                                  <Checkbox
                                    checked={trackCheckState(row, table)}
                                    disabled={!row.getCanSelect()}
                                    indeterminate={trackIndeterminateState(row)}
                                    onChange={row.getToggleSelectedHandler()}
                                  />
                                  {row.getCanExpand() ? (
                                    <button
                                      onClick={row.getToggleExpandedHandler()}
                                      className="cursor-pointer"
                                    >
                                      {row.getIsExpanded() ? (
                                        <ControlsChevronDown />
                                      ) : (
                                        <ControlsChevronRight />
                                      )}
                                    </button>
                                  ) : (
                                    ""
                                  )}
                                </div>
                              ),
                            },
                          ],
                        },
                        {
                          id: "name",
                          header: () => "Name",
                          columns: [
                            {
                              header: () => "First Name",
                              accessorKey: "firstName",
                            },
                          ],
                        },
                        {
                          id: "info",
                          header: () => "Info",
                          columns: [
                            {
                              header: () => "Age",
                              accessorKey: "age",
                              cell: (props) => props.getValue(),
                              size: 30,
                            },
                            {
                              header: () => "Visits",
                              accessorKey: "visits",
                              cell: (props) => props.getValue(),
                              size: 60,
                            },
                            {
                              header: () => "Activity",
                              accessorKey: "activity",
                              size: 80,
                            },
                            {
                              header: () => "Status",
                              accessorKey: "status",
                              size: 80,
                            },
                            {
                              header: () => "Profile Progress",
                              accessorKey: "progress",
                              cell: (props) => props.getValue(),
                            },
                          ],
                        },
                        {
                          id: "actions",
                          header: () => "Actions",
                          size: 90,
                          columns: [
                            {
                              header: () => "Actions",
                              accessorKey: "actions",
                              cell: (props) => props.getValue(),
                              size: 90,
                            },
                          ],
                        },
                      ],
                      // eslint-disable-next-line react-hooks/exhaustive-deps
                      [rowSelection],
                    );
                  
                    const getSubRows = useCallback(
                      ({ subRows }: DataHelper) => subRows as DataHelper[],
                      [],
                    );
                  
                    return (
                      <div className="border border-beerus rounded-lg overflow-hidden">
                        <Table
                          columns={columns}
                          data={data}
                          width={800}
                          height={400}
                          layout="stretched-auto"
                          state={{ expanded, rowSelection }}
                          getSubRows={getSubRows}
                          onExpandedChange={setExpanded}
                          onRowSelectionChange={setRowSelection}
                          preventSelectionByRowClick={true}
                          isSelectable={true}
                        />
                      </div>
                    );
                  };
                  
                  export default Example;
                  

                    A table with minimap

                    Name
                    Info
                    Info1
                    Info2
                    Info3
                    Info4
                    Info5
                    Progress
                    First Name
                    Last Name
                    Age
                    Visits
                    Activity
                    Age1
                    Visits1
                    Activity1
                    Age2
                    Visits2
                    Activity2
                    Age3
                    Visits3
                    Activity3
                    Age4
                    Visits4
                    Activity4
                    Age5
                    Visits5
                    Activity5
                    Profile Progress
                    Test
                    Test
                    000000000000000000
                    0
                    Test
                    Test
                    301001003010010030100100301001003010010030100100
                    100
                    Test
                    Test
                    602002006020020060200200602002006020020060200200
                    200
                    Test
                    Test
                    903003009030030090300300903003009030030090300300
                    300
                    Test
                    Test
                    120400400120400400120400400120400400120400400120400400
                    400
                    Test
                    Test
                    150500500150500500150500500150500500150500500150500500
                    500
                    Test
                    Test
                    180600600180600600180600600180600600180600600180600600
                    600
                    Test
                    Test
                    210700700210700700210700700210700700210700700210700700
                    700
                    Test
                    Test
                    240800800240800800240800800240800800240800800240800800
                    800
                    Test
                    Test
                    270900900270900900270900900270900900270900900270900900
                    900
                    Test
                    Test
                    300100010003001000100030010001000300100010003001000100030010001000
                    1000
                    Test
                    Test
                    330110011003301100110033011001100330110011003301100110033011001100
                    1100
                    Test
                    Test
                    360120012003601200120036012001200360120012003601200120036012001200
                    1200
                    Test
                    Test
                    390130013003901300130039013001300390130013003901300130039013001300
                    1300
                    Test
                    Test
                    420140014004201400140042014001400420140014004201400140042014001400
                    1400
                    Test
                    Test
                    450150015004501500150045015001500450150015004501500150045015001500
                    1500
                    Test
                    Test
                    480160016004801600160048016001600480160016004801600160048016001600
                    1600
                    Test
                    Test
                    510170017005101700170051017001700510170017005101700170051017001700
                    1700
                    Test
                    Test
                    540180018005401800180054018001800540180018005401800180054018001800
                    1800
                    Test
                    Test
                    570190019005701900190057019001900570190019005701900190057019001900
                    1900
                    Test
                    Test
                    600200020006002000200060020002000600200020006002000200060020002000
                    2000
                    Test
                    Test
                    630210021006302100210063021002100630210021006302100210063021002100
                    2100
                    Test
                    Test
                    660220022006602200220066022002200660220022006602200220066022002200
                    2200
                    Test
                    Test
                    690230023006902300230069023002300690230023006902300230069023002300
                    2300
                    Test
                    Test
                    720240024007202400240072024002400720240024007202400240072024002400
                    2400
                    Test
                    Test
                    750250025007502500250075025002500750250025007502500250075025002500
                    2500
                    Test
                    Test
                    780260026007802600260078026002600780260026007802600260078026002600
                    2600
                    Test
                    Test
                    810270027008102700270081027002700810270027008102700270081027002700
                    2700
                    Test
                    Test
                    840280028008402800280084028002800840280028008402800280084028002800
                    2800
                    Test
                    Test
                    870290029008702900290087029002900870290029008702900290087029002900
                    2900
                    Test
                    Test
                    900300030009003000300090030003000900300030009003000300090030003000
                    3000
                    Test
                    Test
                    930310031009303100310093031003100930310031009303100310093031003100
                    3100
                    Test
                    Test
                    960320032009603200320096032003200960320032009603200320096032003200
                    3200
                    Test
                    Test
                    990330033009903300330099033003300990330033009903300330099033003300
                    3300
                    Test
                    Test
                    102034003400102034003400102034003400102034003400102034003400102034003400
                    3400
                    Test
                    Test
                    105035003500105035003500105035003500105035003500105035003500105035003500
                    3500