diff --git a/packages/@react-spectrum/table/test/Table.ssr.test.js b/packages/@react-spectrum/table/test/Table.ssr.test.js
index 58665ea39a1..820c8b13ddf 100644
--- a/packages/@react-spectrum/table/test/Table.ssr.test.js
+++ b/packages/@react-spectrum/table/test/Table.ssr.test.js
@@ -42,3 +42,92 @@ describe('Table SSR', function () {
`);
});
});
+
+describe('Table Nested Rows SSR', function () {
+ it('should render without errors', async function () {
+ await testSSR(__filename, `
+ import {Provider} from '@react-spectrum/provider';
+ import {theme} from '@react-spectrum/theme-default';
+ import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../';
+ import {enableTableNestedRows} from '@react-stately/flags';
+ enableTableNestedRows();
+
+ let nestedItems = [
+ {foo: 'Lvl 1 Foo 1', bar: 'Lvl 1 Bar 1', baz: 'Lvl 1 Baz 1', childRows: [
+ {foo: 'Lvl 2 Foo 1', bar: 'Lvl 2 Bar 1', baz: 'Lvl 2 Baz 1', childRows: [
+ {foo: 'Lvl 3 Foo 1', bar: 'Lvl 3 Bar 1', baz: 'Lvl 3 Baz 1'}
+ ]},
+ {foo: 'Lvl 2 Foo 2', bar: 'Lvl 2 Bar 2', baz: 'Lvl 2 Baz 2'}
+ ]}
+ ];
+
+ let columns = [
+ {name: 'Foo', key: 'foo'},
+ {name: 'Bar', key: 'bar'},
+ {name: 'Baz', key: 'baz'}
+ ];
+
+
+
+
+ {column => {column.name}}
+
+
+ {(item) =>
+ (
+ {(key) => {
+ return {item[key.toString()]} | ;
+ }}
+
)
+ }
+
+
+
+ `);
+ });
+});
+
+// TODO: selectionMode="multiple" errors
+describe('Table Static SSR', function () {
+ it('should render without errors', async function () {
+ await testSSR(__filename, `
+ import {Provider} from '@react-spectrum/provider';
+ import {theme} from '@react-spectrum/theme-default';
+ import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../';
+ import {enableTableNestedRows} from '@react-stately/flags';
+ enableTableNestedRows();
+
+
+
+
+ Name
+ Type
+ Date Modified
+
+
+
+ Games |
+ File folder |
+ 6/7/2020 |
+
+
+ Program Files |
+ File folder |
+ 4/7/2021 |
+
+
+ bootmgr |
+ System file |
+ 11/20/2010 |
+
+
+ log.txt |
+ Text Document |
+ 1/18/2016 |
+
+
+
+
+ `);
+ });
+});
diff --git a/packages/@react-spectrum/table/test/Table.test.js b/packages/@react-spectrum/table/test/Table.test.js
index 63ee4dda0ae..8e6b2e56683 100644
--- a/packages/@react-spectrum/table/test/Table.test.js
+++ b/packages/@react-spectrum/table/test/Table.test.js
@@ -23,7 +23,6 @@ import {Content} from '@react-spectrum/view';
import {CRUDExample} from '../stories/CRUDExample';
import {Dialog, DialogTrigger} from '@react-spectrum/dialog';
import {Divider} from '@react-spectrum/divider';
-import {enableTableNestedRows} from '@react-stately/flags';
import {getFocusableTreeWalker} from '@react-aria/focus';
import {Heading} from '@react-spectrum/text';
import {Item, Picker} from '@react-spectrum/picker';
@@ -5041,11 +5040,3 @@ export let tableTests = () => {
};
describe('TableView', tableTests);
-
-describe('TableView with expandable rows flag on', function () {
- beforeAll(() => {
- enableTableNestedRows();
- });
-
- tableTests();
-});
diff --git a/packages/@react-spectrum/table/test/TableNestedRows.test.js b/packages/@react-spectrum/table/test/TableNestedRows.test.js
new file mode 100644
index 00000000000..415b76eb2f1
--- /dev/null
+++ b/packages/@react-spectrum/table/test/TableNestedRows.test.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2020 Adobe. All rights reserved.
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License. You may obtain a copy
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
+ * OF ANY KIND, either express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+
+jest.mock('@react-aria/live-announcer');
+jest.mock('@react-aria/utils/src/scrollIntoView');
+import {act, render as renderComponent} from '@react-spectrum/test-utils-internal';
+import {Cell, Column, Row, TableBody, TableHeader, TableView} from '../';
+import {enableTableNestedRows} from '@react-stately/flags';
+import {Provider} from '@react-spectrum/provider';
+import React from 'react';
+import {tableTests} from './Table.test';
+import {theme} from '@react-spectrum/theme-default';
+
+describe('TableView with expandable rows flag on', function () {
+ beforeAll(() => {
+ enableTableNestedRows();
+ });
+
+ tableTests();
+
+ describe('with nested rows', function () {
+ let offsetWidth, offsetHeight;
+
+ beforeAll(function () {
+ offsetWidth = jest.spyOn(window.HTMLElement.prototype, 'clientWidth', 'get').mockImplementation(() => 1000);
+ offsetHeight = jest.spyOn(window.HTMLElement.prototype, 'clientHeight', 'get').mockImplementation(() => 1000);
+ jest.useFakeTimers();
+ });
+
+ afterAll(function () {
+ offsetWidth.mockReset();
+ offsetHeight.mockReset();
+ });
+
+ afterEach(() => {
+ act(() => {jest.runAllTimers();});
+ });
+ it('can render', function () {
+ let columns = [
+ {name: 'Foo', key: 'foo'},
+ {name: 'Bar', key: 'bar'},
+ {name: 'Baz', key: 'baz'}
+ ];
+
+ let nestedItems = [
+ {foo: 'Lvl 1 Foo 1', bar: 'Lvl 1 Bar 1', baz: 'Lvl 1 Baz 1', childRows: [
+ {foo: 'Lvl 2 Foo 1', bar: 'Lvl 2 Bar 1', baz: 'Lvl 2 Baz 1', childRows: [
+ {foo: 'Lvl 3 Foo 1', bar: 'Lvl 3 Bar 1', baz: 'Lvl 3 Baz 1'}
+ ]},
+ {foo: 'Lvl 2 Foo 2', bar: 'Lvl 2 Bar 2', baz: 'Lvl 2 Baz 2'}
+ ]}
+ ];
+
+ renderComponent(
+
+
+
+ {column => {column.name}}
+
+
+ {(item) =>
+ (
+ {(key) => {
+ return {item[key]} | ;
+ }}
+
)
+ }
+
+
+
+ );
+ });
+ });
+});
diff --git a/packages/@react-stately/grid/src/GridCollection.ts b/packages/@react-stately/grid/src/GridCollection.ts
index 20dc2db58dd..4b78da4f95f 100644
--- a/packages/@react-stately/grid/src/GridCollection.ts
+++ b/packages/@react-stately/grid/src/GridCollection.ts
@@ -79,20 +79,6 @@ export class GridCollection implements IGridCollection {
if (last) {
last.nextKey = null;
-
- if (rowHasCellWithColSpan && node.type === 'item') {
- let lastColIndex = last?.colIndex ?? 0 + 1; // internally colIndex is 0 based
- let lastColSpan = last?.colSpan ?? 1;
- let numberOfCellsInRow = lastColIndex + lastColSpan;
- if (numberOfCellsInRow !== this.columnCount) {
- throw new Error(`Cell count must match column count. Found ${numberOfCellsInRow} cells and ${this.columnCount} columns.`);
- }
- } else if (node.type === 'item') {
- let numberOfCellsInRow = [...node.childNodes].length;
- if (numberOfCellsInRow !== this.columnCount) {
- throw new Error(`Cell count must match column count. Found ${numberOfCellsInRow} cells and ${this.columnCount} columns.`);
- }
- }
}
// Remove deleted nodes and their children from the key map
diff --git a/packages/@react-stately/table/src/Row.ts b/packages/@react-stately/table/src/Row.ts
index b3c2d7a10fd..9cc5595538f 100644
--- a/packages/@react-stately/table/src/Row.ts
+++ b/packages/@react-stately/table/src/Row.ts
@@ -72,6 +72,7 @@ Row.getCollectionNode = function* getCollectionNode(props: RowProps, conte
} else {
let cells: PartialNode[] = [];
let childRows: PartialNode[] = [];
+ let columnCount = 0;
React.Children.forEach(children, node => {
if (node.type === Row) {
if (cells.length < context.columns.length) {
@@ -87,9 +88,14 @@ Row.getCollectionNode = function* getCollectionNode(props: RowProps, conte
type: 'cell',
element: node
});
+ columnCount += node.props.colSpan ?? 1;
}
});
+ if (columnCount !== context.columns.length) {
+ throw new Error(`Cell count must match column count. Found ${columnCount} cells and ${context.columns.length} columns.`);
+ }
+
yield* cells;
yield* childRows;
}