@pantheon-systems/pds-toolkit-react 2.0.0-alpha.20 → 2.0.0-alpha.22

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.
@@ -1,18 +1,141 @@
1
1
  import { ComponentPropsWithoutRef, ReactNode } from 'react';
2
2
  import './table.css';
3
+ export type SortOrder = 'asc' | 'desc';
4
+ export interface TableColumn {
5
+ /** Content to display in the header cell. */
6
+ header: ReactNode;
7
+ /** Stable identifier used for sort keys and cell lookup in rowData. */
8
+ id: string;
9
+ /** When true, renders a sort button next to the header label. */
10
+ sortable?: boolean;
11
+ }
3
12
  export interface TableProps extends ComponentPropsWithoutRef<'table'> {
4
13
  /** Additional class names */
5
14
  className?: string;
6
- /** Column index (0-based) to sort by on initial render. */
7
- defaultSortKey?: number;
8
- /** Initial sort direction when defaultSortKey is set. Defaults to 'asc'. */
9
- defaultSortOrder?: 'asc' | 'desc';
10
- /** Table headers */
11
- headers?: Array<{
12
- sortable?: boolean;
13
- title: ReactNode;
14
- }>;
15
- /** Table row data - array of rows, where each row is an array of cell values */
16
- rowData?: Array<Array<string | ReactNode>>;
15
+ /** Column definitions. Each column requires a stable `id`. */
16
+ columns: TableColumn[];
17
+ /**
18
+ * Current page number (1-based). Providing this alongside `onPageChange`
19
+ * enables controlled pagination mode.
20
+ */
21
+ currentPage?: number;
22
+ /**
23
+ * Column id to sort by on initial render. Only applies in uncontrolled sort mode.
24
+ */
25
+ defaultSortKey?: string;
26
+ /**
27
+ * Initial sort direction when `defaultSortKey` is set. Defaults to `'asc'`.
28
+ * Only applies in uncontrolled sort mode.
29
+ */
30
+ defaultSortOrder?: SortOrder;
31
+ /**
32
+ * Custom empty state rendered when `rowData` is empty and `isLoading` is false.
33
+ * When provided, takes precedence over `emptyStateHeading` and `emptyStateMessage`.
34
+ */
35
+ emptyState?: ReactNode;
36
+ /**
37
+ * Heading text for the default empty state. Defaults to `"No results found."`
38
+ * Override for translation or context-specific messaging.
39
+ */
40
+ emptyStateHeading?: string;
41
+ /**
42
+ * Optional message displayed below the heading in the default empty state.
43
+ */
44
+ emptyStateMessage?: string;
45
+ /**
46
+ * Returns the accessible label for each option in the rows-per-page selector.
47
+ * Defaults to `(size) => \`Show ${size} rows per page\``.
48
+ * Override for translation.
49
+ */
50
+ getPageSizeLabel?: (size: number) => string;
51
+ /**
52
+ * Derives a stable string ID from a row object for selection tracking.
53
+ * Defaults to the row's array index. Provide this when using pagination
54
+ * to preserve selection across page changes.
55
+ */
56
+ getRowId?: (row: Record<string, ReactNode>) => string;
57
+ /**
58
+ * Returns the visually hidden accessible label for each row's checkbox.
59
+ * Receives the row object and its 1-based display index.
60
+ * Defaults to `(_row, index) => \`Select row ${index}\``.
61
+ * Override to include a meaningful identifier (e.g. the site name) for
62
+ * screen reader users who navigate through checkboxes.
63
+ */
64
+ getSelectRowLabel?: (row: Record<string, ReactNode>, index: number) => string;
65
+ /**
66
+ * Returns the accessible label for a column's sort button.
67
+ * Defaults to `(columnHeader) => \`Sort by ${columnHeader}\``.
68
+ * Override for translation.
69
+ */
70
+ getSortLabel?: (columnHeader: string) => string;
71
+ /**
72
+ * When true, renders skeleton rows instead of data. Use while data is loading.
73
+ */
74
+ isLoading?: boolean;
75
+ /**
76
+ * Number of items per page. Required to enable pagination.
77
+ * In uncontrolled pagination mode the Table slices `rowData` internally.
78
+ * In controlled mode the consumer passes the current page slice as `rowData`.
79
+ */
80
+ itemsPerPage?: number;
81
+ /**
82
+ * Number of skeleton rows to render when `isLoading` is true. Defaults to 5.
83
+ */
84
+ loadingRowCount?: number;
85
+ /**
86
+ * Callback fired when the user navigates to a new page. Receives the new
87
+ * 1-based page number. Providing this prop enables controlled pagination mode.
88
+ */
89
+ onPageChange?: (page: number) => void;
90
+ /**
91
+ * Callback fired when the user changes the rows-per-page value.
92
+ * When provided alongside `pageSizeOptions`, enables controlled page size mode.
93
+ * In uncontrolled mode the Table manages page size internally.
94
+ */
95
+ onPageSizeChange?: (size: number) => void;
96
+ /**
97
+ * Callback fired when row selection changes. Providing this prop enables
98
+ * the checkbox column. Receives the full array of currently selected row IDs.
99
+ */
100
+ onRowSelectionChange?: (ids: string[]) => void;
101
+ /**
102
+ * Callback fired when a sortable header is clicked. Providing this prop
103
+ * enables controlled sort mode — the component will not sort `rowData`
104
+ * internally and expects the parent to pass pre-sorted data.
105
+ */
106
+ onSort?: (key: string, order: SortOrder) => void;
107
+ /**
108
+ * Available page size options rendered in the rows-per-page selector.
109
+ * When provided, the selector is shown to the left of the pagination controls.
110
+ */
111
+ pageSizeOptions?: number[];
112
+ /**
113
+ * Row data as an array of records keyed by column id.
114
+ * In controlled pagination mode, pass only the current page's rows.
115
+ */
116
+ rowData: Array<Record<string, ReactNode>>;
117
+ /**
118
+ * Visually hidden accessible label for the select-all header checkbox.
119
+ * Defaults to `'Select all rows'`. Override for translation.
120
+ */
121
+ selectAllLabel?: string;
122
+ /**
123
+ * Controlled selected row IDs. When provided alongside `onRowSelectionChange`,
124
+ * enables controlled selection mode.
125
+ */
126
+ selectedRows?: string[];
127
+ /**
128
+ * Controlled sort column id. Only used when `onSort` is provided.
129
+ */
130
+ sortKey?: string;
131
+ /**
132
+ * Controlled sort direction. Only used when `onSort` is provided.
133
+ */
134
+ sortOrder?: SortOrder;
135
+ /**
136
+ * Total number of items across all pages. Required in controlled pagination
137
+ * mode so the Pagination component can compute the page count.
138
+ */
139
+ totalItemCount?: number;
17
140
  }
