\n Organization members can only see data for the most recently-updated\n repositories. To see all repositories, talk to your organization\n administrator about becoming a security manager.\n
}
+// ----------------------------------------------------------------------------
+// TableSkeleton
+// ----------------------------------------------------------------------------
+export type TableSkeletonProps = React.ComponentPropsWithoutRef<'table'> & {
+ /**
+ * Specify the amount of space that should be available around the contents of
+ * a cell
+ */
+ cellPadding?: 'condensed' | 'normal' | 'spacious'
+
+ /**
+ * Provide an array of columns for the table. Columns will render as the headers
+ * of the table.
+ */
+ columns: Array>
+
+ /**
+ * Optionally specify the number of rows which should be included in the
+ * skeleton state of the component
+ */
+ rows?: number
+}
+
+function TableSkeleton({cellPadding, columns, rows = 10, ...rest}: TableSkeletonProps) {
+ const {gridTemplateColumns} = useTableLayout(columns)
+ return (
+
+
+ >,
+ )
+
+ expect(screen.getByRole('table', {name: 'Test'})).toBeInTheDocument()
+ for (const column of columns) {
+ expect(screen.getByRole('columnheader', {name: column.header as string})).toBeInTheDocument()
+ }
+
+ for (const cell of screen.getAllByRole('cell')) {
+ expect(cell).toHaveTextContent('Loading')
+ }
+ })
+ })
})
diff --git a/src/DataTable/index.ts b/src/DataTable/index.ts
index b98a280cfb8..b6a3ebc63b6 100644
--- a/src/DataTable/index.ts
+++ b/src/DataTable/index.ts
@@ -12,6 +12,7 @@ import {
TableSubtitle,
TableActions,
TableDivider,
+ TableSkeleton,
} from './Table'
const Table = Object.assign(TableImpl, {
@@ -20,6 +21,7 @@ const Table = Object.assign(TableImpl, {
Subtitle: TableSubtitle,
Actions: TableActions,
Divider: TableDivider,
+ Skeleton: TableSkeleton,
Head: TableHead,
Body: TableBody,
Header: TableHeader,
@@ -41,4 +43,5 @@ export type {
TableTitleProps,
TableSubtitleProps,
TableActionsProps,
+ TableSkeletonProps,
} from './Table'
diff --git a/src/DataTable/useTable.ts b/src/DataTable/useTable.ts
index 67a1c145ddf..cf9579a8764 100644
--- a/src/DataTable/useTable.ts
+++ b/src/DataTable/useTable.ts
@@ -42,48 +42,6 @@ interface Cell {
type ColumnSortState = {id: string | number; direction: Exclude} | null
-export function getGridTemplateFromColumns(columns: Array>): string[] {
- return columns.map(column => {
- const columnWidth = column.width ?? 'grow'
- let minWidth = 'auto'
- let maxWidth = '1fr'
-
- if (columnWidth === 'auto') {
- maxWidth = 'auto'
- }
-
- // Setting a min-width of 'max-content' ensures that the column will grow to fit the widest cell's content.
- // However, If the column has a max width, we can't set the min width to `max-content` because
- // the widest cell's content might overflow the container.
- if (columnWidth === 'grow' && !column.maxWidth) {
- minWidth = 'max-content'
- }
-
- // Column widths set to "growCollapse" don't need a min width unless one is explicitly provided.
- if (columnWidth === 'growCollapse') {
- minWidth = '0'
- }
-
- // If a consumer passes `minWidth` or `maxWidth`, we need to override whatever we set above.
- if (column.minWidth) {
- minWidth = typeof column.minWidth === 'number' ? `${column.minWidth}px` : column.minWidth
- }
-
- if (column.maxWidth) {
- maxWidth = typeof column.maxWidth === 'number' ? `${column.maxWidth}px` : column.maxWidth
- }
-
- // If a consumer is passing one of the shorthand widths or doesn't pass a width at all, we use the
- // min and max width calculated above to create a minmax() column template value.
- if (typeof columnWidth !== 'number' && ['grow', 'growCollapse', 'auto'].includes(columnWidth)) {
- return minWidth === maxWidth ? minWidth : `minmax(${minWidth}, ${maxWidth})`
- }
-
- // If we reach this point, the consumer is passing an explicit width value.
- return typeof columnWidth === 'number' ? `${columnWidth}px` : columnWidth
- })
-}
-
export function useTable({
columns,
data,
@@ -96,6 +54,7 @@ export function useTable({
const [sortByColumn, setSortByColumn] = useState(() => {
return getInitialSortState(columns, initialSortColumn, initialSortDirection)
})
+ const {gridTemplateColumns} = useTableLayout(columns)
// Reset the `sortByColumn` state if the columns change and that column is no
// longer provided
@@ -235,7 +194,7 @@ export function useTable({
actions: {
sortBy,
},
- gridTemplateColumns: getGridTemplateFromColumns(columns).join(' '),
+ gridTemplateColumns,
}
}
@@ -310,6 +269,54 @@ function getInitialSortState(
return null
}
+export function useTableLayout(columns: Array>): {gridTemplateColumns: string} {
+ return {
+ gridTemplateColumns: getGridTemplateFromColumns(columns).join(' '),
+ }
+}
+
+export function getGridTemplateFromColumns(columns: Array>): string[] {
+ return columns.map(column => {
+ const columnWidth = column.width ?? 'grow'
+ let minWidth = 'auto'
+ let maxWidth = '1fr'
+
+ if (columnWidth === 'auto') {
+ maxWidth = 'auto'
+ }
+
+ // Setting a min-width of 'max-content' ensures that the column will grow to fit the widest cell's content.
+ // However, If the column has a max width, we can't set the min width to `max-content` because
+ // the widest cell's content might overflow the container.
+ if (columnWidth === 'grow' && !column.maxWidth) {
+ minWidth = 'max-content'
+ }
+
+ // Column widths set to "growCollapse" don't need a min width unless one is explicitly provided.
+ if (columnWidth === 'growCollapse') {
+ minWidth = '0'
+ }
+
+ // If a consumer passes `minWidth` or `maxWidth`, we need to override whatever we set above.
+ if (column.minWidth) {
+ minWidth = typeof column.minWidth === 'number' ? `${column.minWidth}px` : column.minWidth
+ }
+
+ if (column.maxWidth) {
+ maxWidth = typeof column.maxWidth === 'number' ? `${column.maxWidth}px` : column.maxWidth
+ }
+
+ // If a consumer is passing one of the shorthand widths or doesn't pass a width at all, we use the
+ // min and max width calculated above to create a minmax() column template value.
+ if (typeof columnWidth !== 'number' && ['grow', 'growCollapse', 'auto'].includes(columnWidth)) {
+ return minWidth === maxWidth ? minWidth : `minmax(${minWidth}, ${maxWidth})`
+ }
+
+ // If we reach this point, the consumer is passing an explicit width value.
+ return typeof columnWidth === 'number' ? `${columnWidth}px` : columnWidth
+ })
+}
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function get, Path extends string>(
object: ObjectType,