npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@lightspeed/cirrus-table

v1.0.4

Published

Cirrus Table Component

Downloads

2,804

Readme

Table

A set of recommended design rules and reusable React components to create tables of data quickly for specific workflow needs.

They should help customers find, view, organize and interact with their data in easy and convenient ways. The interface should disappear so that retailers can focus on the job at hand.

Installation

First, make sure you have been through the install steps steps required to add Flame in your application. Although it's not required to have Flame installed to use Logo, you will need to install its peer dependencies.

If using Yarn:

yarn add @lightspeed/cirrus-table

Or using npm:

npm i -S @lightspeed/cirrus-table

Styled System props

| Component Name | styled-system props | | -------------- | ----------------------------------------------------------------------------------------------------- | | Td | height | | | width | | | space | | | fontSize | | | textAlign | | | color | | Th | color | | | height | | | width | | | space | | | display | | | alignItems, justifyContent | | | fontSize | | Tr | color | | | space |

Usage

Components

<Table>

Note: you need to manually wrap the <Table> with a <Card> to get the recommended visual for tables. This is left to the consumer for maximum flexibility.

Styled table tag (<table>) with the following props:

| Prop | Type | Description | | ---------------- | ---------------------------- | ----------------------------------------------------------- | | loadingStatus? | "loading" or "completed" | Shows a loading indicator between the table header and body |

Base Table Elements

<Thead>

An augmented version of the table header which features a loading bar hooked onto the table's loading state

<Th>

A Styled System augmented table heading tag (<th>)

<Tr>

A Styled System augmented table row tag (<tr>)

| Prop | Type | Description | | ----------- | ------ | ----------------------------------------------------------- | | isHoverable | bool | If true, no hover style will be applied, false by default |

<Td>

A Styled System augmented table cell tag (<td>).

<Tbody>

An emotion instantiated tbody. No augmentation added, it's simply there for markup stylistic purposes.

<Tfoot>

An emotion instantiated tfoot. No augmentation added, it's simply there for markup stylistic purposes.

<NoDataTd>

An extension of <Td>. It comes with a pre-formatted styles for a no data state.

<Pager />

A simple pager component designed for the table.

| Prop | Type | Description | | -------------- | ------ | ------------------------------------------------------------ | | isFirst | bool | If true, the "back" pager button is disabled | | isLast | bool | If true, the "forward" pager button is disabled | | handleNext | func | Callback function attached to the the "forward" pager button | | handlePrevious | func | Callback function attached to the the "back" pager button | | children | any | Element will be added to the front of the Pager button group |

Table Action Components & Filtering

Additional actions can be added to the table.

Table exports an all encompassing Object called TableActions, which contains various components that are hooked to a single context that mostly handles the interconnected ui state possible within actions, e.g: filters and tags.

Using the TableActions.Context and Actions

The TableActions provides many ways to add and remove filters programaticaly.

Here are some of the exposed functions that will come in handy:

| Prop | Description | | ------------------------------------------------------------ | -------------------------------------------------------------- | | applyFilter(filterKey, label, value) | Upserts a new filter with a corresponding label and raw values | | applyFilters(Array<{key:string, value: any, label: string}>) | Replace filters with the current list sent in parameters | | deleteFilter(filterKey) | Delete a filter by key | | deleteAllFilters() | Deletes all filters | | deleteAllFiltersAndSearchTerm | Deletes all filters, including the search term | | getValues(filterKey) | Retrieves a global count of all active filters | | getFilters() | Retrieves the entire list of active filters |

There are two ways of gaining access to these functions:

Using React.useContext

const MyApp = () => {
  const { applyFilter, deleteFilter /* ... */ } = React.useContext(TableActions.Context);
};

Via the consumer component

const MyApp = () => {
  return (
    <TableActions.Consumer>
      {({ applyFilter, deleteFilter, /* ... */ }) => (
        /* ... */
      )}
    </TableActions.Consumer>
  );
}
TableActions.FilterPanelProvider

