diff --git a/change/@fluentui-react-components-7a8583a3-a0c8-4391-9083-d36fa2598973.json b/change/@fluentui-react-components-7a8583a3-a0c8-4391-9083-d36fa2598973.json
new file mode 100644
index 00000000000000..5f83e892f15129
--- /dev/null
+++ b/change/@fluentui-react-components-7a8583a3-a0c8-4391-9083-d36fa2598973.json
@@ -0,0 +1,7 @@
+{
+ "type": "patch",
+ "comment": "feat: exports `useDataGridContextValues_unstable`",
+ "packageName": "@fluentui/react-components",
+ "email": "lingfangao@hotmail.com",
+ "dependentChangeType": "patch"
+}
diff --git a/change/@fluentui-react-table-4d29794e-c7a5-4723-8a85-3e5668c2c102.json b/change/@fluentui-react-table-4d29794e-c7a5-4723-8a85-3e5668c2c102.json
new file mode 100644
index 00000000000000..acfc2b079995b8
--- /dev/null
+++ b/change/@fluentui-react-table-4d29794e-c7a5-4723-8a85-3e5668c2c102.json
@@ -0,0 +1,7 @@
+{
+ "type": "prerelease",
+ "comment": "feat: exports `useDataGridContextValues_unstable`",
+ "packageName": "@fluentui/react-table",
+ "email": "lingfangao@hotmail.com",
+ "dependentChangeType": "patch"
+}
diff --git a/packages/react-components/react-components/etc/react-components.unstable.api.md b/packages/react-components/react-components/etc/react-components.unstable.api.md
index 58ea76622cfee9..a9b4d3172608aa 100644
--- a/packages/react-components/react-components/etc/react-components.unstable.api.md
+++ b/packages/react-components/react-components/etc/react-components.unstable.api.md
@@ -223,6 +223,7 @@ import { useDataGridBody_unstable } from '@fluentui/react-table';
import { useDataGridBodyStyles_unstable } from '@fluentui/react-table';
import { useDataGridCell_unstable } from '@fluentui/react-table';
import { useDataGridCellStyles_unstable } from '@fluentui/react-table';
+import { useDataGridContextValues_unstable } from '@fluentui/react-table';
import { useDataGridHeader_unstable } from '@fluentui/react-table';
import { useDataGridHeaderCell_unstable } from '@fluentui/react-table';
import { useDataGridHeaderCellStyles_unstable } from '@fluentui/react-table';
@@ -713,6 +714,8 @@ export { useDataGridCell_unstable }
export { useDataGridCellStyles_unstable }
+export { useDataGridContextValues_unstable }
+
export { useDataGridHeader_unstable }
export { useDataGridHeaderCell_unstable }
diff --git a/packages/react-components/react-components/src/unstable/index.ts b/packages/react-components/react-components/src/unstable/index.ts
index 071aa3890facba..9c23a561df6d09 100644
--- a/packages/react-components/react-components/src/unstable/index.ts
+++ b/packages/react-components/react-components/src/unstable/index.ts
@@ -139,6 +139,7 @@ export {
useDataGridStyles_unstable,
useDataGrid_unstable,
renderDataGrid_unstable,
+ useDataGridContextValues_unstable,
DataGridHeader,
dataGridHeaderClassNames,
useDataGridHeaderStyles_unstable,
diff --git a/packages/react-components/react-data-grid-react-window/etc/react-data-grid-react-window.api.md b/packages/react-components/react-data-grid-react-window/etc/react-data-grid-react-window.api.md
index 00b194abd2edcf..91df62b77636f8 100644
--- a/packages/react-components/react-data-grid-react-window/etc/react-data-grid-react-window.api.md
+++ b/packages/react-components/react-data-grid-react-window/etc/react-data-grid-react-window.api.md
@@ -7,12 +7,23 @@
///
import type { DataGridBodyProps as DataGridBodyProps_2 } from '@fluentui/react-table';
-import type { DataGridBodySlots as DataGridBodySlots_2 } from '@fluentui/react-table';
-import type { DataGridBodyState as DataGridBodyState_2 } from '@fluentui/react-table';
+import { DataGridCell } from '@fluentui/react-table';
+import { DataGridCellProps } from '@fluentui/react-table';
+import { DataGridHeader } from '@fluentui/react-table';
+import { DataGridHeaderCell } from '@fluentui/react-table';
+import { DataGridHeaderCellProps } from '@fluentui/react-table';
+import { DataGridHeaderProps } from '@fluentui/react-table';
+import { DataGridProps } from '@fluentui/react-table';
+import { DataGridRowProps } from '@fluentui/react-table';
+import { DataGridSelectionCell } from '@fluentui/react-table';
+import { DataGridSelectionCellProps } from '@fluentui/react-table';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React_2 from 'react';
import type { TableRowData } from '@fluentui/react-table';
+// @public (undocumented)
+export const DataGrid: ForwardRefComponent;
+
// @public
export const DataGridBody: ForwardRefComponent & ((props: DataGridBodyProps) => JSX.Element);
@@ -22,21 +33,31 @@ export type DataGridBodyProps = Omit;
+ ariaRowIndexStart?: number;
};
-// @public (undocumented)
-export type DataGridBodySlots = DataGridBodySlots_2;
+export { DataGridCell }
-// @public
-export type DataGridBodyState = Omit & Pick & Pick, 'width'> & {
- renderRow: RowRenderFunction;
-};
+export { DataGridCellProps }
-// @public
-export const renderDataGridBody_unstable: (state: DataGridBodyState) => JSX.Element;
+export { DataGridHeader }
+
+export { DataGridHeaderCell }
+
+export { DataGridHeaderCellProps }
+
+export { DataGridHeaderProps }
+
+export { DataGridProps }
// @public
-export const useDataGridBody_unstable: (props: DataGridBodyProps, ref: React_2.Ref) => DataGridBodyState;
+export const DataGridRow: ForwardRefComponent & ((props: DataGridRowProps) => JSX.Element);
+
+export { DataGridRowProps }
+
+export { DataGridSelectionCell }
+
+export { DataGridSelectionCellProps }
// (No @packageDocumentation comment for this package)
diff --git a/packages/react-components/react-data-grid-react-window/src/DataGrid.ts b/packages/react-components/react-data-grid-react-window/src/DataGrid.ts
new file mode 100644
index 00000000000000..f0274f9b91596f
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/DataGrid.ts
@@ -0,0 +1 @@
+export * from './components/DataGrid/index';
diff --git a/packages/react-components/react-data-grid-react-window/src/DataGridRow.ts b/packages/react-components/react-data-grid-react-window/src/DataGridRow.ts
new file mode 100644
index 00000000000000..dff1abb3f73e23
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/DataGridRow.ts
@@ -0,0 +1 @@
+export * from './components/DataGridRow';
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGrid/DataGrid.tsx b/packages/react-components/react-data-grid-react-window/src/components/DataGrid/DataGrid.tsx
new file mode 100644
index 00000000000000..b2daaa21a7941e
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGrid/DataGrid.tsx
@@ -0,0 +1,18 @@
+import * as React from 'react';
+import { useDataGrid_unstable } from './useDataGrid';
+import {
+ renderDataGrid_unstable,
+ useDataGridStyles_unstable,
+ useDataGridContextValues_unstable,
+} from '@fluentui/react-table';
+import type { DataGridProps } from '@fluentui/react-table';
+import type { ForwardRefComponent } from '@fluentui/react-utilities';
+
+export const DataGrid: ForwardRefComponent = React.forwardRef((props, ref) => {
+ const state = useDataGrid_unstable(props, ref);
+
+ useDataGridStyles_unstable(state);
+ return renderDataGrid_unstable(state, useDataGridContextValues_unstable(state));
+});
+
+DataGrid.displayName = 'DataGrid';
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGrid/index.ts b/packages/react-components/react-data-grid-react-window/src/components/DataGrid/index.ts
new file mode 100644
index 00000000000000..0b3589e2b3bc1d
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGrid/index.ts
@@ -0,0 +1,2 @@
+export * from './DataGrid';
+export * from './useDataGrid';
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGrid/useDataGrid.ts b/packages/react-components/react-data-grid-react-window/src/components/DataGrid/useDataGrid.ts
new file mode 100644
index 00000000000000..c50790787ddad8
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGrid/useDataGrid.ts
@@ -0,0 +1,16 @@
+import * as React from 'react';
+import type { DataGridProps, DataGridState } from '@fluentui/react-table';
+import { useDataGrid_unstable as useBaseState } from '@fluentui/react-table';
+
+/**
+ * Create the state required to render DataGrid.
+ *
+ * The returned state can be modified with hooks such as useDataGridStyles_unstable,
+ * before being passed to renderDataGrid_unstable.
+ *
+ * @param props - props from this instance of DataGrid
+ * @param ref - reference to root HTMLElement of DataGrid
+ */
+export const useDataGrid_unstable = (props: DataGridProps, ref: React.Ref): DataGridState => {
+ return useBaseState({ ...props, 'aria-rowcount': props.items.length }, ref);
+};
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/DataGridBody.test.tsx b/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/DataGridBody.test.tsx
deleted file mode 100644
index 4bc16e449b3b03..00000000000000
--- a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/DataGridBody.test.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { DataGridBody } from './DataGridBody';
-import { DataGridBodyProps } from './DataGridBody.types';
-import { isConformant } from '../../testing/isConformant';
-
-describe('DataGridBody', () => {
- isConformant({
- Component: DataGridBody,
- displayName: 'DataGridBody',
- disabledTests: ['component-has-static-classnames-object'],
- requiredProps: {
- height: 50,
- itemSize: 1000,
- },
- });
-});
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/DataGridBody.types.ts b/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/DataGridBody.types.ts
index 227cdb7c96488f..44d0baf65fe88c 100644
--- a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/DataGridBody.types.ts
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/DataGridBody.types.ts
@@ -34,6 +34,13 @@ export type DataGridBodyProps = Omit;
+ /**
+ * All virtualized rows must have the [aria-rowindex](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-rowindex)
+ * attribute for correct screen reader navigation. The default start index is 2 since we assume that there is only
+ * one row in the header. If this is not the case, the start index can be reconfigured through this prop.
+ * @default 2
+ */
+ ariaRowIndexStart?: number;
};
/**
@@ -41,6 +48,6 @@ export type DataGridBodyProps = Omit &
Pick &
- Pick, 'width'> & {
+ Pick, 'width' | 'ariaRowIndexStart'> & {
renderRow: RowRenderFunction;
};
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/renderDataGridBody.tsx b/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/renderDataGridBody.tsx
index bb0b233768b6cf..5d4edd062a76a2 100644
--- a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/renderDataGridBody.tsx
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/renderDataGridBody.tsx
@@ -3,6 +3,7 @@ import type { DataGridBodyState, DataGridBodySlots } from './DataGridBody.types'
import { FixedSizeList as List, ListChildComponentProps } from 'react-window';
import { getSlots } from '@fluentui/react-utilities';
import { TableRowData, TableRowIdContextProvider } from '@fluentui/react-table';
+import { TableRowIndexContextProvider } from '../../contexts/rowIndexContext';
/**
* Render the final JSX of DataGridVirtualizedBody
@@ -21,7 +22,11 @@ export const renderDataGridBody_unstable = (state: DataGridBodyState) => {
>
{({ data, index, style }: ListChildComponentProps) => {
const row: TableRowData = data[index];
- return {state.renderRow(row, style)};
+ return (
+
+ {state.renderRow(row, style)}
+
+ );
}}
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/useDataGridBody.ts b/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/useDataGridBody.ts
index 5f945f12f5b794..04274aa32bb715 100644
--- a/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/useDataGridBody.ts
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGridBody/useDataGridBody.ts
@@ -12,7 +12,7 @@ import { useDataGridBody_unstable as useDataGridBodyBase_unstable, RowRenderFunc
* @param ref - reference to root HTMLElement of DataGridBody
*/
export const useDataGridBody_unstable = (props: DataGridBodyProps, ref: React.Ref): DataGridBodyState => {
- const { height, itemSize, width = '100%', children } = props;
+ const { height, itemSize, width = '100%', ariaRowIndexStart = 2, children } = props;
// cast the row render function to work with unknown args
const renderRowWithUnknown = children as RowRenderFunction;
@@ -24,5 +24,6 @@ export const useDataGridBody_unstable = (props: DataGridBodyProps, ref: React.Re
height,
renderRow: children,
width,
+ ariaRowIndexStart,
};
};
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/DataGridRow.tsx b/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/DataGridRow.tsx
new file mode 100644
index 00000000000000..11c6f85063d87c
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/DataGridRow.tsx
@@ -0,0 +1,18 @@
+import * as React from 'react';
+import { useDataGridRowStyles_unstable, renderDataGridRow_unstable } from '@fluentui/react-table';
+import { useDataGridRow_unstable } from './useDataGridRow';
+import type { DataGridRowProps } from '@fluentui/react-table';
+import type { ForwardRefComponent } from '@fluentui/react-utilities';
+
+/**
+ * DataGridRow component
+ */
+export const DataGridRow: ForwardRefComponent &
+ ((props: DataGridRowProps) => JSX.Element) = React.forwardRef((props, ref) => {
+ const state = useDataGridRow_unstable(props, ref);
+
+ useDataGridRowStyles_unstable(state);
+ return renderDataGridRow_unstable(state);
+}) as ForwardRefComponent & ((props: DataGridRowProps) => JSX.Element);
+
+DataGridRow.displayName = 'DataGridRow';
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/index.ts b/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/index.ts
new file mode 100644
index 00000000000000..15727b3664100a
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/index.ts
@@ -0,0 +1,2 @@
+export * from './DataGridRow';
+export * from './useDataGridRow';
diff --git a/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/useDataGridRow.ts b/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/useDataGridRow.ts
new file mode 100644
index 00000000000000..b7e73da01d1b7c
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/components/DataGridRow/useDataGridRow.ts
@@ -0,0 +1,18 @@
+import * as React from 'react';
+import type { DataGridRowProps, DataGridRowState } from '@fluentui/react-table';
+import { useDataGridRow_unstable as useBaseState } from '@fluentui/react-table';
+import { useTableRowIndexContext } from '../../contexts/rowIndexContext';
+
+/**
+ * Create the state required to render DataGridRow.
+ *
+ * The returned state can be modified with hooks such as useDataGridRowStyles_unstable,
+ * before being passed to renderDataGridRow_unstable.
+ *
+ * @param props - props from this instance of DataGridRow
+ * @param ref - reference to root HTMLElement of DataGridRow
+ */
+export const useDataGridRow_unstable = (props: DataGridRowProps, ref: React.Ref): DataGridRowState => {
+ const rowIndex = useTableRowIndexContext();
+ return useBaseState({ ...props, 'aria-rowindex': rowIndex }, ref);
+};
diff --git a/packages/react-components/react-data-grid-react-window/src/contexts/rowIndexContext.ts b/packages/react-components/react-data-grid-react-window/src/contexts/rowIndexContext.ts
new file mode 100644
index 00000000000000..6ff39e8372cba0
--- /dev/null
+++ b/packages/react-components/react-data-grid-react-window/src/contexts/rowIndexContext.ts
@@ -0,0 +1,9 @@
+import * as React from 'react';
+
+const rowIndexContext = React.createContext(undefined);
+
+export const tableRowIndexContextDefaultValue = undefined;
+
+export const useTableRowIndexContext = () => React.useContext(rowIndexContext) ?? tableRowIndexContextDefaultValue;
+
+export const TableRowIndexContextProvider = rowIndexContext.Provider;
diff --git a/packages/react-components/react-data-grid-react-window/src/index.ts b/packages/react-components/react-data-grid-react-window/src/index.ts
index c3328a9b2c49b4..de176daf4b3443 100644
--- a/packages/react-components/react-data-grid-react-window/src/index.ts
+++ b/packages/react-components/react-data-grid-react-window/src/index.ts
@@ -1,3 +1,16 @@
-export { DataGridBody, useDataGridBody_unstable, renderDataGridBody_unstable } from './DataGridBody';
+export { DataGridBody } from './DataGridBody';
+export { DataGrid } from './DataGrid';
+export { DataGridRow } from './DataGridRow';
-export type { DataGridBodyProps, DataGridBodyState, DataGridBodySlots } from './DataGridBody';
+export { DataGridCell, DataGridHeader, DataGridHeaderCell, DataGridSelectionCell } from '@fluentui/react-table';
+
+export type {
+ DataGridCellProps,
+ DataGridHeaderCellProps,
+ DataGridHeaderProps,
+ DataGridSelectionCellProps,
+ DataGridRowProps,
+ DataGridProps,
+} from '@fluentui/react-table';
+
+export type { DataGridBodyProps } from './DataGridBody';
diff --git a/packages/react-components/react-table/etc/react-table.api.md b/packages/react-components/react-table/etc/react-table.api.md
index d23e10b88c72d1..234f8f11403f7e 100644
--- a/packages/react-components/react-table/etc/react-table.api.md
+++ b/packages/react-components/react-table/etc/react-table.api.md
@@ -545,6 +545,9 @@ export const useDataGridCell_unstable: (props: DataGridCellProps, ref: React_2.R
// @public
export const useDataGridCellStyles_unstable: (state: DataGridCellState) => DataGridCellState;
+// @public (undocumented)
+export function useDataGridContextValues_unstable(state: DataGridState): DataGridContextValues;
+
// @public
export const useDataGridHeader_unstable: (props: DataGridHeaderProps, ref: React_2.Ref) => DataGridHeaderState;
diff --git a/packages/react-components/react-table/src/components/DataGrid/index.ts b/packages/react-components/react-table/src/components/DataGrid/index.ts
index 6906263be7ae7b..f421b8aa7c5534 100644
--- a/packages/react-components/react-table/src/components/DataGrid/index.ts
+++ b/packages/react-components/react-table/src/components/DataGrid/index.ts
@@ -3,3 +3,4 @@ export * from './DataGrid.types';
export * from './renderDataGrid';
export * from './useDataGrid';
export * from './useDataGridStyles';
+export * from './useDataGridContextValues';
diff --git a/packages/react-components/react-table/src/index.ts b/packages/react-components/react-table/src/index.ts
index d162af3a1d39e9..bc387da8b5edc6 100644
--- a/packages/react-components/react-table/src/index.ts
+++ b/packages/react-components/react-table/src/index.ts
@@ -151,6 +151,7 @@ export {
useDataGridStyles_unstable,
useDataGrid_unstable,
renderDataGrid_unstable,
+ useDataGridContextValues_unstable,
} from './DataGrid';
export type {
DataGridProps,
diff --git a/packages/react-components/react-table/stories/DataGrid/Virtualization.stories.tsx b/packages/react-components/react-table/stories/DataGrid/Virtualization.stories.tsx
index 8f19b8a2785a21..117c799f8e8229 100644
--- a/packages/react-components/react-table/stories/DataGrid/Virtualization.stories.tsx
+++ b/packages/react-components/react-table/stories/DataGrid/Virtualization.stories.tsx
@@ -9,17 +9,15 @@ import {
VideoRegular,
} from '@fluentui/react-icons';
import { PresenceBadgeStatus, Avatar, useScrollbarWidth, useFluent } from '@fluentui/react-components';
+import { TableColumnDefinition, createTableColumn, TableCellLayout } from '@fluentui/react-components/unstable';
import {
- DataGridRow,
+ DataGridBody,
DataGrid,
+ DataGridRow,
DataGridHeader,
- DataGridHeaderCell,
DataGridCell,
- TableColumnDefinition,
- createTableColumn,
- TableCellLayout,
-} from '@fluentui/react-components/unstable';
-import { DataGridBody } from '@fluentui/react-data-grid-react-window';
+ DataGridHeaderCell,
+} from '@fluentui/react-data-grid-react-window';
type FileCell = {
label: string;
@@ -170,3 +168,18 @@ export const Virtualization = () => {
);
};
+
+Virtualization.parameters = {
+ docs: {
+ description: {
+ story: [
+ 'Virtualizating the DataGrid component involves recomposing components to use a virtualized container.',
+ 'This is already done in the extension package `@fluentui/react-data-grid-react-window` which provides',
+ 'extended DataGrid components that are powered',
+ 'by [react-window](https://react-window.vercel.app/#/examples/list/fixed-size).',
+ '',
+ 'The example below shows how to use this extension package to virtualize the DataGrid component.',
+ ].join('\n'),
+ },
+ },
+};
diff --git a/scripts/storybook/src/utils.js b/scripts/storybook/src/utils.js
index c1c10f89b71d6c..be565404addf08 100644
--- a/scripts/storybook/src/utils.js
+++ b/scripts/storybook/src/utils.js
@@ -159,7 +159,7 @@ function _createCodesandboxRule(allPackageInfo = getAllPackageInfo()) {
* @returns {import('storybook-addon-export-to-codesandbox').BabelPluginOptions}
*/
function getCodesandboxBabelOptions() {
- return Object.values(allPackageInfo).reduce((acc, cur) => {
+ const importMappings = Object.values(allPackageInfo).reduce((acc, cur) => {
if (isConvergedPackage({ packagePathOrJson: cur.packageJson, projectType: 'library' })) {
const isPrerelease = semver.prerelease(cur.packageJson.version) !== null;
@@ -170,6 +170,13 @@ function _createCodesandboxRule(allPackageInfo = getAllPackageInfo()) {
return acc;
}, /** @type import('storybook-addon-export-to-codesandbox').BabelPluginOptions*/ ({}));
+
+ return {
+ ...importMappings,
+ '@fluentui/react-data-grid-react-window': {
+ replace: '@fluentui/react-data-grid-react-window',
+ },
+ };
}
}