import{j as e}from"./jsx-runtime-CnH95YSl.js";import{useMDXComponents as r}from"./index-BeeV6X6A.js";import"./index-_dyfSX8u.js";import{M as s,T as l,S as d,D as c,C as a}from"./index-DLgQDw3r.js";import{D as o,a as h,A as p,E as m,C as u,F as f,b as x}from"./DataTable.stories-tcZyd507.js";import"./index-NdkWRN8K.js";import"./_commonjsHelpers-gnU0ypJ3.js";import"./preview-D06dtFvI.js";import"./iframe-Cf-Lpz6Y.js";import"./DocsRenderer-CFRXHY34-CCeAz_jE.js";import"./client-ByW5HbEz.js";import"./index-DieBXP3Z.js";import"./index-BJTM6NaI.js";import"./index-B5xazMy1.js";import"./index-CXQShRbs.js";import"./index-DrFu-skq.js";import"./index-BJMTVygn.js";import"./OdysseyStorybookThemeDecorator-BuDiOG2V.js";import"./OdysseyThemeProvider-Bh0Bu-2o.js";import"./OdysseyProvider-qIn9QVYS.js";import"./personData-CRkmqebZ.js";import"./Status-BlOUycBm.js";import"./MuiPropsContext-DhRylJZk.js";import"./Chip-CXnMieIl.js";import"./createSvgIcon-ClUWwDzL.js";import"./useIsFocusVisible-DH0qxT5e.js";import"./ButtonBase-BNqa2TMD.js";import"./assertThisInitialized-B9jnkVVz.js";import"./inheritsLoose-CJ6Ie9dp.js";import"./TransitionGroupContext-DAL84N7p.js";import"./Box-1mvP3NLW.js";import"./Box-BcMTQ_R2.js";import"./createBox-Dxawkfow.js";import"./Button-BEA5U6Tg.js";import"./BaseButton-DYZHKnV3.js";import"./Tooltip-CsVWtVfL.js";import"./Tooltip-Cq2rQGbD.js";import"./Grow-C8kUeGCY.js";import"./utils-kUZVaD1e.js";import"./getReactElementRef-DsIevm5t.js";import"./resolveComponentProps-DXQ8X87i.js";import"./isHostComponent-DVu5iVWx.js";import"./useControlled-NQulfz4l.js";import"./Popper-BARIxJrI.js";import"./popper-BVOCD5jc.js";import"./ownerDocument-DW-IO8s5.js";import"./Portal-C6D59xAE.js";import"./Button-BzIwUmSM.js";import"./Typography-Cz6D417Y.js";import"./Typography-ClQ35Rr-.js";import"./ArrowRight-ChWYjNny.js";import"./DataTable-XayRBHyP.js";import"./index.esm-DTxqsiYY.js";import"./createChainedFunction-BO_9K8Jh.js";import"./debounce-Be36O1Ab.js";import"./ListItem-C0ExFtXb.js";import"./utils-iop7lDec.js";import"./useFormControl-BMISTZuX.js";import"./FormLabel-CiGre9wK.js";import"./List-CmjR1pNu.js";import"./ownerWindow-HkKU3E4x.js";import"./Stack-B7OGvu7C.js";import"./createStyled-D6bTcpHC.js";import"./useThemeProps-DwvbKxez.js";import"./Paper-D-_O-EjU.js";import"./CircularProgress-HbIdZLBB.js";import"./DialogContent-Cwn-I-C_.js";import"./Fade-dUgBN8rJ.js";import"./Modal-CSDyCVCf.js";import"./getScrollbarSize-Bqq2hMjQ.js";import"./dialogActionsClasses-ZEPlxVw-.js";import"./DialogTitle-C-K7jEio.js";import"./Menu-K9lpVvDG.js";import"./MenuList-BMOesnfs.js";import"./colorManipulator-DKifQsuo.js";import"./IconButton-5qShmnSr.js";import"./Radio-B4gVvwps.js";import"./SwitchBase-CefEM0OA.js";import"./Checkbox-vZwuXtzm.js";import"./useMobilePicker-DZhX9dEQ.js";import"./Select-DZTigpTO.js";import"./ArrowDropDown-DdemyKZU.js";import"./InputBase-DeB4_faH.js";import"./FormHelperText-CsNAE1E3.js";import"./useThemeProps-BPvYx-mf.js";import"./InputAdornment-CdR3XT6f.js";import"./visuallyHidden-Dan1xhjv.js";import"./MenuItem-vhp8G-Nb.js";import"./Collapse-DfdoVIdP.js";import"./AlertTitle-q6ff_Zkl.js";import"./useSlot-CvpE2t6D.js";import"./Close-OXBt1nIe.js";import"./Skeleton-BPjIT6NG.js";import"./Divider-Ln3VaO81.js";import"./Autocomplete-CxtGbb8j.js";import"./ListSubheader-CQJAAOsd.js";import"./tableSortLabelClasses-CkKrbp1R.js";import"./FormControlLabel-0BBemR80.js";import"./DateTimePicker-B7a9bgL6.js";import"./Tabs-CQz87GHd.js";import"./DatePicker-BwDkz3WT.js";import"./MenuButton-B3T7c15t.js";import"./BaseMenuButton-BIietjUB.js";import"./useUniqueId-Bsgqe1tm.js";import"./createUniqueId-ByTaVY63.js";import"./MenuContext-DKMyPMNY.js";import"./More-DLQ2RjWn.js";import"./Callout-FZxPpigF.js";import"./Link-BDoLypER.js";import"./Link-DNIf0luC.js";import"./ExternalLink-D0l1c5Cz.js";import"./EmptyState-CpBEzmap.js";import"./DataFilters-BnT_U3-o.js";import"./Autocomplete-Cpi_kUVA.js";import"./useAutocomplete-BRetTkpF.js";import"./index.esm-CBOWgn41.js";import"./Field-DH3L8v09.js";import"./ScreenReaderText-CebALBsG.js";import"./FieldHint-B3Jif_Up.js";import"./inputUtils-Dbi8XkA6.js";import"./Checkbox-DPv3Q9UW.js";import"./Hint-DoJneNg9.js";import"./CheckboxGroup-Be66QML5.js";import"./FormGroup-HFkGZ983.js";import"./Radio-BdNnpooK.js";import"./RadioGroup-BYJZ378_.js";import"./RadioGroup-CtUWSbQc.js";import"./SearchField-BdnOrhVM.js";import"./Search-C5TVrLyE.js";import"./Tag-DwH0t814.js";import"./TagList-BZGEhGXn.js";import"./TextField-BhK0y2Zt.js";import"./Filter-DsDJ7si-.js";import"./ChevronRight-C12ToI7Y.js";import"./Pagination-CB1wBW8Q.js";import"./MenuItem-CmSG6PNu.js";import"./List-UlX1tusJ.js";import"./Show-BnmQFsN6.js";import"./useScrollIndication-mYI-g6xa.js";function i(n){const t={a:"a",code:"code",del:"del",em:"em",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...r(),...n.components};return e.jsxs(e.Fragment,{children:[e.jsx(s,{of:o}),`
`,e.jsx(l,{of:o}),`
`,e.jsx(d,{of:o}),`
`,e.jsx(c,{of:o}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"<DataTable>"}),` is intended to be simple to set up, but flexible and extensible enough that you can make it do
whatever you need.`]}),`
`,e.jsxs(t.p,{children:["It's built on top of ",e.jsx(t.a,{href:"https://www.material-react-table.com/",rel:"nofollow",children:"Material-React-Table v2"}),`, so reading those docs might
be helpful in understanding how `,e.jsx(t.code,{children:"<DataTable>"}),` works under-the-hood. DataTable offers additional functionality on top of MRT,
and also restricts certain MRT behaviors to match the desired behavior and appearance of an Odyssey table.`]}),`
`,e.jsx(t.p,{children:`You can build anything from a simple list of local data to a sortable, filterable, searchable, reorderable view of data
pulled live from an API.`}),`
`,e.jsx(t.p,{children:`DataTable is "bring-your-own functionality." It offers the UI and local functionality you need, with hooks for you to provide
your own data handling. This means that the table can render a robust filtering and searching UI out-of-the-box, and you can provide
a function that retrieves the relevant data based on the user's query.`}),`
`,e.jsx(t.h2,{id:"getting-started",children:"Getting started"}),`
`,e.jsxs(t.p,{children:["A simple ",e.jsx(t.code,{children:"<DataTable>"})," only needs two props: ",e.jsx(t.code,{children:"columns"})," and ",e.jsx(t.code,{children:"getData"}),":"]}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`<DataTable columns={columns} getData={getData} />
`})}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"columns"})," is an array of ",e.jsx(t.code,{children:"DataTableColumn<DataTableRowData>"})," objects that define the structure of the table."]}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"getData"})," is a function that accepts a set of query params and returns an array of objects that match the ",e.jsx(t.code,{children:"columns"})," shape."]}),`
`,e.jsx(t.h3,{id:"a-simple-example-planet-explorer",children:"A simple example: Planet Explorer"}),`
`,e.jsxs(t.p,{children:["Let's create a simple table that displays information about the ",e.jsx(t.del,{children:"9 planets"})," 8 planets plus Pluto."]}),`
`,e.jsxs(t.p,{children:["First, we'll define a ",e.jsx(t.code,{children:"Planet"})," type, to hold ourselves accountable to the shape of data we want to be working with:"]}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`export type Planet = {
  id: number;
  name: string;
  distance: number;
  visit: "flyby" | "orbit" | "landing";
};
`})}),`
`,e.jsx(t.p,{children:"Next, we'll define the table columns:"}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`export const columns: DataTableColumn<DataTableRowData>[] = [
  {
    accessorKey: "id",
    header: "number",
  },
  {
    accessorKey: "name",
    header: "Name",
  },
  {
    accessorKey: "distance",
    header: "Distance from Sun (AU)",
  },
  ...
];
`})}),`
`,e.jsxs(t.p,{children:["Those first three columns are pretty simple and only need an ",e.jsx(t.code,{children:"accessorKey"}),` (functionally, the unique id of the column)
and a `,e.jsx(t.code,{children:"header"})," (the title displayed to the end user). The other two columns include additional info, such as ",e.jsx(t.code,{children:"filterVariant"}),`
(which defines what kind of control is shown when filtering the column; a text input, radio buttons, etc), `,e.jsx(t.code,{children:"filterOptions"}),`
(the options available in a radio- or checkbox-type filter), and `,e.jsx(t.code,{children:"Cell"}),` (which allows you to define a custom table cell to
display the column data).`]}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"DataTableColumn"})," matches ",e.jsx(t.code,{children:"MRT_TableColumn"}),", so for full information, check the ",e.jsx(t.a,{href:"https://www.material-react-table.com/docs/api/column-options",rel:"nofollow",children:"Column Options"})," docs from Material-React-Table."]}),`
`,e.jsxs(t.p,{children:["(Note that not every feature of Material-React-Table is available in ",e.jsx(t.code,{children:"DataTable"}),", so things like custom edit states won't work.)"]}),`
`,e.jsx(t.p,{children:"Finally, we'll define the planet data itself:"}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`export const data: Planet[] = [
  {
    id: 1,
    name: "Mercury",
    distance: 0.4,
    visit: "landing",
  },
  {
    id: 2,
    name: "Venus",
    distance: 0.7,
    visit: "landing",
  },
  ...
];
`})}),`
`,e.jsx(t.p,{children:"Now, in our component file, we'll put it all together:"}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`import {
  columns as planetColumns,
  data as planetData
} from "./planetData";

...

const getData = () => {
  return planetData;
};

<DataTable
  columns={planetColumns}
  getData={getData}
/>
`})}),`
`,e.jsx(t.h3,{id:"making-it-real",children:"Making it real"}),`
`,e.jsx(t.p,{children:"The example is slightly simplified. Here's a live example of this same table:"}),`
`,e.jsx(a,{of:h}),`
`,e.jsx(t.p,{children:"And here's how we get there:"}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`const ParentComponent = () => {
  // It's best-practice to save the incoming data in a state so we
  // can manipulate it locally if needed. This isn't strictly necessary
  // for this example, but if we started playing with the row order, we'd need this.
  const [data, setData] = useState<Planet[]>(planetData);

  // Typically, you'll take the query params sent via getData and use them to filter the
  // data being sent from the API. For this example, I've created a \`filterData\` function
  // that lives outside the component, and then I'm passing the data and the params into that
  // and returning the response.
  // The full filterData function is explained later in the docs.
  const getData = useCallback(
    ({
      search,
      filters,
      sort,
      page = 1,
      resultsPerPage = 20,
    }: DataTableGetDataType) => {
      return filterData({ data, search, filters, sort, page, resultsPerPage });
    },
    [data],
  );

  // Callback that fires when the user selects or unselects a row.
  // It passes through the full rowSelection state, so you can count
  // the selected rows or perform actions on them.
  const onChangeRowSelection = useCallback(
    (rowSelection: DataTableRowSelectionState) => {
      if (Object.keys(rowSelection).length > 0) {
        console.log(\`\${Object.keys(rowSelection).length} selected\`);
      }
    },
    [],
  );

  return (
    <DataTable
      columns={planetColumns}
      getData={getData}
      onChangeRowSelection={onChangeRowSelection}
      // These are true by default, but adding them
      // here to be extra-clear
      hasChangeableDensity
      hasColumnResizing
      hasFilters
      hasRowSelection
      hasSearch
      hasSorting
      // These are true by default, but
      // disabled for this simple example
      hasPagination={false}
      hasColumnVisibility={false}
      hasRowReordering={false}
    />
  );
};
`})}),`
`,e.jsx(t.h3,{id:"filtering-data",children:"Filtering data"}),`
`,e.jsxs(t.p,{children:["In the above example, the incoming data is stored via ",e.jsx(t.code,{children:"useState"}),", and the ",e.jsx(t.code,{children:"getData"}),` callback passes that
data and the query params to a separate `,e.jsx(t.code,{children:"filterData"})," function that lives outside the component."]}),`
`,e.jsx(t.p,{children:"This might feel obtuse, but it's necessary for building robust and scalable DataTables. Here's why:"}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"getData"})," is purely a GET function. It retrieves data, but doesn't mutate it. ",e.jsxs(t.em,{children:["Whatever is returned by ",e.jsx(t.code,{children:"getData"}),`
is treated as final data, which the table will not modify.`]})]}),`
`,e.jsxs(t.p,{children:[`If you need to mutate the data at all, you need to store it separately. The most common way to mutate table data is through
the `,e.jsx(t.code,{children:"onReorderRows"}),` callback, which handles drag-and-drop and other row-reordering operations. So: if you need to reorder rows,
you need to store data in state.`]}),`
`,e.jsxs(t.p,{children:["This is what the ",e.jsx(t.code,{children:"filterData"})," function looks like in this example. ",e.jsx(t.em,{children:`Yours will probably look different; this is just here
as a demonstration of the sort of functionality it encapsulates.`})]}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`const filterData = ({
  data,
  ...args
}: {
  data: Planet[];
} & DataTableGetDataType) => {
  let filteredData = data;
  const { search, filters, sort, page = 1, resultsPerPage = 20 } = args;

  // Implement text-based query filtering
  if (search) {
    filteredData = filteredData.filter((row) =>
      Object.values(row).some((value) =>
        value.toString().toLowerCase().includes(search.toLowerCase()),
      ),
    );
  }

  // Implement column-specific filtering
  if (filters) {
    filteredData = filteredData.filter((row) => {
      return filters.every(({ id, value }) => {
        // If filter value is null or undefined, skip this filter
        if (value === null || value === undefined) {
          return true;
        }

        // If filter value is array, search for each array value
        if (Array.isArray(value)) {
          return value.some((arrayValue) => {
            return row[id as keyof Planet]
              ?.toString()
              .toLowerCase()
              .includes(arrayValue.toString().toLowerCase());
          });
        }

        // General filtering for other columns
        return row[id as keyof Planet]
          ?.toString()
          .toLowerCase()
          .includes(value.toString().toLowerCase());
      });
    });
  }

  // Implement sorting
  if (sort && sort.length > 0) {
    filteredData.sort((a, b) => {
      for (const { id, desc } of sort) {
        const aValue = a[id as keyof Planet];
        const bValue = b[id as keyof Planet];

        if (aValue < bValue) return desc ? 1 : -1;
        if (aValue > bValue) return desc ? -1 : 1;
      }

      return 0;
    });
  }

  // Implement pagination
  const startRow = (page - 1) * resultsPerPage;
  const endRow = startRow + resultsPerPage;
  filteredData = filteredData.slice(startRow, endRow);

  return filteredData;
};
`})}),`
`,e.jsx(t.h2,{id:"a-fully-featured-example",children:"A fully-featured example"}),`
`,e.jsx(t.p,{children:`Here's a table that hits a (simulated) API and includes filtering, sorting, drag-and-drop reordering,
pagination, and more:`}),`
`,e.jsx(a,{of:p}),`
`,e.jsx(t.h3,{id:"row-reordering",children:"Row reordering"}),`
`,e.jsxs(t.p,{children:["To enable row reordering, the ",e.jsx(t.code,{children:"onReorderRows"})," callback must be defined. Similar to ",e.jsx(t.code,{children:"getData"}),`, in this example
the component itself has an `,e.jsx(t.code,{children:"onReorderRows"})," handler:"]}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`const onReorderRows = useCallback(
  ({ ...props }: DataTableOnReorderRowsType) => {
    const reorderedData = reorderData({ data, ...props });
    setData(reorderedData as Planet[]);
  },
  [data],
);
`})}),`
`,e.jsxs(t.p,{children:["And the ",e.jsx(t.code,{children:"reorderData"})," function it calls out to:"]}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`const reorderData = ({
  data,
  ...args
}: {
  data: (Planet | Person)[];
} & DataTableOnReorderRowsType) => {
  const updatedData = data;
  const { rowId, newRowIndex } = args;
  const rowIndex = updatedData.findIndex((row) => row.id === rowId);

  if (rowIndex !== -1) {
    // Remove the row from its current position
    const [removedRow] = updatedData.splice(rowIndex, 1);

    // Insert the row at the new index
    updatedData.splice(newRowIndex, 0, removedRow);
  }

  return updatedData;
};
`})}),`
`,e.jsx(t.p,{children:`In a real-world scenario, the table would handle the visual portion of the reordering locally and send
the revised order to the API in the background to save.`}),`
`,e.jsx(t.h1,{id:"a-deep-dive-into-specific-features",children:"A deep dive into specific features"}),`
`,e.jsx(t.p,{children:"Some particular features warrant more explanation."}),`
`,e.jsx(t.h2,{id:"pagination",children:"Pagination"}),`
`,e.jsx(t.p,{children:`DataTable comes with standard pagination controls, allowing the user to set how many rows are visible per page, and
allowing them to navigate forward and back through the pages.`}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"paginationType"})," is set to ",e.jsx(t.code,{children:"paged"})," by default. You can change it to ",e.jsx(t.code,{children:"loadMore"}),`, in which case the only pagination control
will be a "Show more" button that loads more rows when pressed. This shouldn't be used in new tables, but is provided as a
convenience to teams migrating from ARC who are already using that functionality.`]}),`
`,e.jsxs(t.p,{children:["If ",e.jsx(t.code,{children:"totalRows"}),` is provided, the pagination will disable the "next" button when the last page has been reached. Otherwise,
the Next button will always be active.`]}),`
`,e.jsxs(t.p,{children:["Providing ",e.jsx(t.code,{children:"totalRows"})," leads to a much better end-user experience, but due to API limitations, that data might not always be available."]}),`
`,e.jsx(t.h2,{id:"empty-states--loading-states",children:"Empty states & loading states"}),`
`,e.jsxs(t.p,{children:["The DataTable will handle its own loading state, toggling it on or off as it hits the ",e.jsx(t.code,{children:"getData"})," callback."]}),`
`,e.jsx(t.p,{children:`There's a default "no results" state, which shows when the end user passes a query that produces no response. (For example, if
the user filters the table for the name "asdfadsfadsfasdfdsfd" and that name doesn't exist in the data, the "no response" state
will be shown.)`}),`
`,e.jsxs(t.p,{children:['You can provide a custom "no response" state using the custom ',e.jsx(t.code,{children:"<EmptyState>"})," component:"]}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`noResultsPlaceholder={<EmptyState
  heading="Whoops, there's nothing here!"
  text="You should try searching or filtering for something else."
/>}
`})}),`
`,e.jsx(t.p,{children:`If the table data is completely empty — calculated based on whether there's no data present even when the search and filtering params
are in their default state — the placeholder state will be shown. However, you can provide a custom empty state, which is useful
for providing a first-run experience for the DataTable:`}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`emptyPlaceholder={
  <EmptyState
    heading="Start by adding data assets"
    text="All relevant data will be displayed and can be searched and filtered"
    PrimaryCallToActionComponent={<Button variant="primary" label="Primary" />}
    SecondaryCallToActionComponent={<Button variant="secondary" label="Secondary" />}
  />
}
`})}),`
`,e.jsx(a,{of:m}),`
`,e.jsx(t.h2,{id:"row-reordering-1",children:"Row reordering"}),`
`,e.jsx(t.p,{children:`Rows can be reordered via drag-and-drop. The table also includes keyboard support for reordering — if the user
presses the spacebar while focused on a row, the table enters "reorder mode" and the row can be moved up and down
via arrow keys. When the user is satisfied with its position, they can "lock it in" by hitting Space or Enter again.`}),`
`,e.jsx(t.p,{children:`For accessibility reasons, if drag-and-drop reordering is enabled, each row will have an action menu on the right side that
includes items for moving the row to the top, bottom, up one, or down one. This cannot be disabled if row reordering is active.`}),`
`,e.jsxs(t.p,{children:['"Move to bottom" is only provided if you provide the ',e.jsx(t.code,{children:"totalRows"}),` to the table, since otherwise the table doesn't know the index
of the bottom row.`]}),`
`,e.jsx(t.h2,{id:"table-settings-density--column-visibility",children:"Table settings (density & column visibility)"}),`
`,e.jsx(t.p,{children:`DataTable can provide controls that allow the end user to change which columns are visible, as well as the density of each row. Note
that, even if the density settings are disabled, you can change the initial table density without exposing that control to the end user.
(For example, if you wanted to make a table with extra breathing room, or a table that's particularly compact).`}),`
`,e.jsx(t.h2,{id:"scroll-indication",children:"Scroll indication"}),`
`,e.jsx(t.p,{children:`If the table content is wider than the available space, a subtle shadow will be displayed in whichever direction the
table can be scrolled. This happens automatically, adjusts when the table container is resized, and adapts to the current
scroll position of the content.`}),`
`,e.jsx(t.h2,{id:"row-actions--bulk-actions",children:"Row actions & bulk actions"}),`
`,e.jsx(t.p,{children:`Action buttons and menu items can be added to each row. If rows are selectable, you can also add bulk actions to the top of the table,
which will be applied to all selected rows. (For example, the bulk actions menu starts out disabled, but if the user selects 3 rows,
the actions menu will be enabled and any actions performed would be applied to all 3 selected rows.)`}),`
`,e.jsx(t.h2,{id:"additional-action-buttons-and-menu-items",children:"Additional action buttons and menu items"}),`
`,e.jsxs(t.p,{children:["Using ",e.jsx(t.code,{children:"additionalActionButton"})," and ",e.jsx(t.code,{children:"additionalActionMenuItems"}),", you can provide additional actions that sit at the top of the ",e.jsx(t.code,{children:"DataView"}),`. This is
perfect for things like an "Add row" button or a menu of actions that affect the entire table or list.`]}),`
`,e.jsx(t.h2,{id:"row-details",children:"Row details"}),`
`,e.jsxs(t.p,{children:["Rows can optionally expand down to reveal additional content, defined via the ",e.jsx(t.code,{children:"renderDetailPanel"}),` prop, which expects a function with two
optional args (`,e.jsx(t.code,{children:"row"})," and ",e.jsx(t.code,{children:"table"}),"). By using the ",e.jsx(t.code,{children:"row"}),` arg, you can add logic that conditionally returns either a ReactNode or undefined; by this
mechanism, you can choose to display details for some rows and not others.`]}),`
`,e.jsx(t.h2,{id:"custom-filters",children:"Custom filters"}),`
`,e.jsx(a,{of:u}),`
`,e.jsxs(t.p,{children:["Within ",e.jsx(t.code,{children:"<DataTable>"}),", you can now pass a custom ",e.jsx(t.code,{children:"filters"})," prop. ",e.jsx(t.em,{children:"This will override the default filters, which are based off the table columns"}),"."]}),`
`,e.jsxs(t.p,{children:["The ",e.jsx(t.code,{children:"filters"})," variable should be an array, which can contain any combination of:"]}),`
`,e.jsxs(t.ol,{children:[`
`,e.jsx(t.li,{children:"A table column (the full column def)"}),`
`,e.jsxs(t.li,{children:["A string that matches the ",e.jsx(t.code,{children:"accessorKey"})," of a table column"]}),`
`,e.jsx(t.li,{children:"A custom filter."}),`
`]}),`
`,e.jsx(t.p,{children:"Using this schema, you can pass in the existing set of table columns plus your own filters. You can also use this mechanism to change the order that the filters are displayed."}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`const filters = [
  ...columns,
  {
    id: "",
    label: "",
    render: (updateFilters: UpdateFiltersCallback) => {},
  },
];
`})}),`
`,e.jsx(t.p,{children:"This is the shape of a custom filter:"}),`
`,e.jsx(t.pre,{children:e.jsx(t.code,{className:"language-tsx",children:`export type DataFilter = {
  /**
   * A unique ID for the filter, typically the same id
   * as the column it'll be applied to.
   */
  id: string;
  /**
   * The human-friendly name of the filter.
   */
  label: string;
  /**
   * The type of filter, which determines which filtering control
   * is shown.
   */
  variant?: MRT_ColumnDef<MRT_RowData>["filterVariant"];
  /**
   * The current value of the filter. Typically a string, but
   * filters that allow for multiple selections (such as multi-select)
   * can accept an array.
   */
  value?: DataFilterValue;
  /**
   * If the filter control has preset options (such as a select or multi-select),
   * these are the options provided.
   */
  options?: Array<{ label: string; value: string }>;
  /**
   * A callback which renders a custom filter control
   */
  render?: (updateFilters: UpdateFilters) => ReactNode;
};
`})}),`
`,e.jsxs(t.p,{children:["The ",e.jsx(t.code,{children:"id"})," is the string representing the filter (it'll be passed through to your filtering function, so if your filter id is ",e.jsx(t.code,{children:"foo"}),", within your filtering function you'll be able to target ",e.jsx(t.code,{children:'filter.id === "foo"'})," and then retrieve the value with ",e.jsx(t.code,{children:"filter.value"}),"."]}),`
`,e.jsxs(t.p,{children:["The ",e.jsx(t.code,{children:"label"})," is the human-readable name of the filter."]}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"value"})," is the current value"]}),`
`,e.jsxs(t.p,{children:[e.jsx(t.code,{children:"render"})," is a function that accepts the callback for changing the filters and returns a ReactNode with the custom filter control."]}),`
`,e.jsx(t.p,{children:"You can add a custom control to a default filter:"}),`
`,e.jsx(a,{of:f}),`
`,e.jsx(t.p,{children:"You can use an out-of-the-box filter variant with a custom filter:"}),`
`,e.jsx(a,{of:x}),`
`,e.jsx(t.h1,{id:"gotchas",children:"Gotchas"}),`
`,e.jsxs(t.p,{children:[`It is very, very important that you memoize your callbacks! Performance slows to a crawl if you don't.
For the best performance, keep your `,e.jsx(t.code,{children:"getData"})," and ",e.jsx(t.code,{children:"onChangeRowSelection"}),` functions outside of the component
and then call them from within, passing the table data in at the same time.`]}),`
`,e.jsx(t.h1,{id:"upgrading-from-labs-datatable-to-datatable",children:"Upgrading from Labs DataTable to DataTable"}),`
`,e.jsx(t.p,{children:"We've made some API changes between the previous version (in Odyssey Labs) and this stable version."}),`
`,e.jsx(t.p,{children:"Be aware of the following:"}),`
`,e.jsxs(t.ul,{children:[`
`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"fetchDataFn"})," is now ",e.jsx(t.code,{children:"getData"})]}),`
`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"onRowSelectionChange"})," is now ",e.jsx(t.code,{children:"onChangeRowSelection"})]}),`
`,e.jsxs(t.li,{children:[e.jsx(t.code,{children:"reorderDataFn"})," is now ",e.jsx(t.code,{children:"onReorderRows"})]}),`
`,e.jsxs(t.li,{children:["Within ",e.jsx(t.code,{children:"reorderDataFn"}),", the param ",e.jsx(t.code,{children:"newIndex"})," is now ",e.jsx(t.code,{children:"newRowIndex"})]}),`
`]})]})}function zt(n={}){const{wrapper:t}={...r(),...n.components};return t?e.jsx(t,{...n,children:e.jsx(i,{...n})}):i(n)}export{zt as default};