A Provider to keep track of active filters and routing of the TableActions.Dropdown

| Prop | Type | Description | | --------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | onFilterChange | func | Callback function that will receive in parameters the currently selected array of filters | | initialSearchTerm | string | The initial search term. If using TableActions.SearchBar, it'll automatically use the initialSearchTerm as it's value | | initialFilters | Array<{key:string, value: any, label: string}> | The initial filters for the table actions. See PagerTable on how to set initialFilters properly | | renderDropdownContent | ReactNode | The content that will be used within dropdowns. Primarely used to have a single point of entry for dropdown content used by the search bar dropdown and the filter tag dropdowns |

const MyApp = () => (
  <TableActions.Provider
    initialSearchTerm={{}}
    initialFilters={{}}
    onFilterChange={() => {}}
    renderDropdownContent={<div>The shared content that will appear in the Dropdown</div>}
  >
    {/*
        Render the rest of your content here.
    */}
  </TableActions.Provider>
);
TableActions.ActionBar

A wrapper component which sets the right positioning of elements. This is a simple dumb component with no logic.

| Prop | Type | Description | | ---------------- | ----------- | ------------------------------------------------------------------------------------ | | leftHandActions | ReactNode | Render slot the left. Usually, you will want to add you search bar and dropdown here | | rightHandActions | ReactNode | Render slot for right. The pager should be here | | children | ReactNode | |

const MyApp = () => (
  <TableActions.ActionBar
    leftHandActions={<div>this div will appear on the left</div>}
    rightHandActions={<div>this div will appear on the right</div>}
  >
    <div>this div will appear underneath the previously set actions</div>
  </TableActions.ActionBar>
);
TableActions.SearchBar

A prebuilt search bar component hooked onto the filtering context. Simply add and use.

Pressing enter or clicking on the button will trigger a change to the stored search term within the provider and cause onFilterChange to be executed.

| Prop | Type | Description | | ----------- | -------- | ----------------------------------------------------- | | buttonText | string | Text that appears on the search button | | buttonTitle | string | Text for title attribute of the search button | | placeholder | string | Placeholder text that appears on the search input | | disabled | bool | Set to true to disable search input and search button |

const MyApp = () => (
  <TableActions.Provider
    initalSearchTerm="I will automatically appear in the search bar"
    onFilterChange={(filters, searchTerm) => {
      // When pressing enter on the search bar or clicking on the submit button,
      // This function will be triggered
    }}
    renderDropdownContent={<div>The shared content that will appear in the Dropdown</div>}
  >
    <TableActions.SearchBar placeholder="Put your search term here" buttonText="Search" />
  </TableActions.Provider>
);
TableActions.FilterTagLister

A list of all Filters active. Automatically hooked to the TableActions.FilterPanelProvider. It will automatically select the right dropdown view, based on which tag has been picked.

| Prop | Type | Description | | -------------- | ----------- | ----------------------------------------------------------- | | renderDropdown | ReactNode | (Optional) Override of the provider's renderDropdownContent | | dropdownWidth | ReactNode | Width of the dropdown | | children | ReactNode | |

const MyApp = () => (
  <TableActions.Provider
    initalFilters={{
      status: {
        value: 'Any value to store relevant data for the filtering process'
        label: 'This is what will appear on a tag'
      }
    }}
    renderDropdownContent={
        <TableActions.Dropdown>
          {/*
            Notice how the initialFilters object has `status` as an object key
            If we want the TableActions.FilterTagLister to pick up the right
            TableActions.DropdownSection, ensure that the key and filterKey match!
          */}
          <TableActions.DropdownSection title="Just some title" filterKey="status">
            Anything in the `TableActions.DropdownSection` will be rendered when clicking
            on the Tag generated from `TableActions.FilterTagLister`
          </TableActions.DropdownSection>
        </TableActions.Dropdown>
    }
  >
    <TableActions.FilterTagLister />
  </TableActions.Provider>
);
TableActions.DropdownMenu