18
- export declare const Table: ({ className, defaultSortKey, defaultSortOrder, headers, rowData, ...props }: TableProps) => import("react/jsx-runtime").JSX.Element;
141
+ export declare const Table: ({ className, columns, currentPage, defaultSortKey, defaultSortOrder, emptyState, emptyStateHeading, emptyStateMessage, getPageSizeLabel, getRowId, getSelectRowLabel, getSortLabel, isLoading, itemsPerPage, loadingRowCount, onPageChange, onPageSizeChange, onRowSelectionChange, onSort, pageSizeOptions, rowData, selectAllLabel, selectedRows, sortKey, sortOrder, totalItemCount, ...props }: TableProps) => import("react/jsx-runtime").JSX.Element;
@@ -1 +1 @@
1
- .pds-compact-empty-state{display:flex;flex-direction:column;font-family:var(--pds-typography-ff-default);padding-block:var(--pds-spacing-5xl);row-gap:var(--pds-spacing-xl);text-align:center;width:100%}.pds-compact-empty-state__icon{color:var(--pds-color-fg-default-secondary)}.pds-compact-empty-state__heading{display:block;margin-block-end:var(--pds-spacing-3xs)}.pds-compact-empty-state__message{color:var(--pds-color-text-default-secondary);font-size:var(--pds-typography-size-m);margin-block-end:0;margin-inline:auto;max-width:600px;text-wrap:pretty}
1
+ .pds-compact-empty-state{align-items:center;display:flex;flex-direction:column;font-family:var(--pds-typography-ff-default);padding-block:var(--pds-spacing-5xl);row-gap:var(--pds-spacing-xl);text-align:center;width:100%}.pds-compact-empty-state__icon{color:var(--pds-color-fg-default-secondary)}.pds-compact-empty-state__heading{display:block;font-size:var(--pds-typography-size-l);font-weight:var(--pds-typography-fw-bold);margin-block-end:var(--pds-spacing-3xs)}.pds-compact-empty-state__message{color:var(--pds-color-fg-default-secondary);font-size:var(--pds-typography-size-m);margin-block-end:0;margin-inline:auto;max-width:600px;text-wrap:pretty}
@@ -1,2 +1,2 @@
1
- .pds-dropdown{position:relative}.pds-dropdown--inline{display:inline-block}.pds-dropdown__trigger{align-items:center;background:transparent;border:none;border-radius:var(--pds-border-radius-container);color:inherit;cursor:pointer;display:inline-flex;font-family:inherit;gap:var(--pds-spacing-3xs);padding:var(--pds-spacing-3xs) var(--pds-spacing-2xs);transition:background-color .15s ease}.pds-dropdown__trigger:hover{background-color:var(--pds-color-interactive-background-hover)}.pds-dropdown__trigger:focus-visible{outline:var(--pds-border-width-outline) solid var(--pds-color-interactive-focus);outline-offset:1px}.pds-dropdown__trigger-icon{color:var(--pds-color-fg-default-secondary);transition:var(--pds-animation-transition-rotation)}.pds-dropdown__trigger[aria-expanded=true] .pds-dropdown__trigger-icon{transform:rotate(180deg)}.pds-dropdown__panel{background-color:var(--pds-color-dropdown-background);box-shadow:var(--pds-elevation-overlay);flex-direction:column;gap:var(--pds-spacing-4xs);margin:0;min-width:10rem;overflow-y:auto;padding-inline:var(--pds-spacing-2xs);z-index:var(--pds-z-index-dropdown)}.pds-dropdown__item,.pds-dropdown__panel{border-radius:var(--pds-border-radius-container);display:flex;list-style:none;outline:none;padding-block:var(--pds-spacing-2xs)}.pds-dropdown__item{align-items:center;color:var(--pds-color-dropdown-foreground);cursor:pointer;gap:var(--pds-spacing-2xs);justify-content:space-between;min-height:var(--pds-spacing-2xl);padding-inline:var(--pds-spacing-xs)}.pds-dropdown__item:focus-visible:not(:hover){outline:var(--pds-border-width-outline) solid var(--pds-color-interactive-focus);outline-offset:-1px}.pds-dropdown__item--focused,.pds-dropdown__item:hover{background-color:var(--pds-color-dropdown-item-background-hover)}.pds-dropdown__item:active{background-color:var(--pds-color-dropdown-item-background-active)}.pds-dropdown__selected-icon{align-self:center;color:var(--pds-color-status-success-foreground);display:flex;flex-shrink:0;height:.875em;width:.875em}.pds-dropdown__item--critical{color:var(--pds-color-status-critical-foreground)}.pds-dropdown__item--critical.pds-dropdown__item--focused,.pds-dropdown__item--critical:hover{background-color:var(--pds-color-status-critical-background)}.pds-dropdown__item--disabled{cursor:not-allowed;opacity:.5;pointer-events:none}.pds-dropdown__item-content{align-items:center;display:flex;gap:var(--pds-spacing-2xs)}.pds-dropdown__item-icon{display:flex;flex-shrink:0}.pds-dropdown__item-label{display:flex;flex-direction:column}.pds-dropdown__item-description{color:var(--pds-color-fg-default-secondary);font-size:var(--pds-typography-size-xs);line-height:var(--pds-typography-lh-s);margin-block-start:var(--pds-spacing-4xs)}.pds-dropdown__item-trailing{display:flex;flex-shrink:0}.pds-dropdown__heading{color:var(--pds-color-dropdown-heading);font-family:var(--pds-typography-ff-compact);font-size:var(--pds-typography-size-xs);font-weight:var(--pds-typography-fw-regular);line-height:var(--pds-typography-lh-s);list-style:none;padding:var(--pds-spacing-xs) var(--pds-spacing-xs) var(--pds-spacing-3xs)}.pds-dropdown__separator{border-block-end:var(--pds-border-width-default) solid var(--pds-color-border-default);list-style:none;margin-block-end:2px;margin-inline:calc(var(--pds-spacing-2xs)*-1);padding-block:2px}.pds-dropdown__filter{list-style:none;margin-block-start:calc(var(--pds-spacing-2xs)*-1);margin-inline:calc(var(--pds-spacing-2xs)*-1);padding:0}.pds-dropdown__filter-wrapper{align-items:center;display:flex;position:relative}.pds-dropdown__filter-icon{color:var(--pds-color-fg-default-secondary);left:var(--pds-spacing-s);pointer-events:none;position:absolute}.pds-dropdown__filter-wrapper:has(.pds-dropdown__filter-icon)
1
+ .pds-dropdown{position:relative}.pds-dropdown--inline{display:inline-block}.pds-dropdown__trigger{align-items:center;background:transparent;border:none;border-radius:var(--pds-border-radius-container);color:inherit;cursor:pointer;display:inline-flex;font-family:inherit;gap:var(--pds-spacing-3xs);padding:var(--pds-spacing-3xs) var(--pds-spacing-2xs);transition:background-color .15s ease}.pds-dropdown__trigger:hover{background-color:var(--pds-color-interactive-background-hover)}.pds-dropdown__trigger:focus-visible{outline:var(--pds-border-width-outline) solid var(--pds-color-interactive-focus);outline-offset:1px}.pds-dropdown__trigger-icon{color:var(--pds-color-fg-default-secondary);transition:var(--pds-animation-transition-rotation)}.pds-dropdown__trigger[aria-expanded=true] .pds-dropdown__trigger-icon{transform:rotate(180deg)}.pds-dropdown__panel{background-color:var(--pds-color-dropdown-background);box-shadow:var(--pds-elevation-overlay);flex-direction:column;gap:var(--pds-spacing-4xs);margin:0;min-width:10rem;overflow-y:auto;padding-inline:var(--pds-spacing-2xs);z-index:var(--pds-z-index-dropdown)}.pds-dropdown__item,.pds-dropdown__panel{border-radius:var(--pds-border-radius-container);display:flex;list-style:none;outline:none;padding-block:var(--pds-spacing-2xs)}.pds-dropdown__item{align-items:center;color:var(--pds-color-dropdown-foreground);cursor:pointer;gap:var(--pds-spacing-s);justify-content:space-between;min-height:var(--pds-spacing-2xl);padding-inline:var(--pds-spacing-xs)}.pds-dropdown__item:focus-visible:not(:hover){outline:var(--pds-border-width-outline) solid var(--pds-color-interactive-focus);outline-offset:-1px}.pds-dropdown__item--focused,.pds-dropdown__item:hover{background-color:var(--pds-color-dropdown-item-background-hover)}.pds-dropdown__item:active{background-color:var(--pds-color-dropdown-item-background-active)}.pds-dropdown__selected-icon{align-self:center;color:var(--pds-color-status-success-foreground);display:flex;flex-shrink:0;height:.875em;width:.875em}.pds-dropdown__item--critical{color:var(--pds-color-status-critical-foreground)}.pds-dropdown__item--critical.pds-dropdown__item--focused,.pds-dropdown__item--critical:hover{background-color:var(--pds-color-status-critical-background)}.pds-dropdown__item--disabled{cursor:not-allowed;opacity:.5;pointer-events:none}.pds-dropdown__item-content{align-items:center;display:flex;gap:var(--pds-spacing-2xs)}.pds-dropdown__item-icon{display:flex;flex-shrink:0}.pds-dropdown__item-label{display:flex;flex-direction:column}.pds-dropdown__item-description{color:var(--pds-color-fg-default-secondary);font-size:var(--pds-typography-size-xs);line-height:var(--pds-typography-lh-s);margin-block-start:var(--pds-spacing-4xs)}.pds-dropdown__item-trailing{display:flex;flex-shrink:0}.pds-dropdown__heading{color:var(--pds-color-dropdown-heading);font-family:var(--pds-typography-ff-compact);font-size:var(--pds-typography-size-xs);font-weight:var(--pds-typography-fw-regular);line-height:var(--pds-typography-lh-s);list-style:none;padding:var(--pds-spacing-xs) var(--pds-spacing-xs) var(--pds-spacing-3xs)}.pds-dropdown__separator{border-block-end:var(--pds-border-width-default) solid var(--pds-color-border-default);list-style:none;margin-block-end:2px;margin-inline:calc(var(--pds-spacing-2xs)*-1);padding-block:2px}.pds-dropdown__filter{list-style:none;margin-block-start:calc(var(--pds-spacing-2xs)*-1);margin-inline:calc(var(--pds-spacing-2xs)*-1);padding:0}.pds-dropdown__filter-wrapper{align-items:center;display:flex;position:relative}.pds-dropdown__filter-icon{color:var(--pds-color-fg-default-secondary);left:var(--pds-spacing-s);pointer-events:none;position:absolute}.pds-dropdown__filter-wrapper:has(.pds-dropdown__filter-icon)
2
2
  .pds-dropdown__filter-input{padding-inline-start:calc(var(--pds-spacing-s) + var(--pds-spacing-xl))}.pds-dropdown__filter-input{background-color:transparent;border:none;border-block-end:var(--pds-border-width-default) solid var(--pds-color-border-separator);border-radius:0;box-sizing:border-box;color:var(--pds-color-fg-default);font-family:inherit;font-size:var(--pds-typography-size-s);padding:var(--pds-spacing-xs) var(--pds-spacing-s);width:100%}.pds-dropdown__filter-input::placeholder{color:var(--pds-color-input-placeholder);font-size:var(--pds-typography-size-xs)}.pds-dropdown__filter-input:focus-visible{border-radius:var(--pds-border-radius-container) var(--pds-border-radius-container) 0 0;outline:var(--pds-border-width-outline) solid var(--pds-color-interactive-focus);outline-offset:-3px}.pds-dropdown__no-results{color:var(--pds-color-fg-default-secondary);font-size:var(--pds-typography-size-s);padding-block-end:var(--pds-spacing-s);padding-block-start:var(--pds-spacing-xs);padding-inline:var(--pds-spacing-s)}