@planningcenter/tapestry 4.3.0-rc.0 → 4.3.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DataTable/DataTable.d.ts +3 -1
- package/dist/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/components/DataTable/DataTable.js +15 -6
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/DataTableColumn.d.ts +8 -1
- package/dist/components/DataTable/DataTableColumn.d.ts.map +1 -1
- package/dist/components/DataTable/useRowPressBoundary.d.ts +23 -0
- package/dist/components/DataTable/useRowPressBoundary.d.ts.map +1 -0
- package/dist/components/DataTable/useRowPressBoundary.js +106 -0
- package/dist/components/DataTable/useRowPressBoundary.js.map +1 -0
- package/dist/components/internal/pagination/Pagination.d.ts +7 -1
- package/dist/components/internal/pagination/Pagination.d.ts.map +1 -1
- package/dist/components/internal/pagination/Pagination.js +2 -2
- package/dist/components/internal/pagination/Pagination.js.map +1 -1
- package/dist/reactRender.css +164 -164
- package/dist/reactRender.css.map +1 -1
- package/dist/reactRenderLegacy.css +164 -164
- package/dist/reactRenderLegacy.css.map +1 -1
- package/package.json +2 -2
|
@@ -105,7 +105,9 @@ export interface DataTableProps {
|
|
|
105
105
|
* `[singular, plural]` tuple is provided, the noun also supplies the table's
|
|
106
106
|
* `aria-label` in its plural form (e.g. `"items"` or `"people"`) unless an
|
|
107
107
|
* `aria-label` is passed directly, which always takes precedence; `true`
|
|
108
|
-
* never provides a label.
|
|
108
|
+
* never provides a label. The same plural noun also names the pagination
|
|
109
|
+
* landmark (e.g. `"people table pagination"`), which otherwise falls back to
|
|
110
|
+
* `"Pagination"`.
|
|
109
111
|
*/
|
|
110
112
|
resultNoun?: ResultNoun;
|
|
111
113
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAKpB,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,2BAA2B,CAAA;AAGhF,OAAO,KAAK,EAAE,EACZ,KAAK,SAAS,EAKf,MAAM,OAAO,CAAA;AACd,OAAO,EAWL,KAAK,UAAU,IAAI,cAAc,EAClC,MAAM,6BAA6B,CAAA;AAEpC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGxD,OAAO,EAGL,KAAK,UAAU,EAEhB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,KAAK,SAAS,EAAc,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.tsx"],"names":[],"mappings":"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"}
|
|
@@ -4,13 +4,14 @@ import { Pagination } from '../internal/pagination/Pagination.js';
|
|
|
4
4
|
import Icon from '../../utilities/Icon.js';
|
|
5
5
|
import { useId } from '../../utilities/useId.js';
|
|
6
6
|
import classNames from 'classnames';
|
|
7
|
-
import React__default, { useMemo, useState,
|
|
7
|
+
import React__default, { useRef, useMemo, useState, useLayoutEffect } from 'react';
|
|
8
8
|
import { Table, TableHeader, Column, Checkbox, TableBody, Row, Cell } from 'react-aria-components/Table';
|
|
9
9
|
import { prepareColumn } from './DataTableColumnTypes.js';
|
|
10
10
|
import { getRowKey } from './DataTableRow.js';
|
|
11
11
|
import { hasResultsCount, resolveResultNounLabel, ResultsCount } from './ResultsCount.js';
|
|
12
12
|
import { RowActions } from './RowActions.js';
|
|
13
13
|
import { TableActions } from './TableActions.js';
|
|
14
|
+
import { useRowPressBoundary } from './useRowPressBoundary.js';
|
|
14
15
|
|
|
15
16
|
const DEFAULT_ERROR_STATE = "Something went wrong.";
|
|
16
17
|
/**
|
|
@@ -34,6 +35,10 @@ const DataTable = ({ className, columns, currentPage = 1, data, disabledKeys, em
|
|
|
34
35
|
const combinedClassName = classNames("tds-data-table-grid", className);
|
|
35
36
|
const sortDescriptor = useSortDescriptor(sortBy);
|
|
36
37
|
const { hasScrollContainer, wrapperRef } = useStickyHeader(stickyHeader, scrollContainerRef, scrollContainerSelector);
|
|
38
|
+
const scrollRef = useRef(null);
|
|
39
|
+
// A `Button` or `Link` in a cell keeps its presses to itself, so activating
|
|
40
|
+
// one doesn't also press the row it's in.
|
|
41
|
+
const cellBoundaryProps = useRowPressBoundary(scrollRef, rowsAreInteractive);
|
|
37
42
|
// React Aria only invokes `renderEmptyState` when the collection is empty, so
|
|
38
43
|
// the loading spinner and error message only take over the body while `data`
|
|
39
44
|
// is empty; once rows exist they always render.
|
|
@@ -91,7 +96,11 @@ const DataTable = ({ className, columns, currentPage = 1, data, disabledKeys, em
|
|
|
91
96
|
// A caller-supplied `aria-label` always wins; otherwise the results noun
|
|
92
97
|
// provides the table's accessible name so a label is present whenever a noun
|
|
93
98
|
// is given. Array nouns are transformed to their plural form.
|
|
94
|
-
const
|
|
99
|
+
const resultNounLabel = resolveResultNounLabel(resultNoun);
|
|
100
|
+
const ariaLabel = restProps["aria-label"] || resultNounLabel;
|
|
101
|
+
const paginationLabel = resultNounLabel
|
|
102
|
+
? `${resultNounLabel} table pagination`
|
|
103
|
+
: undefined;
|
|
95
104
|
const hasActions = (tableActions?.length ?? 0) > 0;
|
|
96
105
|
const showHeader = Boolean(resultNoun || hasActions);
|
|
97
106
|
const hasRowActions = (rowActions?.length ?? 0) > 0;
|
|
@@ -109,7 +118,7 @@ const DataTable = ({ className, columns, currentPage = 1, data, disabledKeys, em
|
|
|
109
118
|
totalCount: resultCount ?? data.length }),
|
|
110
119
|
hasActions && (React__default.createElement(TableActions, { actions: tableActions, resultNoun: resultNoun, selectedKeys: selectedKeys })))),
|
|
111
120
|
React__default.createElement("div", { ref: wrapperRef, className: "tds-data-table-scroll-wrapper" },
|
|
112
|
-
React__default.createElement("div", { className: "tds-data-table-scroll" },
|
|
121
|
+
React__default.createElement("div", { ref: scrollRef, className: "tds-data-table-scroll" },
|
|
113
122
|
React__default.createElement(Table, { ...restProps, ...selectableProps, ...(ariaLabel ? { "aria-label": ariaLabel } : {}), ...(describedBy ? { "aria-describedby": describedBy } : {}), ...{ id: tableId }, className: combinedClassName,
|
|
114
123
|
// Pinned rather than exposed as a prop: `disabledKeys` only ever
|
|
115
124
|
// turns off selection here, leaving the row clickable and
|
|
@@ -137,15 +146,15 @@ const DataTable = ({ className, columns, currentPage = 1, data, disabledKeys, em
|
|
|
137
146
|
}) },
|
|
138
147
|
selectable && (React__default.createElement(Cell, { className: "tds-data-table-cell tds-data-table-cell--selectable" },
|
|
139
148
|
React__default.createElement(Checkbox, { slot: "selection", className: "tds-data-table-selectable-checkbox" }))),
|
|
140
|
-
preparedColumns.map((prepared) => (React__default.createElement(Cell, { key: prepared.column.name, "data-pii": prepared.column.pii || undefined, className: classNames("tds-data-table-cell", {
|
|
149
|
+
preparedColumns.map((prepared) => (React__default.createElement(Cell, { key: prepared.column.name, ...cellBoundaryProps, "data-pii": prepared.column.pii || undefined, className: classNames("tds-data-table-cell", {
|
|
141
150
|
[`tds-data-table-cell--align-${prepared.align}`]: prepared.align !== "start",
|
|
142
151
|
"tds-data-table-cell--numeric": prepared.isNumeric,
|
|
143
152
|
}) }, prepared.renderCell(row)))),
|
|
144
|
-
hasRowActions && (React__default.createElement(Cell, { className: "tds-data-table-cell tds-data-table-cell--actions" },
|
|
153
|
+
hasRowActions && (React__default.createElement(Cell, { ...cellBoundaryProps, className: "tds-data-table-cell tds-data-table-cell--actions" },
|
|
145
154
|
React__default.createElement(RowActions, { actions: rowActions, row: row, rowKey: rowKey })))));
|
|
146
155
|
}))))),
|
|
147
156
|
showPagination && (React__default.createElement("div", { className: "tds-data-table-frame-footer" },
|
|
148
|
-
React__default.createElement(Pagination, { currentPage: currentPage, onPageChange: onPageChange, totalPages: totalPages }))))));
|
|
157
|
+
React__default.createElement(Pagination, { "aria-label": paginationLabel, currentPage: currentPage, onPageChange: onPageChange, totalPages: totalPages }))))));
|
|
149
158
|
};
|
|
150
159
|
DataTable.displayName = "DataTable";
|
|
151
160
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.js","sources":["../../../src/components/DataTable/DataTable.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { LoadingSpinner } from \"@components/internal\"\nimport { Pagination } from \"@components/internal/pagination\"\nimport Icon from \"@utilities/Icon\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, {\n type ReactNode,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport {\n Cell,\n Checkbox,\n Column,\n type Key,\n Row,\n type Selection,\n type SortDescriptor,\n Table,\n TableBody,\n TableHeader,\n type TableProps as AriaTableProps,\n} from \"react-aria-components/Table\"\n\nimport type { DataTableColumn } from \"./DataTableColumn\"\nimport { prepareColumn, type PreparedColumn } from \"./DataTableColumnTypes\"\nimport { getRowKey } from \"./DataTableRow\"\nimport {\n hasResultsCount,\n resolveResultNounLabel,\n type ResultNoun,\n ResultsCount,\n} from \"./ResultsCount\"\nimport { type RowAction, RowActions } from \"./RowActions\"\nimport { type TableAction, TableActions } from \"./TableActions\"\n\nexport type { ResultNoun, RowAction, TableAction }\n\nexport type Sort = { column: string; direction: \"asc\" | \"desc\" }\n\nexport type DataTableLoadingState = \"error\" | \"idle\" | \"loading\"\n\nexport interface DataTableProps {\n /**\n * Columns define what data is displayed and how. Pass a stable reference\n * (e.g. a module constant or memoized value); columns are prepared per array\n * identity, so an inline array rebuilds each column's formatter every render.\n */\n columns: DataTableColumn[]\n /**\n * The 1-indexed current page. Only used when `totalPages` is set, and\n * defaults to `1`.\n */\n currentPage?: number\n /** The array of rows to display. */\n data: unknown[]\n /**\n * Row keys that can't be selected. Keys are the values returned by `getRowId`\n * (or `row.id`, or the row's index) — the same keys used by `selectedKeys`.\n * Only selection is disabled: the row's checkbox renders disabled and \"select\n * all\" skips it, while the row itself stays clickable, navigable, and\n * focusable. Has no effect unless the table is `selectable`.\n */\n disabledKeys?: (number | string)[]\n /** Rendered in place of the table body when there is no data. */\n emptyState?: ReactNode\n /** Rendered in place of the table body when `loadingState` is `\"error\"`. */\n errorState?: ReactNode\n /** Returns a stable identity for each row. Defaults to `row.id`. */\n getRowId?: (row: unknown) => number | string\n /**\n * Returns a URL to navigate to when the row is clicked. Rows with a link\n * render as navigable elements (clickable, keyboard-focusable, and\n * openable in a new tab). Works alongside `onRowClick` and `selectable`.\n */\n getRowLink?: (row: unknown) => string\n /**\n * An `id` for the table element. When omitted, a stable generated id is used\n * so the results count can be linked to the table via `aria-describedby`.\n */\n id?: string\n /**\n * Async loading state for the table body.\n * - `\"loading\"`: While `data` is empty, replaces the empty state with a\n * centered spinner.\n * - `\"error\"`: While `data` is empty, replaces the empty state with\n * `errorState` (or a default error message).\n * - `\"idle\"` (default): Normal rendering.\n */\n loadingState?: DataTableLoadingState\n /**\n * Called with the 1-indexed page the user navigated to. The table doesn't\n * page `data` itself — pass the rows for the new page back in through `data`\n * (and update `currentPage`) in response.\n */\n onPageChange?: (page: number) => void\n /**\n * Called with the row when it is clicked. Rows with a click handler render\n * as interactive elements (clickable and keyboard-focusable). When\n * `getRowLink` is also set, both run and the row navigates.\n */\n onRowClick?: (row: unknown) => void\n /**\n * Called when the set of selected rows changes. Always receives a plain\n * array of row keys — never React Aria's `\"all\"` sentinel, which is\n * resolved to the concrete keys of the loaded rows.\n */\n onSelectedChange?: (keys: (number | string)[]) => void\n /** Callback invoked when the sort state changes. */\n onSortChange?: (sort: Sort) => void\n /**\n * Overrides the number shown by the `resultNoun` count, which otherwise\n * uses the length of `data`. Use this when the table renders only part of\n * the result set — a paginated or virtualized table — so the count reflects\n * the whole set. Has no effect unless `resultNoun` is set.\n */\n resultCount?: number\n /**\n * Displays the number of results (the length of `data`, or `resultCount`\n * when supplied) above the table, followed by a noun that matches the count.\n * Pass a string to use it as the singular noun and append `\"s\"` for the\n * plural (e.g. `\"result\"` → `\"results\"`), or a `[singular, plural]` tuple to\n * supply an irregular plural explicitly (e.g. `[\"person\", \"people\"]`). Pass\n * `true` to use `\"result\"`.\n * When `false` or omitted, no count is rendered. The count is formatted with\n * `Intl.NumberFormat` and the singular form is used only when the count is\n * exactly `1`. When the table is `selectable` and rows are selected, the\n * count instead reflects the selection as `\"{selected} of {total}\"`, e.g.\n * `\"2 of 100\"`, with a visually-hidden suffix naming the noun so assistive\n * tech reads the unambiguous `\"2 of 100 people selected\"`.\n * The count is linked to the table with `aria-describedby` so\n * screen readers announce it as a description of the table. When a string or\n * `[singular, plural]` tuple is provided, the noun also supplies the table's\n * `aria-label` in its plural form (e.g. `\"items\"` or `\"people\"`) unless an\n * `aria-label` is passed directly, which always takes precedence; `true`\n * never provides a label.\n */\n resultNoun?: ResultNoun\n /**\n * Displays a sticky column to the right that holds row-scoped actions.\n * Renders as a dropdown with 2+ actions or a single button with one. Each\n * action's `onAction` or `getHref` receives the row.\n */\n rowActions?: RowAction[]\n /** Ref to the scroll container the sticky header should track. Takes priority over `scrollContainerSelector`. Only used when `stickyHeader` is true. */\n scrollContainerRef?: React.RefObject<HTMLElement>\n /** CSS selector for the scroll container the sticky header should track. Only used when `stickyHeader` is true. Defaults to \".content-wrap\" */\n scrollContainerSelector?: string\n /**\n * Enables row selection via checkboxes, including a \"select all\" checkbox in\n * the header. Without a row action (`onRowClick` or `getRowLink`), pressing\n * anywhere in a row toggles the row selection.\n */\n selectable?: boolean\n /** The selected row keys. Keys are the values returned by `getRowId` (or `row.id`, or the row's index). */\n selectedKeys?: (number | string)[]\n /** The current sort state for the table. */\n sortBy?: Sort\n /** Enables a sticky header that tracks an outer scroll container. Progressive enhancement: Relies on `animation-timeline: scroll()`, which isn't supported in all browsers (e.g. Firefox) — the header scrolls with the table body instead of sticking in those cases. */\n stickyHeader?: boolean\n /**\n * Table actions rendered as an `IconButton` group directly after the results\n * count, above the table. Each entry becomes an icon button whose `callback`\n * receives the ids of the currently selected rows. Unlike the original RFC,\n * these are not gated on `selectable` — actions such as print or export can\n * operate without a row selection.\n */\n tableActions?: TableAction[]\n /**\n * The total number of pages in the result set. Setting it renders the page\n * controls below the table; leaving it unset renders no pagination at all.\n * A single page has nothing to navigate to, so the controls only render once\n * there are two or more pages.\n *\n * The table displays whatever rows it is given — paging is the caller's job.\n * `data` should hold only the current page's rows, `resultCount` the size of\n * the whole result set, and `onPageChange` should load the next page.\n */\n totalPages?: number\n}\n\nconst DEFAULT_ERROR_STATE = \"Something went wrong.\"\n\ntype AriaTablePropsToOmit = \"children\" | \"slot\"\n\ntype AriaTablePropsToInclude = never\n\nexport type DataTableElementProps = CombineAriaPropsWithCustomProps<\n AriaTableProps,\n DataTableProps,\n AriaTablePropsToOmit,\n AriaTablePropsToInclude\n>\n\n/**\n * A table for displaying tabular data. Built on React Aria's `Table`.\n *\n * Each column declares a `type` that controls how its cell values are\n * formatted: `string`, `number`, `currency`, `date`, `datetime`, `boolean`,\n * `enum`, and `custom`. A column's `render` function always takes precedence\n * over the built-in type formatting.\n *\n * Setting `totalPages` renders page controls below the table; the table itself\n * never slices `data`, so `onPageChange` is where the caller loads the page.\n *\n * Filtering, presets, and other RFC features are not yet implemented.\n *\n * @component\n */\nexport const DataTable = ({\n className,\n columns,\n currentPage = 1,\n data,\n disabledKeys,\n emptyState,\n errorState,\n getRowId,\n getRowLink,\n id,\n loadingState = \"idle\",\n resultCount,\n resultNoun,\n scrollContainerRef,\n scrollContainerSelector = \".content-wrap\",\n rowActions,\n selectable,\n selectedKeys: controlledSelectedKeys,\n stickyHeader,\n sortBy,\n tableActions,\n totalPages,\n onPageChange,\n onRowClick,\n onSelectedChange,\n onSortChange,\n ...restProps\n}: DataTableElementProps) => {\n const hasRowPressAction = Boolean(onRowClick || getRowLink)\n const rowsAreInteractive = hasRowPressAction || Boolean(selectable)\n const combinedClassName = classNames(\"tds-data-table-grid\", className)\n const sortDescriptor = useSortDescriptor(sortBy)\n const { hasScrollContainer, wrapperRef } = useStickyHeader(\n stickyHeader,\n scrollContainerRef,\n scrollContainerSelector\n )\n\n // React Aria only invokes `renderEmptyState` when the collection is empty, so\n // the loading spinner and error message only take over the body while `data`\n // is empty; once rows exist they always render.\n const emptyStateContent = getEmptyStateContent({\n emptyState,\n errorState,\n loadingState,\n })\n const renderEmptyState = emptyStateContent\n ? () => emptyStateContent\n : undefined\n\n // Keyed on column names rather than the `columns` array identity so a fresh\n // `columns` literal each render doesn't rebuild every formatter. `columns` is\n // intentionally omitted from the deps.\n const columnKey = columns.map((c) => `${c.name}/${c.type}`).join(\"|\")\n const preparedColumns = useMemo<PreparedColumn[]>(\n () => columns.map(prepareColumn),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [columnKey]\n )\n\n // Selection is controlled when `selectedKeys` is provided; otherwise it's\n // tracked internally so the results count and table actions still reflect it.\n const isControlled = controlledSelectedKeys !== undefined\n const [internalSelectedKeys, setInternalSelectedKeys] = useState<\n (number | string)[]\n >([])\n const selectedKeys = isControlled\n ? controlledSelectedKeys\n : internalSelectedKeys\n\n // React Aria treats a row's own action as primary only while the selection is\n // empty: with checkbox selection, once any row is selected the table is in\n // selection mode and pressing anywhere in a row toggles its selection instead\n // of firing the action. Rows without an action always select on press. The\n // row's hover state previews the checkbox's hover state whenever a press would\n // select, so this has to track the selection rather than the props alone.\n const rowPressSelects =\n Boolean(selectable) && (!hasRowPressAction || selectedKeys.length > 0)\n\n const selectableProps = useSelectableProps({\n data,\n disabledKeys,\n getRowId,\n onSelectedChange: (keys) => {\n if (!isControlled) setInternalSelectedKeys(keys)\n onSelectedChange?.(keys)\n },\n selectable,\n selectedKeys,\n })\n\n // Associate the visible results count with the table so screen readers\n // announce it as a description of the table. `Table` doesn't support a real\n // `<caption>` (its children go through a collection builder), so we link the\n // count via `aria-describedby`, merging with any caller-supplied value.\n const stableId = useId()\n const tableId = id || `tds-data-table-${stableId}`\n const resultsCountId = `${tableId}-results-count`\n const describedBy = hasResultsCount(resultNoun)\n ? [restProps[\"aria-describedby\"], resultsCountId].filter(Boolean).join(\" \")\n : restProps[\"aria-describedby\"]\n\n // A caller-supplied `aria-label` always wins; otherwise the results noun\n // provides the table's accessible name so a label is present whenever a noun\n // is given. Array nouns are transformed to their plural form.\n const ariaLabel =\n restProps[\"aria-label\"] || resolveResultNounLabel(resultNoun)\n\n const hasActions = (tableActions?.length ?? 0) > 0\n const showHeader = Boolean(resultNoun || hasActions)\n const hasRowActions = (rowActions?.length ?? 0) > 0\n // A lone page has nothing to navigate to, so the controls stay out of the\n // frame entirely rather than rendering a single inert page marker.\n const showPagination = totalPages !== undefined && totalPages > 1\n\n return (\n <div\n className={classNames(\"tds-data-table\", {\n \"tds-data-table--sticky-header\": hasScrollContainer,\n })}\n >\n <div className=\"tds-data-table-frame\">\n {showHeader && (\n <div className=\"tds-data-table-frame-header\">\n <ResultsCount\n id={resultsCountId}\n resultNoun={resultNoun}\n selectable={selectable}\n selectedCount={selectedKeys.length}\n // An explicit `resultCount` covers the whole result set, which a\n // paginated table's `data` doesn't.\n totalCount={resultCount ?? data.length}\n />\n {hasActions && (\n <TableActions\n actions={tableActions!} // Safe to assert non-null here because of `hasActions`\n resultNoun={resultNoun}\n selectedKeys={selectedKeys}\n />\n )}\n </div>\n )}\n <div ref={wrapperRef} className=\"tds-data-table-scroll-wrapper\">\n <div className=\"tds-data-table-scroll\">\n <Table\n {...restProps}\n {...selectableProps}\n {...(ariaLabel ? { \"aria-label\": ariaLabel } : {})}\n {...(describedBy ? { \"aria-describedby\": describedBy } : {})}\n // RAC's `Table` forwards `id` to the underlying table element at\n // runtime (via `filterDOMProps({ global: true })`) but omits `id`\n // from its prop types, so spread it through a cast.\n {...({ id: tableId } as Partial<AriaTableProps>)}\n className={combinedClassName}\n // Pinned rather than exposed as a prop: `disabledKeys` only ever\n // turns off selection here, leaving the row clickable and\n // focusable. React Aria defaults this to \"all\", which would also\n // disable `onRowClick`/`getRowLink` and drop the row out of the\n // focus order, so it has to be set explicitly.\n disabledBehavior=\"selection\"\n disabledKeys={disabledKeys}\n sortDescriptor={sortDescriptor}\n onSortChange={(sort) => {\n onSortChange?.(serializeSort(sort))\n }}\n >\n <TableHeader className=\"tds-data-table-header\">\n {/*\n Rendered as a sibling before the `preparedColumns.map` below\n (not folded into it) so the map's `index` still starts at 0\n for the first *data* column — that's what keeps\n `isRowHeader={index === 0}` pointing at the first data\n column instead of this selection column.\n */}\n {selectable && (\n <Column className=\"tds-data-table-column tds-data-table-column--selectable\">\n <Checkbox\n slot=\"selection\"\n className=\"tds-data-table-selectable-checkbox\"\n />\n </Column>\n )}\n {preparedColumns.map(({ align, column }, index) => (\n <Column\n key={column.name}\n id={column.name}\n isRowHeader={index === 0}\n className={classNames(\"tds-data-table-column\", {\n [`tds-data-table-column--align-${align}`]:\n align !== \"start\",\n })}\n allowsSorting={column.sortable}\n >\n {column.hideLabel ? (\n <span className=\"tds-data-table-column-label--hidden\">\n {column.headerLabel}\n </span>\n ) : (\n column.headerLabel\n )}\n {column.sortable && (\n <Icon\n className=\"tds-data-table-column-icon tds-data-table-column-icon--sort\"\n symbol=\"general#up-caret\"\n aria-hidden={true}\n />\n )}\n </Column>\n ))}\n {hasRowActions && (\n <Column className=\"tds-data-table-column tds-data-table-column--actions\">\n <span className=\"tds-data-table-column-label--hidden\">\n Actions\n </span>\n </Column>\n )}\n </TableHeader>\n <TableBody\n className=\"tds-data-table-body\"\n renderEmptyState={renderEmptyState}\n >\n {data.map((row, rowIndex) => {\n const rowKey = getRowKey(row, rowIndex, getRowId)\n return (\n <Row\n key={rowKey}\n id={rowKey}\n href={getRowLink?.(row)}\n onAction={onRowClick ? () => onRowClick(row) : undefined}\n className={classNames(\"tds-data-table-row\", {\n \"tds-data-table-row--interactive\": rowsAreInteractive,\n \"tds-data-table-row--press-selects\": rowPressSelects,\n })}\n >\n {selectable && (\n <Cell className=\"tds-data-table-cell tds-data-table-cell--selectable\">\n <Checkbox\n slot=\"selection\"\n className=\"tds-data-table-selectable-checkbox\"\n />\n </Cell>\n )}\n {preparedColumns.map((prepared) => (\n <Cell\n key={prepared.column.name}\n data-pii={prepared.column.pii || undefined}\n className={classNames(\"tds-data-table-cell\", {\n [`tds-data-table-cell--align-${prepared.align}`]:\n prepared.align !== \"start\",\n \"tds-data-table-cell--numeric\": prepared.isNumeric,\n })}\n >\n {prepared.renderCell(row)}\n </Cell>\n ))}\n {hasRowActions && (\n <Cell className=\"tds-data-table-cell tds-data-table-cell--actions\">\n <RowActions\n actions={rowActions!} // Safe to assert non-null here because of `hasRowActions`\n row={row}\n rowKey={rowKey}\n />\n </Cell>\n )}\n </Row>\n )\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n {showPagination && (\n <div className=\"tds-data-table-frame-footer\">\n <Pagination\n currentPage={currentPage}\n onPageChange={onPageChange}\n totalPages={totalPages!}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n\nDataTable.displayName = \"DataTable\"\n\n/**\n * Resolves the content rendered in the table body's empty-state slot based on\n * `loadingState`, falling back to `emptyState`. Returns `null` when nothing\n * should render (idle with no `emptyState`).\n */\nfunction getEmptyStateContent({\n emptyState,\n errorState,\n loadingState,\n}: {\n emptyState: ReactNode\n errorState: ReactNode\n loadingState: DataTableLoadingState\n}): ReactNode {\n if (loadingState === \"loading\") {\n return (\n <div className=\"tds-data-table-loading\" role=\"status\">\n <span className=\"tds-data-table-cell-label--hidden\">Loading</span>\n <span className=\"tds-data-table-loading-spinner\" aria-hidden=\"true\">\n <LoadingSpinner />\n </span>\n </div>\n )\n }\n\n // Error and empty share the same container; they differ only in content.\n const content =\n loadingState === \"error\" ? (errorState ?? DEFAULT_ERROR_STATE) : emptyState\n if (content == null) return null\n\n return <div className=\"tds-data-table-empty\">{content}</div>\n}\n\nfunction useSortDescriptor(\n sortBy: Sort | undefined\n): SortDescriptor | undefined {\n return useMemo(() => {\n if (!sortBy) return undefined\n return deserializeSort(sortBy)\n }, [sortBy])\n}\n\nfunction deserializeSort(sort: Sort): SortDescriptor {\n if (sort.direction === \"desc\")\n return { column: sort.column, direction: \"descending\" }\n return { column: sort.column, direction: \"ascending\" }\n}\n\nfunction serializeSort(sort: SortDescriptor): Sort {\n if (sort.direction === \"descending\")\n return { column: sort.column as string, direction: \"desc\" }\n return { column: sort.column as string, direction: \"asc\" }\n}\n\n/**\n * Resolves the `<Table>` selection props, driving React Aria's `<Table>` off\n * the component's selection state. `onSelectedChange` always receives a plain\n * array of keys: React Aria's `\"all\"` selection sentinel (used for\n * infinite-loading collections, which this component doesn't have) is resolved\n * to the concrete keys of the currently loaded rows, minus any disabled ones —\n * React Aria's own \"select all\" skips disabled rows, so resolving `\"all\"` has to\n * skip them too.\n */\nfunction useSelectableProps({\n data,\n disabledKeys,\n getRowId,\n onSelectedChange,\n selectable,\n selectedKeys,\n}: {\n data: unknown[]\n disabledKeys: (number | string)[] | undefined\n getRowId: ((row: unknown) => number | string) | undefined\n onSelectedChange: (keys: (number | string)[]) => void\n selectable: boolean | undefined\n selectedKeys: (number | string)[]\n}): Pick<\n AriaTableProps,\n \"onSelectionChange\" | \"selectedKeys\" | \"selectionMode\"\n> {\n const selectedKeysSet = useMemo(\n () => new Set<Key>(selectedKeys),\n [selectedKeys]\n )\n const { rowKeys, rowOrder } = useMemo(() => {\n const rowKeys = data.map((row, index) => getRowKey(row, index, getRowId))\n return {\n rowKeys,\n rowOrder: new Map<Key, number>(rowKeys.map((key, index) => [key, index])),\n }\n }, [data, getRowId])\n\n if (!selectable) return { selectionMode: \"none\" }\n\n return {\n onSelectionChange: (keys: Selection) => {\n if (keys === \"all\") {\n const disabled = new Set<Key>(disabledKeys)\n onSelectedChange(rowKeys.filter((key) => !disabled.has(key)))\n return\n }\n // Keys not found in `rowOrder` (e.g. a previously selected row no longer\n // in `data`) sort to the end rather than being dropped.\n onSelectedChange(\n Array.from(keys).sort(\n (a, b) =>\n (rowOrder.get(a) ?? Infinity) - (rowOrder.get(b) ?? Infinity)\n )\n )\n },\n selectedKeys: selectedKeysSet,\n selectionMode: \"multiple\",\n }\n}\n\nfunction useStickyHeader(\n stickyHeader: boolean | undefined,\n scrollContainerRef: React.RefObject<HTMLElement> | undefined,\n scrollContainerSelector: string | undefined\n) {\n const wrapperRef = useRef<HTMLDivElement>(null)\n const [hasScrollContainer, setHasScrollContainer] = useState(false)\n\n useLayoutEffect(() => {\n setHasScrollContainer(false)\n if (!stickyHeader) return\n if (typeof ResizeObserver === \"undefined\") return\n const wrapper = wrapperRef.current\n if (!wrapper) return\n\n const scrollContainer = getScrollContainer(\n scrollContainerRef,\n scrollContainerSelector,\n wrapper\n )\n if (!scrollContainer) return\n\n setHasScrollContainer(true)\n\n let thead: HTMLElement | null = null\n\n const resizeObserver = new ResizeObserver(() => {\n if (!thead) {\n thead = wrapper.querySelector<HTMLElement>(\".tds-data-table-header\")\n if (!thead) return\n scrollContainer.style.setProperty(\n \"scroll-timeline-name\",\n \"--_sticky-header-scroll\"\n )\n }\n\n const { top: wrapperTop, bottom: wrapperBottom } =\n wrapper.getBoundingClientRect()\n const { top: scrollContainerTop } =\n scrollContainer.getBoundingClientRect()\n // Derive headerTop from the untransformed wrapper to avoid reading the\n // scroll-driven translateY that getBoundingClientRect() includes on thead.\n const headerTop = wrapperTop + wrapper.clientTop\n const start = scrollContainer.scrollTop + (headerTop - scrollContainerTop)\n const max = Math.max(0, wrapperBottom - headerTop - thead.offsetHeight)\n wrapper.style.setProperty(\"--_sticky-header-scroll-start\", `${start}px`)\n wrapper.style.setProperty(\"--_sticky-header-scroll-max\", `${max}px`)\n })\n\n resizeObserver.observe(wrapper)\n resizeObserver.observe(scrollContainer)\n\n return () => {\n resizeObserver.disconnect()\n wrapper.style.removeProperty(\"--_sticky-header-scroll-start\")\n wrapper.style.removeProperty(\"--_sticky-header-scroll-max\")\n }\n }, [stickyHeader, scrollContainerRef, scrollContainerSelector])\n\n return { hasScrollContainer, wrapperRef }\n}\n\nfunction getScrollContainer(\n scrollContainerRef: React.RefObject<HTMLElement> | undefined,\n scrollContainerSelector: string | undefined,\n wrapper: HTMLElement\n): HTMLElement | undefined {\n const element =\n scrollContainerRef?.current ??\n getScrollContainerFromSelector(scrollContainerSelector, wrapper)\n if (element instanceof Window) return\n return element\n}\n\nfunction getScrollContainerFromSelector(\n scrollContainerSelector: string | undefined,\n wrapper: HTMLElement\n): HTMLElement | undefined {\n return scrollContainerSelector\n ? (wrapper.parentElement?.closest<HTMLElement>(scrollContainerSelector) ??\n undefined)\n : undefined\n}\n"],"names":["React"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataTable.js","sources":["../../../src/components/DataTable/DataTable.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { LoadingSpinner } from \"@components/internal\"\nimport { Pagination } from \"@components/internal/pagination\"\nimport Icon from \"@utilities/Icon\"\nimport type { CombineAriaPropsWithCustomProps } from \"@utilities/reactAriaProps\"\nimport { useId } from \"@utilities/useId\"\nimport classNames from \"classnames\"\nimport React, {\n type ReactNode,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport {\n Cell,\n Checkbox,\n Column,\n type Key,\n Row,\n type Selection,\n type SortDescriptor,\n Table,\n TableBody,\n TableHeader,\n type TableProps as AriaTableProps,\n} from \"react-aria-components/Table\"\n\nimport type { DataTableColumn } from \"./DataTableColumn\"\nimport { prepareColumn, type PreparedColumn } from \"./DataTableColumnTypes\"\nimport { getRowKey } from \"./DataTableRow\"\nimport {\n hasResultsCount,\n resolveResultNounLabel,\n type ResultNoun,\n ResultsCount,\n} from \"./ResultsCount\"\nimport { type RowAction, RowActions } from \"./RowActions\"\nimport { type TableAction, TableActions } from \"./TableActions\"\nimport { useRowPressBoundary } from \"./useRowPressBoundary\"\n\nexport type { ResultNoun, RowAction, TableAction }\n\nexport type Sort = { column: string; direction: \"asc\" | \"desc\" }\n\nexport type DataTableLoadingState = \"error\" | \"idle\" | \"loading\"\n\nexport interface DataTableProps {\n /**\n * Columns define what data is displayed and how. Pass a stable reference\n * (e.g. a module constant or memoized value); columns are prepared per array\n * identity, so an inline array rebuilds each column's formatter every render.\n */\n columns: DataTableColumn[]\n /**\n * The 1-indexed current page. Only used when `totalPages` is set, and\n * defaults to `1`.\n */\n currentPage?: number\n /** The array of rows to display. */\n data: unknown[]\n /**\n * Row keys that can't be selected. Keys are the values returned by `getRowId`\n * (or `row.id`, or the row's index) — the same keys used by `selectedKeys`.\n * Only selection is disabled: the row's checkbox renders disabled and \"select\n * all\" skips it, while the row itself stays clickable, navigable, and\n * focusable. Has no effect unless the table is `selectable`.\n */\n disabledKeys?: (number | string)[]\n /** Rendered in place of the table body when there is no data. */\n emptyState?: ReactNode\n /** Rendered in place of the table body when `loadingState` is `\"error\"`. */\n errorState?: ReactNode\n /** Returns a stable identity for each row. Defaults to `row.id`. */\n getRowId?: (row: unknown) => number | string\n /**\n * Returns a URL to navigate to when the row is clicked. Rows with a link\n * render as navigable elements (clickable, keyboard-focusable, and\n * openable in a new tab). Works alongside `onRowClick` and `selectable`.\n */\n getRowLink?: (row: unknown) => string\n /**\n * An `id` for the table element. When omitted, a stable generated id is used\n * so the results count can be linked to the table via `aria-describedby`.\n */\n id?: string\n /**\n * Async loading state for the table body.\n * - `\"loading\"`: While `data` is empty, replaces the empty state with a\n * centered spinner.\n * - `\"error\"`: While `data` is empty, replaces the empty state with\n * `errorState` (or a default error message).\n * - `\"idle\"` (default): Normal rendering.\n */\n loadingState?: DataTableLoadingState\n /**\n * Called with the 1-indexed page the user navigated to. The table doesn't\n * page `data` itself — pass the rows for the new page back in through `data`\n * (and update `currentPage`) in response.\n */\n onPageChange?: (page: number) => void\n /**\n * Called with the row when it is clicked. Rows with a click handler render\n * as interactive elements (clickable and keyboard-focusable). When\n * `getRowLink` is also set, both run and the row navigates.\n */\n onRowClick?: (row: unknown) => void\n /**\n * Called when the set of selected rows changes. Always receives a plain\n * array of row keys — never React Aria's `\"all\"` sentinel, which is\n * resolved to the concrete keys of the loaded rows.\n */\n onSelectedChange?: (keys: (number | string)[]) => void\n /** Callback invoked when the sort state changes. */\n onSortChange?: (sort: Sort) => void\n /**\n * Overrides the number shown by the `resultNoun` count, which otherwise\n * uses the length of `data`. Use this when the table renders only part of\n * the result set — a paginated or virtualized table — so the count reflects\n * the whole set. Has no effect unless `resultNoun` is set.\n */\n resultCount?: number\n /**\n * Displays the number of results (the length of `data`, or `resultCount`\n * when supplied) above the table, followed by a noun that matches the count.\n * Pass a string to use it as the singular noun and append `\"s\"` for the\n * plural (e.g. `\"result\"` → `\"results\"`), or a `[singular, plural]` tuple to\n * supply an irregular plural explicitly (e.g. `[\"person\", \"people\"]`). Pass\n * `true` to use `\"result\"`.\n * When `false` or omitted, no count is rendered. The count is formatted with\n * `Intl.NumberFormat` and the singular form is used only when the count is\n * exactly `1`. When the table is `selectable` and rows are selected, the\n * count instead reflects the selection as `\"{selected} of {total}\"`, e.g.\n * `\"2 of 100\"`, with a visually-hidden suffix naming the noun so assistive\n * tech reads the unambiguous `\"2 of 100 people selected\"`.\n * The count is linked to the table with `aria-describedby` so\n * screen readers announce it as a description of the table. When a string or\n * `[singular, plural]` tuple is provided, the noun also supplies the table's\n * `aria-label` in its plural form (e.g. `\"items\"` or `\"people\"`) unless an\n * `aria-label` is passed directly, which always takes precedence; `true`\n * never provides a label. The same plural noun also names the pagination\n * landmark (e.g. `\"people table pagination\"`), which otherwise falls back to\n * `\"Pagination\"`.\n */\n resultNoun?: ResultNoun\n /**\n * Displays a sticky column to the right that holds row-scoped actions.\n * Renders as a dropdown with 2+ actions or a single button with one. Each\n * action's `onAction` or `getHref` receives the row.\n */\n rowActions?: RowAction[]\n /** Ref to the scroll container the sticky header should track. Takes priority over `scrollContainerSelector`. Only used when `stickyHeader` is true. */\n scrollContainerRef?: React.RefObject<HTMLElement>\n /** CSS selector for the scroll container the sticky header should track. Only used when `stickyHeader` is true. Defaults to \".content-wrap\" */\n scrollContainerSelector?: string\n /**\n * Enables row selection via checkboxes, including a \"select all\" checkbox in\n * the header. Without a row action (`onRowClick` or `getRowLink`), pressing\n * anywhere in a row toggles the row selection.\n */\n selectable?: boolean\n /** The selected row keys. Keys are the values returned by `getRowId` (or `row.id`, or the row's index). */\n selectedKeys?: (number | string)[]\n /** The current sort state for the table. */\n sortBy?: Sort\n /** Enables a sticky header that tracks an outer scroll container. Progressive enhancement: Relies on `animation-timeline: scroll()`, which isn't supported in all browsers (e.g. Firefox) — the header scrolls with the table body instead of sticking in those cases. */\n stickyHeader?: boolean\n /**\n * Table actions rendered as an `IconButton` group directly after the results\n * count, above the table. Each entry becomes an icon button whose `callback`\n * receives the ids of the currently selected rows. Unlike the original RFC,\n * these are not gated on `selectable` — actions such as print or export can\n * operate without a row selection.\n */\n tableActions?: TableAction[]\n /**\n * The total number of pages in the result set. Setting it renders the page\n * controls below the table; leaving it unset renders no pagination at all.\n * A single page has nothing to navigate to, so the controls only render once\n * there are two or more pages.\n *\n * The table displays whatever rows it is given — paging is the caller's job.\n * `data` should hold only the current page's rows, `resultCount` the size of\n * the whole result set, and `onPageChange` should load the next page.\n */\n totalPages?: number\n}\n\nconst DEFAULT_ERROR_STATE = \"Something went wrong.\"\n\ntype AriaTablePropsToOmit = \"children\" | \"slot\"\n\ntype AriaTablePropsToInclude = never\n\nexport type DataTableElementProps = CombineAriaPropsWithCustomProps<\n AriaTableProps,\n DataTableProps,\n AriaTablePropsToOmit,\n AriaTablePropsToInclude\n>\n\n/**\n * A table for displaying tabular data. Built on React Aria's `Table`.\n *\n * Each column declares a `type` that controls how its cell values are\n * formatted: `string`, `number`, `currency`, `date`, `datetime`, `boolean`,\n * `enum`, and `custom`. A column's `render` function always takes precedence\n * over the built-in type formatting.\n *\n * Setting `totalPages` renders page controls below the table; the table itself\n * never slices `data`, so `onPageChange` is where the caller loads the page.\n *\n * Filtering, presets, and other RFC features are not yet implemented.\n *\n * @component\n */\nexport const DataTable = ({\n className,\n columns,\n currentPage = 1,\n data,\n disabledKeys,\n emptyState,\n errorState,\n getRowId,\n getRowLink,\n id,\n loadingState = \"idle\",\n resultCount,\n resultNoun,\n scrollContainerRef,\n scrollContainerSelector = \".content-wrap\",\n rowActions,\n selectable,\n selectedKeys: controlledSelectedKeys,\n stickyHeader,\n sortBy,\n tableActions,\n totalPages,\n onPageChange,\n onRowClick,\n onSelectedChange,\n onSortChange,\n ...restProps\n}: DataTableElementProps) => {\n const hasRowPressAction = Boolean(onRowClick || getRowLink)\n const rowsAreInteractive = hasRowPressAction || Boolean(selectable)\n const combinedClassName = classNames(\"tds-data-table-grid\", className)\n const sortDescriptor = useSortDescriptor(sortBy)\n const { hasScrollContainer, wrapperRef } = useStickyHeader(\n stickyHeader,\n scrollContainerRef,\n scrollContainerSelector\n )\n const scrollRef = useRef<HTMLDivElement>(null)\n // A `Button` or `Link` in a cell keeps its presses to itself, so activating\n // one doesn't also press the row it's in.\n const cellBoundaryProps = useRowPressBoundary(scrollRef, rowsAreInteractive)\n\n // React Aria only invokes `renderEmptyState` when the collection is empty, so\n // the loading spinner and error message only take over the body while `data`\n // is empty; once rows exist they always render.\n const emptyStateContent = getEmptyStateContent({\n emptyState,\n errorState,\n loadingState,\n })\n const renderEmptyState = emptyStateContent\n ? () => emptyStateContent\n : undefined\n\n // Keyed on column names rather than the `columns` array identity so a fresh\n // `columns` literal each render doesn't rebuild every formatter. `columns` is\n // intentionally omitted from the deps.\n const columnKey = columns.map((c) => `${c.name}/${c.type}`).join(\"|\")\n const preparedColumns = useMemo<PreparedColumn[]>(\n () => columns.map(prepareColumn),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [columnKey]\n )\n\n // Selection is controlled when `selectedKeys` is provided; otherwise it's\n // tracked internally so the results count and table actions still reflect it.\n const isControlled = controlledSelectedKeys !== undefined\n const [internalSelectedKeys, setInternalSelectedKeys] = useState<\n (number | string)[]\n >([])\n const selectedKeys = isControlled\n ? controlledSelectedKeys\n : internalSelectedKeys\n\n // React Aria treats a row's own action as primary only while the selection is\n // empty: with checkbox selection, once any row is selected the table is in\n // selection mode and pressing anywhere in a row toggles its selection instead\n // of firing the action. Rows without an action always select on press. The\n // row's hover state previews the checkbox's hover state whenever a press would\n // select, so this has to track the selection rather than the props alone.\n const rowPressSelects =\n Boolean(selectable) && (!hasRowPressAction || selectedKeys.length > 0)\n\n const selectableProps = useSelectableProps({\n data,\n disabledKeys,\n getRowId,\n onSelectedChange: (keys) => {\n if (!isControlled) setInternalSelectedKeys(keys)\n onSelectedChange?.(keys)\n },\n selectable,\n selectedKeys,\n })\n\n // Associate the visible results count with the table so screen readers\n // announce it as a description of the table. `Table` doesn't support a real\n // `<caption>` (its children go through a collection builder), so we link the\n // count via `aria-describedby`, merging with any caller-supplied value.\n const stableId = useId()\n const tableId = id || `tds-data-table-${stableId}`\n const resultsCountId = `${tableId}-results-count`\n const describedBy = hasResultsCount(resultNoun)\n ? [restProps[\"aria-describedby\"], resultsCountId].filter(Boolean).join(\" \")\n : restProps[\"aria-describedby\"]\n\n // A caller-supplied `aria-label` always wins; otherwise the results noun\n // provides the table's accessible name so a label is present whenever a noun\n // is given. Array nouns are transformed to their plural form.\n const resultNounLabel = resolveResultNounLabel(resultNoun)\n const ariaLabel = restProps[\"aria-label\"] || resultNounLabel\n const paginationLabel = resultNounLabel\n ? `${resultNounLabel} table pagination`\n : undefined\n\n const hasActions = (tableActions?.length ?? 0) > 0\n const showHeader = Boolean(resultNoun || hasActions)\n const hasRowActions = (rowActions?.length ?? 0) > 0\n // A lone page has nothing to navigate to, so the controls stay out of the\n // frame entirely rather than rendering a single inert page marker.\n const showPagination = totalPages !== undefined && totalPages > 1\n\n return (\n <div\n className={classNames(\"tds-data-table\", {\n \"tds-data-table--sticky-header\": hasScrollContainer,\n })}\n >\n <div className=\"tds-data-table-frame\">\n {showHeader && (\n <div className=\"tds-data-table-frame-header\">\n <ResultsCount\n id={resultsCountId}\n resultNoun={resultNoun}\n selectable={selectable}\n selectedCount={selectedKeys.length}\n // An explicit `resultCount` covers the whole result set, which a\n // paginated table's `data` doesn't.\n totalCount={resultCount ?? data.length}\n />\n {hasActions && (\n <TableActions\n actions={tableActions!} // Safe to assert non-null here because of `hasActions`\n resultNoun={resultNoun}\n selectedKeys={selectedKeys}\n />\n )}\n </div>\n )}\n <div ref={wrapperRef} className=\"tds-data-table-scroll-wrapper\">\n <div ref={scrollRef} className=\"tds-data-table-scroll\">\n <Table\n {...restProps}\n {...selectableProps}\n {...(ariaLabel ? { \"aria-label\": ariaLabel } : {})}\n {...(describedBy ? { \"aria-describedby\": describedBy } : {})}\n // RAC's `Table` forwards `id` to the underlying table element at\n // runtime (via `filterDOMProps({ global: true })`) but omits `id`\n // from its prop types, so spread it through a cast.\n {...({ id: tableId } as Partial<AriaTableProps>)}\n className={combinedClassName}\n // Pinned rather than exposed as a prop: `disabledKeys` only ever\n // turns off selection here, leaving the row clickable and\n // focusable. React Aria defaults this to \"all\", which would also\n // disable `onRowClick`/`getRowLink` and drop the row out of the\n // focus order, so it has to be set explicitly.\n disabledBehavior=\"selection\"\n disabledKeys={disabledKeys}\n sortDescriptor={sortDescriptor}\n onSortChange={(sort) => {\n onSortChange?.(serializeSort(sort))\n }}\n >\n <TableHeader className=\"tds-data-table-header\">\n {/*\n Rendered as a sibling before the `preparedColumns.map` below\n (not folded into it) so the map's `index` still starts at 0\n for the first *data* column — that's what keeps\n `isRowHeader={index === 0}` pointing at the first data\n column instead of this selection column.\n */}\n {selectable && (\n <Column className=\"tds-data-table-column tds-data-table-column--selectable\">\n <Checkbox\n slot=\"selection\"\n className=\"tds-data-table-selectable-checkbox\"\n />\n </Column>\n )}\n {preparedColumns.map(({ align, column }, index) => (\n <Column\n key={column.name}\n id={column.name}\n isRowHeader={index === 0}\n className={classNames(\"tds-data-table-column\", {\n [`tds-data-table-column--align-${align}`]:\n align !== \"start\",\n })}\n allowsSorting={column.sortable}\n >\n {column.hideLabel ? (\n <span className=\"tds-data-table-column-label--hidden\">\n {column.headerLabel}\n </span>\n ) : (\n column.headerLabel\n )}\n {column.sortable && (\n <Icon\n className=\"tds-data-table-column-icon tds-data-table-column-icon--sort\"\n symbol=\"general#up-caret\"\n aria-hidden={true}\n />\n )}\n </Column>\n ))}\n {hasRowActions && (\n <Column className=\"tds-data-table-column tds-data-table-column--actions\">\n <span className=\"tds-data-table-column-label--hidden\">\n Actions\n </span>\n </Column>\n )}\n </TableHeader>\n <TableBody\n className=\"tds-data-table-body\"\n renderEmptyState={renderEmptyState}\n >\n {data.map((row, rowIndex) => {\n const rowKey = getRowKey(row, rowIndex, getRowId)\n return (\n <Row\n key={rowKey}\n id={rowKey}\n href={getRowLink?.(row)}\n onAction={onRowClick ? () => onRowClick(row) : undefined}\n className={classNames(\"tds-data-table-row\", {\n \"tds-data-table-row--interactive\": rowsAreInteractive,\n \"tds-data-table-row--press-selects\": rowPressSelects,\n })}\n >\n {selectable && (\n <Cell className=\"tds-data-table-cell tds-data-table-cell--selectable\">\n <Checkbox\n slot=\"selection\"\n className=\"tds-data-table-selectable-checkbox\"\n />\n </Cell>\n )}\n {preparedColumns.map((prepared) => (\n <Cell\n key={prepared.column.name}\n {...cellBoundaryProps}\n data-pii={prepared.column.pii || undefined}\n className={classNames(\"tds-data-table-cell\", {\n [`tds-data-table-cell--align-${prepared.align}`]:\n prepared.align !== \"start\",\n \"tds-data-table-cell--numeric\": prepared.isNumeric,\n })}\n >\n {prepared.renderCell(row)}\n </Cell>\n ))}\n {hasRowActions && (\n <Cell\n {...cellBoundaryProps}\n className=\"tds-data-table-cell tds-data-table-cell--actions\"\n >\n <RowActions\n actions={rowActions!} // Safe to assert non-null here because of `hasRowActions`\n row={row}\n rowKey={rowKey}\n />\n </Cell>\n )}\n </Row>\n )\n })}\n </TableBody>\n </Table>\n </div>\n </div>\n {showPagination && (\n <div className=\"tds-data-table-frame-footer\">\n <Pagination\n aria-label={paginationLabel}\n currentPage={currentPage}\n onPageChange={onPageChange}\n totalPages={totalPages!}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n\nDataTable.displayName = \"DataTable\"\n\n/**\n * Resolves the content rendered in the table body's empty-state slot based on\n * `loadingState`, falling back to `emptyState`. Returns `null` when nothing\n * should render (idle with no `emptyState`).\n */\nfunction getEmptyStateContent({\n emptyState,\n errorState,\n loadingState,\n}: {\n emptyState: ReactNode\n errorState: ReactNode\n loadingState: DataTableLoadingState\n}): ReactNode {\n if (loadingState === \"loading\") {\n return (\n <div className=\"tds-data-table-loading\" role=\"status\">\n <span className=\"tds-data-table-cell-label--hidden\">Loading</span>\n <span className=\"tds-data-table-loading-spinner\" aria-hidden=\"true\">\n <LoadingSpinner />\n </span>\n </div>\n )\n }\n\n // Error and empty share the same container; they differ only in content.\n const content =\n loadingState === \"error\" ? (errorState ?? DEFAULT_ERROR_STATE) : emptyState\n if (content == null) return null\n\n return <div className=\"tds-data-table-empty\">{content}</div>\n}\n\nfunction useSortDescriptor(\n sortBy: Sort | undefined\n): SortDescriptor | undefined {\n return useMemo(() => {\n if (!sortBy) return undefined\n return deserializeSort(sortBy)\n }, [sortBy])\n}\n\nfunction deserializeSort(sort: Sort): SortDescriptor {\n if (sort.direction === \"desc\")\n return { column: sort.column, direction: \"descending\" }\n return { column: sort.column, direction: \"ascending\" }\n}\n\nfunction serializeSort(sort: SortDescriptor): Sort {\n if (sort.direction === \"descending\")\n return { column: sort.column as string, direction: \"desc\" }\n return { column: sort.column as string, direction: \"asc\" }\n}\n\n/**\n * Resolves the `<Table>` selection props, driving React Aria's `<Table>` off\n * the component's selection state. `onSelectedChange` always receives a plain\n * array of keys: React Aria's `\"all\"` selection sentinel (used for\n * infinite-loading collections, which this component doesn't have) is resolved\n * to the concrete keys of the currently loaded rows, minus any disabled ones —\n * React Aria's own \"select all\" skips disabled rows, so resolving `\"all\"` has to\n * skip them too.\n */\nfunction useSelectableProps({\n data,\n disabledKeys,\n getRowId,\n onSelectedChange,\n selectable,\n selectedKeys,\n}: {\n data: unknown[]\n disabledKeys: (number | string)[] | undefined\n getRowId: ((row: unknown) => number | string) | undefined\n onSelectedChange: (keys: (number | string)[]) => void\n selectable: boolean | undefined\n selectedKeys: (number | string)[]\n}): Pick<\n AriaTableProps,\n \"onSelectionChange\" | \"selectedKeys\" | \"selectionMode\"\n> {\n const selectedKeysSet = useMemo(\n () => new Set<Key>(selectedKeys),\n [selectedKeys]\n )\n const { rowKeys, rowOrder } = useMemo(() => {\n const rowKeys = data.map((row, index) => getRowKey(row, index, getRowId))\n return {\n rowKeys,\n rowOrder: new Map<Key, number>(rowKeys.map((key, index) => [key, index])),\n }\n }, [data, getRowId])\n\n if (!selectable) return { selectionMode: \"none\" }\n\n return {\n onSelectionChange: (keys: Selection) => {\n if (keys === \"all\") {\n const disabled = new Set<Key>(disabledKeys)\n onSelectedChange(rowKeys.filter((key) => !disabled.has(key)))\n return\n }\n // Keys not found in `rowOrder` (e.g. a previously selected row no longer\n // in `data`) sort to the end rather than being dropped.\n onSelectedChange(\n Array.from(keys).sort(\n (a, b) =>\n (rowOrder.get(a) ?? Infinity) - (rowOrder.get(b) ?? Infinity)\n )\n )\n },\n selectedKeys: selectedKeysSet,\n selectionMode: \"multiple\",\n }\n}\n\nfunction useStickyHeader(\n stickyHeader: boolean | undefined,\n scrollContainerRef: React.RefObject<HTMLElement> | undefined,\n scrollContainerSelector: string | undefined\n) {\n const wrapperRef = useRef<HTMLDivElement>(null)\n const [hasScrollContainer, setHasScrollContainer] = useState(false)\n\n useLayoutEffect(() => {\n setHasScrollContainer(false)\n if (!stickyHeader) return\n if (typeof ResizeObserver === \"undefined\") return\n const wrapper = wrapperRef.current\n if (!wrapper) return\n\n const scrollContainer = getScrollContainer(\n scrollContainerRef,\n scrollContainerSelector,\n wrapper\n )\n if (!scrollContainer) return\n\n setHasScrollContainer(true)\n\n let thead: HTMLElement | null = null\n\n const resizeObserver = new ResizeObserver(() => {\n if (!thead) {\n thead = wrapper.querySelector<HTMLElement>(\".tds-data-table-header\")\n if (!thead) return\n scrollContainer.style.setProperty(\n \"scroll-timeline-name\",\n \"--_sticky-header-scroll\"\n )\n }\n\n const { top: wrapperTop, bottom: wrapperBottom } =\n wrapper.getBoundingClientRect()\n const { top: scrollContainerTop } =\n scrollContainer.getBoundingClientRect()\n // Derive headerTop from the untransformed wrapper to avoid reading the\n // scroll-driven translateY that getBoundingClientRect() includes on thead.\n const headerTop = wrapperTop + wrapper.clientTop\n const start = scrollContainer.scrollTop + (headerTop - scrollContainerTop)\n const max = Math.max(0, wrapperBottom - headerTop - thead.offsetHeight)\n wrapper.style.setProperty(\"--_sticky-header-scroll-start\", `${start}px`)\n wrapper.style.setProperty(\"--_sticky-header-scroll-max\", `${max}px`)\n })\n\n resizeObserver.observe(wrapper)\n resizeObserver.observe(scrollContainer)\n\n return () => {\n resizeObserver.disconnect()\n wrapper.style.removeProperty(\"--_sticky-header-scroll-start\")\n wrapper.style.removeProperty(\"--_sticky-header-scroll-max\")\n }\n }, [stickyHeader, scrollContainerRef, scrollContainerSelector])\n\n return { hasScrollContainer, wrapperRef }\n}\n\nfunction getScrollContainer(\n scrollContainerRef: React.RefObject<HTMLElement> | undefined,\n scrollContainerSelector: string | undefined,\n wrapper: HTMLElement\n): HTMLElement | undefined {\n const element =\n scrollContainerRef?.current ??\n getScrollContainerFromSelector(scrollContainerSelector, wrapper)\n if (element instanceof Window) return\n return element\n}\n\nfunction getScrollContainerFromSelector(\n scrollContainerSelector: string | undefined,\n wrapper: HTMLElement\n): HTMLElement | undefined {\n return scrollContainerSelector\n ? (wrapper.parentElement?.closest<HTMLElement>(scrollContainerSelector) ??\n undefined)\n : undefined\n}\n"],"names":["React"],"mappings":"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"}
|
|
@@ -24,7 +24,14 @@ interface BaseColumn {
|
|
|
24
24
|
pii?: boolean;
|
|
25
25
|
/** Enables filtering on this column. See Filtering. */
|
|
26
26
|
queryable?: boolean;
|
|
27
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Custom cell renderer. Defaults to a type-aware format of
|
|
29
|
+
* `row[column.name]`.
|
|
30
|
+
*
|
|
31
|
+
* Controls are safe to render in a row that has an action of its own
|
|
32
|
+
* (`onRowClick`, `getRowLink`, or `selectable`): pressing a button or a link
|
|
33
|
+
* in a cell runs only that control's action, never the row's.
|
|
34
|
+
*/
|
|
28
35
|
render?: (row: unknown) => ReactNode;
|
|
29
36
|
/** Enables the resizing of that column. */
|
|
30
37
|
resizable?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTableColumn.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTableColumn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,mBAAmB,GAC3B,SAAS;AACX;;;GAGG;GACD,UAAU,GACV,QAAQ,GACR,MAAM,GACN,UAAU,GACV,MAAM,GACN,QAAQ,GACR,QAAQ,CAAA;AAEZ,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAA;AAE7D,UAAU,UAAU;IAClB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,oBAAoB,CAAA;IAC5B,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAA;IACnB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB
|
|
1
|
+
{"version":3,"file":"DataTableColumn.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTableColumn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,mBAAmB,GAC3B,SAAS;AACX;;;GAGG;GACD,UAAU,GACV,QAAQ,GACR,MAAM,GACN,UAAU,GACV,MAAM,GACN,QAAQ,GACR,QAAQ,CAAA;AAEZ,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAA;AAE7D,UAAU,UAAU;IAClB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,oBAAoB,CAAA;IAC5B,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAA;IACnB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;OAKG;IACH,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,uDAAuD;IACvD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,SAAS,CAAA;IACpC,2CAA2C;IAC3C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,qCAAqC;AACrC,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,IAAI,EAAE,QAAQ,CAAA;CACf;AAED,qFAAqF;AACrF,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,wEAAwE;IACxE,mBAAmB,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAA;IAC9C,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,QAAQ,CAAA;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,wEAAwE;IACxE,mBAAmB,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAA;IAC9C,IAAI,EAAE,UAAU,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,IAAI,CAAC,qBAAqB,CAAA;IAC9C,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,IAAI,CAAC,qBAAqB,CAAA;IAC9C,IAAI,EAAE,UAAU,CAAA;CACjB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,4CAA4C;AAC5C,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,uDAAuD;IACvD,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,6DAA6D;AAC7D,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,SAAS,CAAA;IACnC,IAAI,EAAE,QAAQ,CAAA;CACf;AAED,MAAM,MAAM,eAAe,GACvB,aAAa,GACb,cAAc,GACd,YAAY,GACZ,UAAU,GACV,cAAc,GACd,UAAU,GACV,YAAY,GACZ,YAAY,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type RefObject, type SyntheticEvent } from "react";
|
|
2
|
+
declare function stopRowPress(event: SyntheticEvent<HTMLTableCellElement>): void;
|
|
3
|
+
/**
|
|
4
|
+
* Keeps button and link clicks inside a cell from triggering the parent row.
|
|
5
|
+
* Returns props to spread on each `Cell`, or `undefined` if the row has no action.
|
|
6
|
+
*
|
|
7
|
+
* We have to handle keyboard events at the table container level because they
|
|
8
|
+
* don't get forwarded to the `<td>`. We use a capture-phase listener to intercept
|
|
9
|
+
* Enter and Space before React's event system sees them. This stops React Aria
|
|
10
|
+
* from running `preventDefault()` on them, ensuring native buttons and links
|
|
11
|
+
* still fire.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useRowPressBoundary(table: RefObject<HTMLElement | null>, enabled: boolean): {
|
|
14
|
+
onClick: typeof stopRowPress;
|
|
15
|
+
onMouseDown: typeof stopRowPress;
|
|
16
|
+
onMouseUp: typeof stopRowPress;
|
|
17
|
+
onPointerDown: typeof stopRowPress;
|
|
18
|
+
onPointerUp: typeof stopRowPress;
|
|
19
|
+
onTouchEnd: typeof stopRowPress;
|
|
20
|
+
onTouchStart: typeof stopRowPress;
|
|
21
|
+
} | undefined;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=useRowPressBoundary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRowPressBoundary.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/useRowPressBoundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAa,MAAM,OAAO,CAAA;AAyDtE,iBAAS,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,oBAAoB,CAAC,QAGhE;AAgBD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACpC,OAAO,EAAE,OAAO;;;;;;;;cAuBjB"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* When a table row is clickable, clicking a Tapestry Button or link inside a cell
|
|
5
|
+
* also triggers the row's action, because non-React Aria elements don't stop event propagation.
|
|
6
|
+
*
|
|
7
|
+
* To stop this behavior, we draw a boundary at the cell: if an event starts on a control, we stop it
|
|
8
|
+
* from bubbling up to the row. We only stop propagation (not the default action),
|
|
9
|
+
* so the native buttons and links still work perfectly.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* The interactive elements the boundary covers. Presses on anything else pass
|
|
13
|
+
* through and trigger the row.
|
|
14
|
+
*
|
|
15
|
+
* Native elements, because the keyboard boundary stops the key press above the
|
|
16
|
+
* cell (see below), which stops it short of the cell's contents too — so a
|
|
17
|
+
* control belongs here only if the browser activates it on its own once nothing
|
|
18
|
+
* calls `preventDefault()`. `<button>` and `<a href>` do. An element made
|
|
19
|
+
* interactive with `role="button"` or `role="link"` and its own key handler
|
|
20
|
+
* doesn't, and counts as ordinary cell content. Cells that need a control should
|
|
21
|
+
* use Tapestry's `Button` or `Link`, a native `<button>` or `<a href>`, or a
|
|
22
|
+
* React Aria component that handles its own presses.
|
|
23
|
+
*/
|
|
24
|
+
const CELL_CONTROL_SELECTOR = "button,a[href]";
|
|
25
|
+
/**
|
|
26
|
+
* Keys React Aria uses to activate a row. We let other keys pass through so
|
|
27
|
+
* keyboard navigation and type-ahead still work.
|
|
28
|
+
*/
|
|
29
|
+
const ROW_ACTIVATION_KEYS = new Set(["Enter", " "]);
|
|
30
|
+
/**
|
|
31
|
+
* Identifies components that already manage their own press events (like a React
|
|
32
|
+
* Aria Dropdown), so we can leave them alone.
|
|
33
|
+
*/
|
|
34
|
+
const SELF_MANAGED_PRESS_SELECTOR = "[data-react-aria-pressable]";
|
|
35
|
+
/**
|
|
36
|
+
* Finds the specific control the user interacted with, as long as it's actually
|
|
37
|
+
* inside the cell. Returns null if the event belongs to the row.
|
|
38
|
+
*/
|
|
39
|
+
function findCellControl(cell, target) {
|
|
40
|
+
if (!(target instanceof Element))
|
|
41
|
+
return null;
|
|
42
|
+
const control = target.closest(CELL_CONTROL_SELECTOR);
|
|
43
|
+
return control && cell.contains(control) ? control : null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Checks if the control (or its wrapper) handles its own press events, stopping
|
|
47
|
+
* the search at the cell boundary.
|
|
48
|
+
*/
|
|
49
|
+
function managesOwnPress(cell, control) {
|
|
50
|
+
const pressable = control.closest(SELF_MANAGED_PRESS_SELECTOR);
|
|
51
|
+
return Boolean(pressable && cell.contains(pressable));
|
|
52
|
+
}
|
|
53
|
+
function stopRowPress(event) {
|
|
54
|
+
if (findCellControl(event.currentTarget, event.target))
|
|
55
|
+
event.stopPropagation();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Standard DOM events that React Aria's `usePress` listens for. We apply these
|
|
59
|
+
* to the `<td>` to stop bubbling. Keyboard events are handled separately below.
|
|
60
|
+
*/
|
|
61
|
+
const CELL_BOUNDARY_PROPS = {
|
|
62
|
+
onClick: stopRowPress,
|
|
63
|
+
onMouseDown: stopRowPress,
|
|
64
|
+
onMouseUp: stopRowPress,
|
|
65
|
+
onPointerDown: stopRowPress,
|
|
66
|
+
onPointerUp: stopRowPress,
|
|
67
|
+
onTouchEnd: stopRowPress,
|
|
68
|
+
onTouchStart: stopRowPress,
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Keeps button and link clicks inside a cell from triggering the parent row.
|
|
72
|
+
* Returns props to spread on each `Cell`, or `undefined` if the row has no action.
|
|
73
|
+
*
|
|
74
|
+
* We have to handle keyboard events at the table container level because they
|
|
75
|
+
* don't get forwarded to the `<td>`. We use a capture-phase listener to intercept
|
|
76
|
+
* Enter and Space before React's event system sees them. This stops React Aria
|
|
77
|
+
* from running `preventDefault()` on them, ensuring native buttons and links
|
|
78
|
+
* still fire.
|
|
79
|
+
*/
|
|
80
|
+
function useRowPressBoundary(table, enabled) {
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
const container = table.current;
|
|
83
|
+
if (!enabled || !container)
|
|
84
|
+
return;
|
|
85
|
+
const stopRowActivationKeys = (event) => {
|
|
86
|
+
if (!ROW_ACTIVATION_KEYS.has(event.key))
|
|
87
|
+
return;
|
|
88
|
+
const target = event.target;
|
|
89
|
+
if (!(target instanceof Element))
|
|
90
|
+
return;
|
|
91
|
+
const cell = target.closest("td");
|
|
92
|
+
if (!cell || !container.contains(cell))
|
|
93
|
+
return;
|
|
94
|
+
const control = findCellControl(cell, target);
|
|
95
|
+
if (!control || managesOwnPress(cell, control))
|
|
96
|
+
return;
|
|
97
|
+
event.stopPropagation();
|
|
98
|
+
};
|
|
99
|
+
container.addEventListener("keydown", stopRowActivationKeys, true);
|
|
100
|
+
return () => container.removeEventListener("keydown", stopRowActivationKeys, true);
|
|
101
|
+
}, [enabled, table]);
|
|
102
|
+
return enabled ? CELL_BOUNDARY_PROPS : undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export { useRowPressBoundary };
|
|
106
|
+
//# sourceMappingURL=useRowPressBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRowPressBoundary.js","sources":["../../../src/components/DataTable/useRowPressBoundary.ts"],"sourcesContent":["import { type RefObject, type SyntheticEvent, useEffect } from \"react\"\n\n/*\n * When a table row is clickable, clicking a Tapestry Button or link inside a cell\n * also triggers the row's action, because non-React Aria elements don't stop event propagation.\n *\n * To stop this behavior, we draw a boundary at the cell: if an event starts on a control, we stop it\n * from bubbling up to the row. We only stop propagation (not the default action),\n * so the native buttons and links still work perfectly.\n */\n\n/**\n * The interactive elements the boundary covers. Presses on anything else pass\n * through and trigger the row.\n *\n * Native elements, because the keyboard boundary stops the key press above the\n * cell (see below), which stops it short of the cell's contents too — so a\n * control belongs here only if the browser activates it on its own once nothing\n * calls `preventDefault()`. `<button>` and `<a href>` do. An element made\n * interactive with `role=\"button\"` or `role=\"link\"` and its own key handler\n * doesn't, and counts as ordinary cell content. Cells that need a control should\n * use Tapestry's `Button` or `Link`, a native `<button>` or `<a href>`, or a\n * React Aria component that handles its own presses.\n */\nconst CELL_CONTROL_SELECTOR = \"button,a[href]\"\n\n/**\n * Keys React Aria uses to activate a row. We let other keys pass through so\n * keyboard navigation and type-ahead still work.\n */\nconst ROW_ACTIVATION_KEYS = new Set([\"Enter\", \" \"])\n\n/**\n * Identifies components that already manage their own press events (like a React\n * Aria Dropdown), so we can leave them alone.\n */\nconst SELF_MANAGED_PRESS_SELECTOR = \"[data-react-aria-pressable]\"\n\n/**\n * Finds the specific control the user interacted with, as long as it's actually\n * inside the cell. Returns null if the event belongs to the row.\n */\nfunction findCellControl(cell: Element, target: EventTarget | null) {\n if (!(target instanceof Element)) return null\n const control = target.closest(CELL_CONTROL_SELECTOR)\n return control && cell.contains(control) ? control : null\n}\n\n/**\n * Checks if the control (or its wrapper) handles its own press events, stopping\n * the search at the cell boundary.\n */\nfunction managesOwnPress(cell: Element, control: Element) {\n const pressable = control.closest(SELF_MANAGED_PRESS_SELECTOR)\n return Boolean(pressable && cell.contains(pressable))\n}\n\nfunction stopRowPress(event: SyntheticEvent<HTMLTableCellElement>) {\n if (findCellControl(event.currentTarget, event.target))\n event.stopPropagation()\n}\n\n/**\n * Standard DOM events that React Aria's `usePress` listens for. We apply these\n * to the `<td>` to stop bubbling. Keyboard events are handled separately below.\n */\nconst CELL_BOUNDARY_PROPS = {\n onClick: stopRowPress,\n onMouseDown: stopRowPress,\n onMouseUp: stopRowPress,\n onPointerDown: stopRowPress,\n onPointerUp: stopRowPress,\n onTouchEnd: stopRowPress,\n onTouchStart: stopRowPress,\n}\n\n/**\n * Keeps button and link clicks inside a cell from triggering the parent row.\n * Returns props to spread on each `Cell`, or `undefined` if the row has no action.\n *\n * We have to handle keyboard events at the table container level because they\n * don't get forwarded to the `<td>`. We use a capture-phase listener to intercept\n * Enter and Space before React's event system sees them. This stops React Aria\n * from running `preventDefault()` on them, ensuring native buttons and links\n * still fire.\n */\nexport function useRowPressBoundary(\n table: RefObject<HTMLElement | null>,\n enabled: boolean\n) {\n useEffect(() => {\n const container = table.current\n if (!enabled || !container) return\n\n const stopRowActivationKeys = (event: KeyboardEvent) => {\n if (!ROW_ACTIVATION_KEYS.has(event.key)) return\n const target = event.target\n if (!(target instanceof Element)) return\n const cell = target.closest(\"td\")\n if (!cell || !container.contains(cell)) return\n const control = findCellControl(cell, target)\n if (!control || managesOwnPress(cell, control)) return\n event.stopPropagation()\n }\n\n container.addEventListener(\"keydown\", stopRowActivationKeys, true)\n return () =>\n container.removeEventListener(\"keydown\", stopRowActivationKeys, true)\n }, [enabled, table])\n\n return enabled ? CELL_BOUNDARY_PROPS : undefined\n}\n"],"names":[],"mappings":";;AAEA;;;;;;;AAOG;AAEH;;;;;;;;;;;;AAYG;AACH,MAAM,qBAAqB,GAAG,gBAAgB;AAE9C;;;AAGG;AACH,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAEnD;;;AAGG;AACH,MAAM,2BAA2B,GAAG,6BAA6B;AAEjE;;;AAGG;AACH,SAAS,eAAe,CAAC,IAAa,EAAE,MAA0B,EAAA;AAChE,IAAA,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC;AAAE,QAAA,OAAO,IAAI;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC;AACrD,IAAA,OAAO,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,OAAO,GAAG,IAAI;AAC3D;AAEA;;;AAGG;AACH,SAAS,eAAe,CAAC,IAAa,EAAE,OAAgB,EAAA;IACtD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC;IAC9D,OAAO,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACvD;AAEA,SAAS,YAAY,CAAC,KAA2C,EAAA;IAC/D,IAAI,eAAe,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;QACpD,KAAK,CAAC,eAAe,EAAE;AAC3B;AAEA;;;AAGG;AACH,MAAM,mBAAmB,GAAG;AAC1B,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,WAAW,EAAE,YAAY;AACzB,IAAA,SAAS,EAAE,YAAY;AACvB,IAAA,aAAa,EAAE,YAAY;AAC3B,IAAA,WAAW,EAAE,YAAY;AACzB,IAAA,UAAU,EAAE,YAAY;AACxB,IAAA,YAAY,EAAE,YAAY;CAC3B;AAED;;;;;;;;;AASG;AACG,SAAU,mBAAmB,CACjC,KAAoC,EACpC,OAAgB,EAAA;IAEhB,SAAS,CAAC,MAAK;AACb,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO;AAC/B,QAAA,IAAI,CAAC,OAAO,IAAI,CAAC,SAAS;YAAE;AAE5B,QAAA,MAAM,qBAAqB,GAAG,CAAC,KAAoB,KAAI;YACrD,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;gBAAE;AACzC,YAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;AAC3B,YAAA,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC;gBAAE;YAClC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;YACjC,IAAI,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE;YACxC,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC;YAC7C,IAAI,CAAC,OAAO,IAAI,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC;gBAAE;YAChD,KAAK,CAAC,eAAe,EAAE;AACzB,QAAA,CAAC;QAED,SAAS,CAAC,gBAAgB,CAAC,SAAS,EAAE,qBAAqB,EAAE,IAAI,CAAC;AAClE,QAAA,OAAO,MACL,SAAS,CAAC,mBAAmB,CAAC,SAAS,EAAE,qBAAqB,EAAE,IAAI,CAAC;AACzE,IAAA,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAEpB,OAAO,OAAO,GAAG,mBAAmB,GAAG,SAAS;AAClD;;;;"}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import "./index.css";
|
|
2
2
|
import React from "react";
|
|
3
3
|
export interface PaginationProps {
|
|
4
|
+
/**
|
|
5
|
+
* Accessible name for the navigation landmark. Default `"Pagination"`. Pass a
|
|
6
|
+
* more specific name (e.g. `"people table pagination"`) when a page holds more
|
|
7
|
+
* than one set of page controls.
|
|
8
|
+
*/
|
|
9
|
+
"aria-label"?: string;
|
|
4
10
|
/** Pages always pinned at each edge (page `1` and the last page). Default `1`. */
|
|
5
11
|
boundaryCount?: number;
|
|
6
12
|
/** 1-indexed current page. */
|
|
@@ -20,7 +26,7 @@ export interface PaginationProps {
|
|
|
20
26
|
* @component
|
|
21
27
|
*/
|
|
22
28
|
export declare const Pagination: {
|
|
23
|
-
({ boundaryCount, currentPage, onPageChange, siblingCount, totalPages, }: PaginationProps): React.JSX.Element;
|
|
29
|
+
({ "aria-label": ariaLabel, boundaryCount, currentPage, onPageChange, siblingCount, totalPages, }: PaginationProps): React.JSX.Element;
|
|
24
30
|
displayName: string;
|
|
25
31
|
};
|
|
26
32
|
//# sourceMappingURL=Pagination.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/pagination/Pagination.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAMpB,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,MAAM,WAAW,eAAe;IAC9B,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,oGAAoG;IACpG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAA;CACnB;AAsGD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU;
|
|
1
|
+
{"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../../src/components/internal/pagination/Pagination.tsx"],"names":[],"mappings":"AAAA,OAAO,aAAa,CAAA;AAMpB,OAAO,KAAK,MAAM,OAAO,CAAA;AAQzB,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,kFAAkF;IAClF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,8BAA8B;IAC9B,WAAW,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,oGAAoG;IACpG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAA;CACnB;AAsGD;;;;;;GAMG;AACH,eAAO,MAAM,UAAU;uGAOpB,eAAe;;CAqCjB,CAAA"}
|
|
@@ -42,14 +42,14 @@ function PageItems({ currentPage, items, name, onPageChange }) {
|
|
|
42
42
|
*
|
|
43
43
|
* @component
|
|
44
44
|
*/
|
|
45
|
-
const Pagination = ({ boundaryCount, currentPage, onPageChange, siblingCount, totalPages, }) => {
|
|
45
|
+
const Pagination = ({ "aria-label": ariaLabel = "Pagination", boundaryCount, currentPage, onPageChange, siblingCount, totalPages, }) => {
|
|
46
46
|
const items = getPaginationItems({
|
|
47
47
|
boundaryCount,
|
|
48
48
|
currentPage,
|
|
49
49
|
siblingCount,
|
|
50
50
|
totalPages,
|
|
51
51
|
});
|
|
52
|
-
return (React__default.createElement(Flex, { align: "center", "aria-label":
|
|
52
|
+
return (React__default.createElement(Flex, { align: "center", "aria-label": ariaLabel, as: "nav", className: "tds-pagination", justify: "center" },
|
|
53
53
|
React__default.createElement(Flex, { align: "center", as: "ul", className: "tds-pagination-list", gap: 0.25 },
|
|
54
54
|
React__default.createElement(PreviousNextControls, { currentPage: currentPage, onPageChange: onPageChange, totalPages: totalPages }),
|
|
55
55
|
React__default.createElement(PageItems, { currentPage: currentPage, items: items.full, name: "full", onPageChange: onPageChange }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.js","sources":["../../../../src/components/internal/pagination/Pagination.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport { Flex } from \"@components/flex\"\nimport Icon from \"@utilities/Icon\"\nimport React from \"react\"\n\nimport {\n getPaginationItems,\n type PaginationItem,\n type PaginationItems,\n} from \"./getPaginationItems\"\n\nexport interface PaginationProps {\n /** Pages always pinned at each edge (page `1` and the last page). Default `1`. */\n boundaryCount?: number\n /** 1-indexed current page. */\n currentPage: number\n /** Called when a page control is activated. */\n onPageChange?: (page: number) => void\n /** Pages shown on each side of the current page in the full (non-collapsed) layout. Default `2`. */\n siblingCount?: number\n /** Total number of pages. */\n totalPages: number\n}\n\ntype PageChangeHandler = PaginationProps[\"onPageChange\"]\ntype PageItemsName = keyof PaginationItems\n\ninterface PreviousNextControlsProps {\n currentPage: number\n onPageChange: PageChangeHandler\n totalPages: number\n}\n\nfunction PreviousNextControls({\n currentPage,\n onPageChange,\n totalPages,\n}: PreviousNextControlsProps) {\n // Below 6 total pages the numbered run alone is enough to reach any page.\n if (totalPages < 6) return null\n\n return (\n <Flex align=\"center\" as=\"li\" className=\"tds-pagination-item\">\n <ButtonGroup aria-label=\"Change page\">\n <IconButton\n aria-label=\"Previous page\"\n disabled={currentPage <= 1}\n icon={<Icon aria-hidden symbol=\"general#left-chevron\" />}\n kind=\"neutral\"\n onClick={() => onPageChange?.(currentPage - 1)}\n />\n <IconButton\n aria-label=\"Next page\"\n disabled={currentPage >= totalPages}\n icon={<Icon aria-hidden symbol=\"general#right-chevron\" />}\n kind=\"neutral\"\n onClick={() => onPageChange?.(currentPage + 1)}\n />\n </ButtonGroup>\n </Flex>\n )\n}\n\ninterface PageControlProps {\n currentPage: number\n item: PaginationItem\n onPageChange: PageChangeHandler\n}\n\nfunction PageControl({ currentPage, item, onPageChange }: PageControlProps) {\n if (item === \"ellipsis\") {\n return <span className=\"tds-pagination-ellipsis\">…</span>\n }\n\n if (item === currentPage) {\n return (\n <span\n aria-current=\"page\"\n className=\"tds-pagination-page tds-pagination-page--current\"\n >\n {item}\n </span>\n )\n }\n\n return (\n <button\n className=\"tds-pagination-page\"\n onClick={() => onPageChange?.(item)}\n type=\"button\"\n >\n {item}\n </button>\n )\n}\n\ninterface PageItemsProps {\n currentPage: number\n items: PaginationItem[]\n name: PageItemsName\n onPageChange: PageChangeHandler\n}\n\nfunction PageItems({ currentPage, items, name, onPageChange }: PageItemsProps) {\n return items.map((item, index) => (\n <Flex\n align=\"center\"\n as=\"li\"\n className={`tds-pagination-item tds-pagination-item--${name}`}\n key={\n item === \"ellipsis\"\n ? `${name}-ellipsis-${index}`\n : `${name}-page-${item}`\n }\n >\n <PageControl\n currentPage={currentPage}\n item={item}\n onPageChange={onPageChange}\n />\n </Flex>\n ))\n}\n\n/**\n * Page controls internal to `DataTable`. Both responsive sets of page items\n * remain in static markup, and CSS selects the appropriate set by container\n * width.\n *\n * @component\n */\nexport const Pagination = ({\n boundaryCount,\n currentPage,\n onPageChange,\n siblingCount,\n totalPages,\n}: PaginationProps) => {\n const items = getPaginationItems({\n boundaryCount,\n currentPage,\n siblingCount,\n totalPages,\n })\n\n return (\n <Flex\n align=\"center\"\n aria-label
|
|
1
|
+
{"version":3,"file":"Pagination.js","sources":["../../../../src/components/internal/pagination/Pagination.tsx"],"sourcesContent":["import \"./index.css\"\n\nimport { IconButton } from \"@components/button\"\nimport { ButtonGroup } from \"@components/button-group\"\nimport { Flex } from \"@components/flex\"\nimport Icon from \"@utilities/Icon\"\nimport React from \"react\"\n\nimport {\n getPaginationItems,\n type PaginationItem,\n type PaginationItems,\n} from \"./getPaginationItems\"\n\nexport interface PaginationProps {\n /**\n * Accessible name for the navigation landmark. Default `\"Pagination\"`. Pass a\n * more specific name (e.g. `\"people table pagination\"`) when a page holds more\n * than one set of page controls.\n */\n \"aria-label\"?: string\n /** Pages always pinned at each edge (page `1` and the last page). Default `1`. */\n boundaryCount?: number\n /** 1-indexed current page. */\n currentPage: number\n /** Called when a page control is activated. */\n onPageChange?: (page: number) => void\n /** Pages shown on each side of the current page in the full (non-collapsed) layout. Default `2`. */\n siblingCount?: number\n /** Total number of pages. */\n totalPages: number\n}\n\ntype PageChangeHandler = PaginationProps[\"onPageChange\"]\ntype PageItemsName = keyof PaginationItems\n\ninterface PreviousNextControlsProps {\n currentPage: number\n onPageChange: PageChangeHandler\n totalPages: number\n}\n\nfunction PreviousNextControls({\n currentPage,\n onPageChange,\n totalPages,\n}: PreviousNextControlsProps) {\n // Below 6 total pages the numbered run alone is enough to reach any page.\n if (totalPages < 6) return null\n\n return (\n <Flex align=\"center\" as=\"li\" className=\"tds-pagination-item\">\n <ButtonGroup aria-label=\"Change page\">\n <IconButton\n aria-label=\"Previous page\"\n disabled={currentPage <= 1}\n icon={<Icon aria-hidden symbol=\"general#left-chevron\" />}\n kind=\"neutral\"\n onClick={() => onPageChange?.(currentPage - 1)}\n />\n <IconButton\n aria-label=\"Next page\"\n disabled={currentPage >= totalPages}\n icon={<Icon aria-hidden symbol=\"general#right-chevron\" />}\n kind=\"neutral\"\n onClick={() => onPageChange?.(currentPage + 1)}\n />\n </ButtonGroup>\n </Flex>\n )\n}\n\ninterface PageControlProps {\n currentPage: number\n item: PaginationItem\n onPageChange: PageChangeHandler\n}\n\nfunction PageControl({ currentPage, item, onPageChange }: PageControlProps) {\n if (item === \"ellipsis\") {\n return <span className=\"tds-pagination-ellipsis\">…</span>\n }\n\n if (item === currentPage) {\n return (\n <span\n aria-current=\"page\"\n className=\"tds-pagination-page tds-pagination-page--current\"\n >\n {item}\n </span>\n )\n }\n\n return (\n <button\n className=\"tds-pagination-page\"\n onClick={() => onPageChange?.(item)}\n type=\"button\"\n >\n {item}\n </button>\n )\n}\n\ninterface PageItemsProps {\n currentPage: number\n items: PaginationItem[]\n name: PageItemsName\n onPageChange: PageChangeHandler\n}\n\nfunction PageItems({ currentPage, items, name, onPageChange }: PageItemsProps) {\n return items.map((item, index) => (\n <Flex\n align=\"center\"\n as=\"li\"\n className={`tds-pagination-item tds-pagination-item--${name}`}\n key={\n item === \"ellipsis\"\n ? `${name}-ellipsis-${index}`\n : `${name}-page-${item}`\n }\n >\n <PageControl\n currentPage={currentPage}\n item={item}\n onPageChange={onPageChange}\n />\n </Flex>\n ))\n}\n\n/**\n * Page controls internal to `DataTable`. Both responsive sets of page items\n * remain in static markup, and CSS selects the appropriate set by container\n * width.\n *\n * @component\n */\nexport const Pagination = ({\n \"aria-label\": ariaLabel = \"Pagination\",\n boundaryCount,\n currentPage,\n onPageChange,\n siblingCount,\n totalPages,\n}: PaginationProps) => {\n const items = getPaginationItems({\n boundaryCount,\n currentPage,\n siblingCount,\n totalPages,\n })\n\n return (\n <Flex\n align=\"center\"\n aria-label={ariaLabel}\n as=\"nav\"\n className=\"tds-pagination\"\n justify=\"center\"\n >\n <Flex align=\"center\" as=\"ul\" className=\"tds-pagination-list\" gap={0.25}>\n <PreviousNextControls\n currentPage={currentPage}\n onPageChange={onPageChange}\n totalPages={totalPages}\n />\n <PageItems\n currentPage={currentPage}\n items={items.full}\n name=\"full\"\n onPageChange={onPageChange}\n />\n <PageItems\n currentPage={currentPage}\n items={items.compact}\n name=\"compact\"\n onPageChange={onPageChange}\n />\n </Flex>\n </Flex>\n )\n}\n\nPagination.displayName = \"Pagination\"\n"],"names":["React"],"mappings":"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"}
|