A wrapper component which will render automatically render the TableActions.Dropdown acquired from the provider. It will handle swapping between a list view or a detailed view.

| Prop | Type | Description | | -------------- | ----------- | ----------------------------------------------------------- | | renderDropdown | ReactNode | (Optional) Override of the provider's renderDropdownContent | | dropdownWidth | ReactNode | Width of the dropdown | | children | ReactNode | |

const MyApp = () => (
  <TableActions.Provider
    renderDropdownContent={
      <TableActions.Dropdown>
        This content will only be rendered within the list view...
        <TableActions.DropdownSection title="Just some title" filterKey="status">
          Anything in the `TableActions.DropdownSection` will be rendered when clicking on the
          corresponding link in the list view.
        </TableActions.DropdownSection>
      </TableActions.Dropdown>
    }
  >
    <TableActions.DropdownMenu />
  </TableActions.Provider>
);
TableActions.Dropdown

The main Dropdown component to be used within the container. This is needed to create the multi-page approach of the filtering dropdown.

Concretely, there are two pages within this dropdown: The listing page and the details page.

The "listing" page is simply whatever components passed in as child to the TableActions.Dropdown. It'll render whatever is passed in as is, with the exception of TableActions.DropdownSection.

If a TableActions.DropdownSection is detected, that component will instead output a clickable menu item. When clicked, the dropdown view will automatically swap to render out the given TableActions.DropdownSection children elements instead.

| Prop | Type | Description | | ---------- | -------- | -------------------------------------------------------------------------------------------------------------- | | goBackText | string | Text that appears on the "back" button within a details view. Automatically hidden when rendered within a tag. |

TableActions.DropdownSection

A section/page of the dropdown. Use this component to automatically create the filter menu within the Dropdown, as well as rendering a "details" view that will be rendered when selected.

| Prop | Type | Description | | --------- | ----------- | --------------------------------------------------------------------------------- | | title | string | Text that appears on the list view of the dropdown | | filterKey | string | Identifier for the section. For syncing the rendering of a section to a given tag | | children | ReactNode | |

TableActions.DropdownTitle

A pre configured version of Cirrus Text to fit the dropdown styling.

TableActions.DropdownActions

A pre configured version of Cirrus Flex to fit within dropdown styling. Use this to output your filter buttons.

TableActions.DropdownDivider

A pre configured version of Cirrus Divider. Use this to add a properly padded seperator between elements.

TableActions.DropdownButtonLink

A pre configured version of Cirrus Button that makes a button look like a link for usage within the Dropdown.

TableActions.CheckboxGroup

A prestyled and context aware checkbox group.

| Prop | Type | Description | | ---------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | checkboxes | Array<{ label: string, value: string}> | Config object to generate checkboxes. Simply pass in the label and the associated value | | filterKey | string | Identifier for the filter. Use this to bind the child functions to the appropriate filter key | | children | Child function ReactNode | Accepts a child function. It forwards an object with two following functions: undoChanges and applyFilter. undoChanges will clear the internal state of the checkbox group but not trigger an actual filter change. applyFilter accepts either a string to be applied as the label for a given tag or a callback function that sends the selected items in parameter and expects a string in return |

TableActions.RadioGroup

A prestyled and context aware radio group.

| Prop | Type | Description | | --------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | radios | Array<{ label: string, value: string}> | Config object to generate radios. Simply pass in the label and the associated value | | filterKey | string | Identifier for the filter. Use this to bind the child functions to the appropriate filter key | | children | Child function ReactNode | Accepts a child function. It forwards an object with two following functions: undoChanges and applyFilter. undoChanges will clear the internal state of the radio group but not trigger an actual filter change. applyFilter accepts either a string to be applied as the label for a given tag or a callback function that sends the selected items in parameter and expects a string in return |

All About Table Features

The Basics

By default, the table is completely stateless and allows you to build and structure it however you want, since the table provides multiple small building blocks.

We also provide some pre-built functionality in form of hooks that you can use immediately with the provided components.

The Sort Feature

Sort exports a hook that pre-binds state as well as a convenient SortButton component and a pre-built Th component that you can slide into the appropriate spot of the table.

import { Table, Thead, Tr, Td, Sortable } from '@lightspeed/cirrus-table';

const MyComponent = () => {
  const {  getSortingDirection, toggleSort, sortKey, sortDirection, setSort }  = Sortable.useSortable();
  // Observe our sortKey/sortDirection for any changes
  React.useEffect(() => {
      // And trigger a side-effect!
    }
  }, [sortKey, sortDirection]);

  return (
    <Card>
      {/* You can use setSort to force save a particular sort state */}
      <button onClick={() => setSort('animal', 'desc')}>
        Descending animals
      </button>

      <Table>
        <Thead>
          <Tr>
          <Sortable.Th
            onClick={toggleSort('animal') /* toggleSort automatically cycle through the sort */}
            direction={getSortingDirection('animal') /* Fully uncontrolled props*/}
          >
            Animal
          </Sortable.Th>
          </Tr>
        </Thead>
        <Tr>
          <Td>Lion</Td>
        </Tr>
        <Tr>
          <Td>Tiger</Td>
        </Tr>
        <Tr>
          <Td>Bear</Td>
        </Tr>
      </Table>
    </Card>
  );
}
Options

Sortable.useSortable

This hook takes two parameters, the first one is the sorting key and second value is the sort order.

Use this to set a default sort order.

const MyComponent = () => {
  const { getSortingDirection } = Sortable.useSortable('color', 'asc');

  getSortingDirection('color'); // this will return `asc`
  toggleSort('color'); // This will cycle through the next sorting direction...
  getSortingDirection('color'); // meaning this will now return `desc`

  // ...
};

As per UX, only one item can be sorted at a time, and it will always follow the following cycle:

unsorted -> ascending -> descending

Important note: as of right now, we only support 1 sort option at a time.

Components

<Sortable.SortButton>

| Prop | Type | Description | | ----------- | -------- | -------------------------------------- | | direction | string | The direction of the arrow for sorting |

<Sortable.Th>

Convenience compone that simply wraps the SortButton inside a Th.

| Prop | Type | Description | | ----------- | ---------- | -------------------------------------- | | direction | string | The direction of the arrow for sorting | | onClick | function | Good ol' function |

Examples

See the examples folder.

The Batch Select Feature

Batch Select exposes multiple components as well a hook to manage state. You may use both of them, or mix and match functionalities.

While there may be many functions to bind, most of them are fairly straight forwards to use and self explanatory.

Example

import { Table, Thead, TBody, Td, BatchSelect } from '@lightspeed/cirrus-table';

const MyApp = () => {
  const {
    itemsSelectedCount,
    toggleAllItems,
    isItemSelected,
    isAllItemsSelected,
    isPartiallySelected,
    toggleItem,
  } = BatchSelect.useBatchSelect(data, {
    idKey: 'id',
    initialSelectedItems: [],
  });

  return (
    <Table>
      <Thead>
        <BatchSelect.HeaderTr
          itemsSelectedCount={itemsSelectedCount}
          selectedItemsText={`${itemsSelectedCount} selected item${
            itemsSelectedCount > 1 ? 's' : ''
          }`}
          checkboxProps={{
            checked: isAllItemsSelected,
            indeterminate: isPartiallySelected,
            onChange: toggleAllItems,
          }}
        >
          <Th>Name</Th>
          <Th>Updated at</Th>
          <Th>Visible</Th>
        </BatchSelect.HeaderTr>
      </Thead>
      <TBody>
        {data.map(item => (
          <BatchSelect.Tr
            key={item.id}
            selected={isItemSelected(item.id)}
            checkboxProps={{
              checked: isItemSelected(item.id),
              onChange: () => {
                toggleItem(item.id);
              },
            }}
          >
            <Td>{item.name}</Td>
            <Td width="150px">{item.updatedAt}</Td>
            <Td width="150px">{item.isVisible}</Td>
          </BatchSelect.Tr>
        ))}
      </TBody>
    </Table>
  );
};
BatchSelect.useBatchSelect

The userBatchSelect hook is used to track what items have been selected.

useBatchSelect accepts a configuration object

const {} = BatchSelect.useBatchSelect(data, {
  idKey: 'id', // optional
  selectedItems: [], // optional
});

| Key | Is Required? | Description | | ------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------ | | data | Required | useBatchSelect will use that data to appropriately track what items are selected or not. useBatchSelect will NOT mutate the data | | idKey | Optional | Change the tracking identifier. By default, useBatchSelect will only keep track of the id key within the data object. | | selectedItems | Optional | Preselect items by forwarding an array of id (or whatever unique indentifier). By default, this field is an empty array. |

useBatchSelect returns the following variables:

| Name | Description | | ------------------- | ------------------------------------------------------------------------------------------------------ | | selectedItems | Get the list of all item IDs that are currently selected | | itemsSelectedCount | Get a numeric count of the selectedItems | | isAllItemsSelected | Return a boolean value of whether or not the selectedItems is empty or has all items contained within | | isPartiallySelected | return a boolean value of whether or not there is at least 1 item selected, but not all items selected |

useBatchSelect returns the following functions

| Name | Params | Description | | -------------- | ------ | -------------------------------------------------------------------- | | isItemSelected | itemID | Checks whether or not an item is selected | | toggleItem | itemID | Automatically add or remove an item from the selectedItems list. | | toggleAllItems | - | Automatically add or remove ALL items from the selectedItems list. | | selectItem | itemID | Add an item to the selectedItems list. | | deselectItem | itemID | Remove an item from the selectedItems list. | | selectAll | - | Add all items to the SelectedItems list. | | deselectAll | - | Remove all items from the SelectedItems list. |

<BatchSelect.HeaderTr>

An augmented header table row <Tr> that handles adding the initial checkbox column and swapping out the table header row to use an action group when items are selected. This component is a wrapper on top of <BatchSelect.CheckboxWell> and handles the logic of replacing table headers with a <BatchSelect.CheckboxWell> when an item is selected.

| Prop | Type | Description | | -------------------- | --------------------- | ------------------------------------------------------------------------------------------- | | itemsSelectedCount | number | Quantity of items selected. | | selectedItemsText | ReactNode | The text or element to appear right beside the checkbox when at least one item is selected. | | innerGroup | ReactNode | Slot to render elements to be attached to the right of the checkbox addon | | outerGroup | ReactNode | Slot to render elements outside of the checkbox addon group. | | checkboxProps | HTMLCheckboxElement | Same properties as a regular cirrus Checkbox | | children | ReactNode | Typically, we put the table header (<Th> or <th>) elements here |

<BatchSelect.Checkbox>

A specially styled cirrus checkbox for the table. Features a slightly larger hit box.

<BatchSelect.CheckboxWell>

A special checkbox that is wrapped in a container and can have an attached button to it.

| Prop | Type | Description | | ------------------- | ----------- | ------------------------------------------------------------------------------------------- | | selectedItemsText | ReactNode | The text or element to appear right beside the checkbox when at least one item is selected. | | innerGroup | ReactNode | Slot to render elements to be attached to the right of the checkbox addon | | outerGroup | ReactNode | Slot to render elements outside of the checkbox addon group. | | checked | boolean | - | | indeterminate | boolean | - | | onChange | boolean | Event handler attached on the Checkbox | | children | ReactNode | Typically, we put the table header (<Th> or <th>) elements here |

<BatchSelect.Tr>

An augmented table row <Tr> that injects a checkbox in the first <Td />. Use this component when you do not want to bother with adjusting padding and margins to match specs.

| Prop | Type | Description | | --------------- | --------------------- | -------------------------------------------- | | checkboxProps | HTMLCheckboxElement | Same properties as a regular cirrus Checkbox | | ...restProps | Tr | Same properties as the Tr component |

<BatchSelect.Dropdown>

A custom dropdown component for the table.

| Prop | Type | Description | | ---------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | title | string | The text content of the dropdown button | | children | ReactNode | What will be rendered within the dropdown menu when the dropdown button is clicked. BatchSelect. Dropdown can also take a child function. Destructuring it will give back a toggleOpen function to programatically close the menu. |

example

<BatchSelect.Dropdown title="Action">
  <BatchSelect.DropdownList>
    <li>An element</li>
    <li>Another element</li>
  </BatchSelect.DropdownList>
</BatchSelect.Dropdown>

// If we need access to toggleOpen function...
<BatchSelect.Dropdown title="Action">
  {({ toggleOpen }) => (
    <BatchSelect.DropdownList>
    <li>An element</li>
    <li>
      <button onClick={toggleOpen}>Close dropdown</button>
    </li>
  </BatchSelect.DropdownList>
  )}
</BatchSelect.Dropdown>
<BatchSelect.DropdownList>

A prestyled <ul> element to be used within the dropdown.

example:

<BatchSelect.DropdownList>
  <li>An element</li>
  <li>Another element</li>
</BatchSelect.DropdownList>
<BatchSelect.BulkButton>

A prestyled cirrus <Button> element to be used within a BatchSelect.HeaderTr or BatchSelect.CheckboxWell inner group.

The Draggable feature

Draggable enables to drag and drop rows to for the purpose of sorthing them.

The draggable feature is a collection of pre-bound HOC elements that uses the react-sortable-hoc library.

<Draggable.Table>

A Table that uses the SortableContainer HOC and pre-binds certain props for convenience sake.

It takes care of setting column sizes on drag, adding a helper class and styling the rows.

The <Draggable.Table> takes the exact same props as a regular <Table>, as well as all the props provided by SortableContainer react-sortable-hoc.

In general, you will only need to your own sorting callback on the onSortEnd prop.

The <Draggable.Table> will automatically enable the useDragHandle prop, meaning it will be required to add a drag handle to your rows. You may of course always set the useDragHandle prop to false.

example

import { Tbody, Td, Draggable } from '@lightspeed/cirrus-table';

const MyApp = () => {
  return (
    <Draggable.Table
      onSortEnd={(({oldIndex, newIndex, collection, isKeySorting})) => {
        console.log('Do your sorting here');
      }}
    >
      <Tbody>
        {/* Add whatever elements */}
      </Tbody>
    </Draggable.Table>
  );
};
<Draggable.Tr> & <Draggable.DragHandle />

<Draggable.Tr> is a <Tr /> that uses the SortableElement HOC. Enables the row to be moved.

<Draggable.DragHandle /> is basically a pre-styled Icon with the SortableHandle HOC applied.

For further details, please consult the react-sortable-hoc library.

Important note: You need to add the index prop on <Draggable.Tr> for proper tracking of row position. You will also need to include the <Draggable.DragHandle /> inside the row, or else you will not be able to move the row. Should you wish to be able to drag the row no matter the cursor location, you may set useDragHandle on the <Draggable.Tbody> to false.

import { Flex } from '@lightspeed/cirrus/core';
import { Table, Draggable, Td } from '@lightspeed/cirrus-table';

const MyApp = () => {
  return (
    <Draggable.Table>
      <Tbody>
        {data.map((item, index) => (
            {/* Notice the presence of the `index` prop. This is important to add! */}
            <Draggable.Tr key={item.id} index={index}>
              <Td>
                {/* Use the Draggable.DragHandle. Or else the row cannot be dragged. */}
                <Draggable.DragHandle>
                  {item.name}
                </Draggable.DragHandle>
              </Td>
              <Td textAlign="right">{item.price}</Td>
            </Draggable.Tr>
          ))}
      </Tbody>
    </Draggable.Table>
  );
};