@multiplatform.one/table 6.4.2 → 6.6.0
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/cjs/components/ChildTable/index.native.js +1 -1
- package/dist/cjs/components/ChildTable/index.native.js.map +1 -1
- package/dist/cjs/components/ColumnHeaderFilter/index.cjs +1 -0
- package/dist/cjs/components/ColumnHeaderFilter/index.native.js +2 -1
- package/dist/cjs/components/ColumnHeaderFilter/index.native.js.map +1 -1
- package/dist/cjs/components/DataTable/DataTableCardControls.native.js +1 -1
- package/dist/cjs/components/DataTable/DataTableCardControls.native.js.map +1 -1
- package/dist/cjs/components/DataTable/DataTableContext.native.js.map +1 -1
- package/dist/cjs/components/DataTable/DataTableMobileCards.cjs +9 -3
- package/dist/cjs/components/DataTable/DataTableMobileCards.native.js +12 -3
- package/dist/cjs/components/DataTable/DataTableMobileCards.native.js.map +1 -1
- package/dist/cjs/components/DataTable/DataTableRoot.cjs +133 -13
- package/dist/cjs/components/DataTable/DataTableRoot.native.js +166 -20
- package/dist/cjs/components/DataTable/DataTableRoot.native.js.map +1 -1
- package/dist/cjs/components/DataTable/DataTableStateContext.native.js.map +1 -1
- package/dist/cjs/components/DataTable/DataTableVirtualized.cjs +3 -1
- package/dist/cjs/components/DataTable/DataTableVirtualized.native.js +3 -1
- package/dist/cjs/components/DataTable/DataTableVirtualized.native.js.map +1 -1
- package/dist/cjs/components/DataTable/index.native.js +50 -13
- package/dist/cjs/components/DataTable/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableBulkActions/index.cjs +16 -1
- package/dist/cjs/components/DataTableBulkActions/index.native.js +20 -1
- package/dist/cjs/components/DataTableBulkActions/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableCell/CellModalEditor.cjs +4 -8
- package/dist/cjs/components/DataTableCell/CellOptionsEditor.native.js.map +1 -1
- package/dist/cjs/components/DataTableCell/index.cjs +1 -33
- package/dist/cjs/components/DataTableCell/index.native.js +1 -34
- package/dist/cjs/components/DataTableCell/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableColumnPinning/index.cjs +2 -2
- package/dist/cjs/components/DataTableColumnPinning/index.native.js +2 -2
- package/dist/cjs/components/DataTableColumnPinning/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableDateFilter/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableExport/index.cjs +1 -0
- package/dist/cjs/components/DataTableExport/index.native.js +1 -0
- package/dist/cjs/components/DataTableExport/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableFilterButton/index.cjs +1 -1
- package/dist/cjs/components/DataTableFilterButton/index.native.js +5 -2
- package/dist/cjs/components/DataTableFilterButton/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableFilterChips/index.cjs +1 -1
- package/dist/cjs/components/DataTableFilterChips/index.native.js +1 -1
- package/dist/cjs/components/DataTableFilterChips/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableFilters/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableGrouping/index.cjs +17 -1
- package/dist/cjs/components/DataTableGrouping/index.native.js +17 -1
- package/dist/cjs/components/DataTableGrouping/index.native.js.map +1 -1
- package/dist/cjs/components/DataTablePagination/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableSearch/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableToolbar/index.cjs +1 -0
- package/dist/cjs/components/DataTableToolbar/index.native.js +2 -1
- package/dist/cjs/components/DataTableToolbar/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableViewOptions/index.native.js.map +1 -1
- package/dist/cjs/components/FilterManager.cjs +18 -14
- package/dist/cjs/components/FilterManager.native.js +18 -14
- package/dist/cjs/components/FilterManager.native.js.map +1 -1
- package/dist/cjs/components/FilterOperatorValueEditor/index.native.js.map +1 -1
- package/dist/cjs/components/KnobDialog.native.js.map +1 -1
- package/dist/cjs/components/SavedFilterDropdown.native.js.map +1 -1
- package/dist/cjs/components/SimpleTable/index.cjs +1 -1
- package/dist/cjs/components/SimpleTable/index.native.js +1 -1
- package/dist/cjs/components/SimpleTable/index.native.js.map +1 -1
- package/dist/cjs/components/TableInput/index.native.js +4 -1
- package/dist/cjs/components/TableInput/index.native.js.map +1 -1
- package/dist/cjs/components/TableInput/shared.native.js.map +1 -1
- package/dist/cjs/hooks/useDataTable.cjs +17 -1
- package/dist/cjs/hooks/useDataTable.native.js +19 -1
- package/dist/cjs/hooks/useDataTable.native.js.map +1 -1
- package/dist/cjs/hooks/useDataTableKeyboard.native.js.map +1 -1
- package/dist/cjs/hooks/useDragScroll.native.js.map +1 -1
- package/dist/cjs/hooks/useInfiniteRows.native.js.map +1 -1
- package/dist/cjs/hooks/useSavedFilters.native.js.map +1 -1
- package/dist/cjs/hooks/useTableColumnPinning.native.js.map +1 -1
- package/dist/cjs/hooks/useTableFiltering.native.js.map +1 -1
- package/dist/cjs/hooks/useTableGrouping.native.js.map +1 -1
- package/dist/cjs/hooks/useTableKeyboard.native.js.map +1 -1
- package/dist/cjs/hooks/useTablePagination.native.js.map +1 -1
- package/dist/cjs/hooks/useTableSearch.native.js.map +1 -1
- package/dist/cjs/hooks/useTableSelection.native.js.map +1 -1
- package/dist/cjs/hooks/useTableSorting.native.js.map +1 -1
- package/dist/cjs/hooks/useTableUrlSync.native.js.map +1 -1
- package/dist/cjs/hooks/useTableViews.native.js.map +1 -1
- package/dist/cjs/shared/t.native.js.map +1 -1
- package/dist/cjs/shims/primitives.native.js.map +1 -1
- package/dist/cjs/shims/tableCellContext.native.js.map +1 -1
- package/dist/cjs/types.native.js.map +1 -1
- package/dist/cjs/utils/columnAlign.native.js.map +1 -1
- package/dist/cjs/utils/filterFields.native.js.map +1 -1
- package/dist/cjs/utils/filterUtils.native.js.map +1 -1
- package/dist/cjs/utils/paginationDefaults.native.js.map +1 -1
- package/dist/cjs/utils/rowPress.cjs +44 -0
- package/dist/cjs/utils/rowPress.native.js +56 -0
- package/dist/cjs/utils/rowPress.native.js.map +1 -0
- package/dist/cjs/utils/urlStateUtils.native.js.map +1 -1
- package/dist/cjs/utils/viewData.native.js.map +1 -1
- package/dist/cjs/utils/withInterp.native.js.map +1 -1
- package/dist/esm/components/ColumnHeaderFilter/index.mjs +1 -0
- package/dist/esm/components/ColumnHeaderFilter/index.mjs.map +1 -1
- package/dist/esm/components/ColumnHeaderFilter/index.native.js +1 -0
- package/dist/esm/components/ColumnHeaderFilter/index.native.js.map +1 -1
- package/dist/esm/components/DataTable/DataTableMobileCards.mjs +9 -3
- package/dist/esm/components/DataTable/DataTableMobileCards.mjs.map +1 -1
- package/dist/esm/components/DataTable/DataTableMobileCards.native.js +12 -3
- package/dist/esm/components/DataTable/DataTableMobileCards.native.js.map +1 -1
- package/dist/esm/components/DataTable/DataTableRoot.mjs +133 -13
- package/dist/esm/components/DataTable/DataTableRoot.mjs.map +1 -1
- package/dist/esm/components/DataTable/DataTableRoot.native.js +159 -13
- package/dist/esm/components/DataTable/DataTableRoot.native.js.map +1 -1
- package/dist/esm/components/DataTable/DataTableVirtualized.mjs +3 -1
- package/dist/esm/components/DataTable/DataTableVirtualized.mjs.map +1 -1
- package/dist/esm/components/DataTable/DataTableVirtualized.native.js +3 -1
- package/dist/esm/components/DataTable/DataTableVirtualized.native.js.map +1 -1
- package/dist/esm/components/DataTable/index.native.js +40 -3
- package/dist/esm/components/DataTable/index.native.js.map +1 -1
- package/dist/esm/components/DataTableBulkActions/index.mjs +16 -1
- package/dist/esm/components/DataTableBulkActions/index.mjs.map +1 -1
- package/dist/esm/components/DataTableBulkActions/index.native.js +20 -1
- package/dist/esm/components/DataTableBulkActions/index.native.js.map +1 -1
- package/dist/esm/components/DataTableCell/CellModalEditor.mjs +4 -8
- package/dist/esm/components/DataTableCell/CellModalEditor.mjs.map +1 -1
- package/dist/esm/components/DataTableCell/index.mjs +1 -33
- package/dist/esm/components/DataTableCell/index.mjs.map +1 -1
- package/dist/esm/components/DataTableCell/index.native.js +1 -34
- package/dist/esm/components/DataTableCell/index.native.js.map +1 -1
- package/dist/esm/components/DataTableColumnPinning/index.mjs +2 -2
- package/dist/esm/components/DataTableColumnPinning/index.mjs.map +1 -1
- package/dist/esm/components/DataTableColumnPinning/index.native.js +2 -2
- package/dist/esm/components/DataTableColumnPinning/index.native.js.map +1 -1
- package/dist/esm/components/DataTableExport/index.mjs +1 -0
- package/dist/esm/components/DataTableExport/index.mjs.map +1 -1
- package/dist/esm/components/DataTableExport/index.native.js +1 -0
- package/dist/esm/components/DataTableExport/index.native.js.map +1 -1
- package/dist/esm/components/DataTableFilterButton/index.mjs +1 -1
- package/dist/esm/components/DataTableFilterButton/index.mjs.map +1 -1
- package/dist/esm/components/DataTableFilterButton/index.native.js +4 -1
- package/dist/esm/components/DataTableFilterButton/index.native.js.map +1 -1
- package/dist/esm/components/DataTableFilterChips/index.mjs +1 -1
- package/dist/esm/components/DataTableFilterChips/index.mjs.map +1 -1
- package/dist/esm/components/DataTableFilterChips/index.native.js +1 -1
- package/dist/esm/components/DataTableGrouping/index.mjs +18 -3
- package/dist/esm/components/DataTableGrouping/index.mjs.map +1 -1
- package/dist/esm/components/DataTableGrouping/index.native.js +18 -3
- package/dist/esm/components/DataTableGrouping/index.native.js.map +1 -1
- package/dist/esm/components/DataTableToolbar/index.mjs +1 -0
- package/dist/esm/components/DataTableToolbar/index.mjs.map +1 -1
- package/dist/esm/components/DataTableToolbar/index.native.js +1 -0
- package/dist/esm/components/DataTableToolbar/index.native.js.map +1 -1
- package/dist/esm/components/FilterManager.mjs +18 -14
- package/dist/esm/components/FilterManager.mjs.map +1 -1
- package/dist/esm/components/FilterManager.native.js +18 -14
- package/dist/esm/components/FilterManager.native.js.map +1 -1
- package/dist/esm/components/SimpleTable/index.mjs +1 -1
- package/dist/esm/components/SimpleTable/index.mjs.map +1 -1
- package/dist/esm/components/SimpleTable/index.native.js +1 -1
- package/dist/esm/components/TableInput/index.native.js +3 -0
- package/dist/esm/components/TableInput/index.native.js.map +1 -1
- package/dist/esm/hooks/useDataTable.mjs +17 -1
- package/dist/esm/hooks/useDataTable.mjs.map +1 -1
- package/dist/esm/hooks/useDataTable.native.js +19 -1
- package/dist/esm/hooks/useDataTable.native.js.map +1 -1
- package/dist/esm/hooks/useTableGrouping.mjs.map +1 -1
- package/dist/esm/utils/rowPress.mjs +19 -0
- package/dist/esm/utils/rowPress.mjs.map +1 -0
- package/dist/esm/utils/rowPress.native.js +28 -0
- package/dist/esm/utils/rowPress.native.js.map +1 -0
- package/dist/jsx/components/ColumnHeaderFilter/index.mjs +1 -0
- package/dist/jsx/components/ColumnHeaderFilter/index.mjs.map +1 -1
- package/dist/jsx/components/ColumnHeaderFilter/index.native.js +1 -0
- package/dist/jsx/components/ColumnHeaderFilter/index.native.js.map +1 -1
- package/dist/jsx/components/DataTable/DataTableMobileCards.mjs +9 -3
- package/dist/jsx/components/DataTable/DataTableMobileCards.mjs.map +1 -1
- package/dist/jsx/components/DataTable/DataTableMobileCards.native.js +12 -3
- package/dist/jsx/components/DataTable/DataTableMobileCards.native.js.map +1 -1
- package/dist/jsx/components/DataTable/DataTableRoot.mjs +133 -13
- package/dist/jsx/components/DataTable/DataTableRoot.mjs.map +1 -1
- package/dist/jsx/components/DataTable/DataTableRoot.native.js +159 -13
- package/dist/jsx/components/DataTable/DataTableRoot.native.js.map +1 -1
- package/dist/jsx/components/DataTable/DataTableVirtualized.mjs +3 -1
- package/dist/jsx/components/DataTable/DataTableVirtualized.mjs.map +1 -1
- package/dist/jsx/components/DataTable/DataTableVirtualized.native.js +3 -1
- package/dist/jsx/components/DataTable/DataTableVirtualized.native.js.map +1 -1
- package/dist/jsx/components/DataTable/index.native.js +40 -3
- package/dist/jsx/components/DataTable/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableBulkActions/index.mjs +16 -1
- package/dist/jsx/components/DataTableBulkActions/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableBulkActions/index.native.js +20 -1
- package/dist/jsx/components/DataTableBulkActions/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableCell/CellModalEditor.mjs +4 -8
- package/dist/jsx/components/DataTableCell/CellModalEditor.mjs.map +1 -1
- package/dist/jsx/components/DataTableCell/index.mjs +1 -33
- package/dist/jsx/components/DataTableCell/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableCell/index.native.js +1 -34
- package/dist/jsx/components/DataTableCell/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableColumnPinning/index.mjs +2 -2
- package/dist/jsx/components/DataTableColumnPinning/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableColumnPinning/index.native.js +2 -2
- package/dist/jsx/components/DataTableColumnPinning/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableExport/index.mjs +1 -0
- package/dist/jsx/components/DataTableExport/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableExport/index.native.js +1 -0
- package/dist/jsx/components/DataTableExport/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableFilterButton/index.mjs +1 -1
- package/dist/jsx/components/DataTableFilterButton/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableFilterButton/index.native.js +4 -1
- package/dist/jsx/components/DataTableFilterButton/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableFilterChips/index.mjs +1 -1
- package/dist/jsx/components/DataTableFilterChips/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableFilterChips/index.native.js +1 -1
- package/dist/jsx/components/DataTableGrouping/index.mjs +18 -3
- package/dist/jsx/components/DataTableGrouping/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableGrouping/index.native.js +17 -1
- package/dist/jsx/components/DataTableGrouping/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableToolbar/index.mjs +1 -0
- package/dist/jsx/components/DataTableToolbar/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableToolbar/index.native.js +1 -0
- package/dist/jsx/components/DataTableToolbar/index.native.js.map +1 -1
- package/dist/jsx/components/FilterManager.mjs +18 -14
- package/dist/jsx/components/FilterManager.mjs.map +1 -1
- package/dist/jsx/components/FilterManager.native.js +18 -14
- package/dist/jsx/components/FilterManager.native.js.map +1 -1
- package/dist/jsx/components/SimpleTable/index.mjs +1 -1
- package/dist/jsx/components/SimpleTable/index.mjs.map +1 -1
- package/dist/jsx/components/SimpleTable/index.native.js +1 -1
- package/dist/jsx/components/SimpleTable/index.native.js.map +1 -1
- package/dist/jsx/components/TableInput/index.native.js +3 -0
- package/dist/jsx/components/TableInput/index.native.js.map +1 -1
- package/dist/jsx/hooks/useDataTable.mjs +17 -1
- package/dist/jsx/hooks/useDataTable.mjs.map +1 -1
- package/dist/jsx/hooks/useDataTable.native.js +19 -1
- package/dist/jsx/hooks/useDataTable.native.js.map +1 -1
- package/dist/jsx/hooks/useTableGrouping.mjs.map +1 -1
- package/dist/jsx/utils/rowPress.mjs +19 -0
- package/dist/jsx/utils/rowPress.mjs.map +1 -0
- package/dist/jsx/utils/rowPress.native.js +56 -0
- package/dist/jsx/utils/rowPress.native.js.map +1 -0
- package/package.json +12 -12
- package/src/components/ColumnHeaderFilter/index.tsx +1 -0
- package/src/components/DataTable/DataTable.spec.tsx +4 -1
- package/src/components/DataTable/DataTable.stories.tsx +190 -5
- package/src/components/DataTable/DataTableMobileCards.tsx +30 -4
- package/src/components/DataTable/DataTableRoot.tsx +195 -8
- package/src/components/DataTable/DataTableVirtualized.tsx +8 -0
- package/src/components/DataTable/cardLayout.spec.tsx +4 -1
- package/src/components/DataTable/customCellAlign.spec.tsx +124 -0
- package/src/components/DataTable/disabledContract.spec.tsx +4 -3
- package/src/components/DataTable/index.native.tsx +47 -1
- package/src/components/DataTable/rowPress.spec.tsx +229 -0
- package/src/components/DataTable/selectionSemantics.spec.tsx +156 -0
- package/src/components/DataTableBulkActions/index.tsx +16 -2
- package/src/components/DataTableBulkActions/selectionCountI18n.spec.tsx +94 -0
- package/src/components/DataTableCell/CellModalEditor.tsx +3 -1
- package/src/components/DataTableCell/DataTableCell.stories.tsx +1 -5
- package/src/components/DataTableCell/cellDraftPolicy.spec.tsx +10 -2
- package/src/components/DataTableCell/dataTableCell.spec.tsx +10 -2
- package/src/components/DataTableCell/index.tsx +5 -36
- package/src/components/DataTableColumnPinning/DataTableColumnPinning.stories.tsx +49 -17
- package/src/components/DataTableDateFilter/DataTableDateFilter.stories.tsx +4 -3
- package/src/components/DataTableExport/DataTableExport.stories.tsx +3 -2
- package/src/components/DataTableExport/index.tsx +1 -0
- package/src/components/DataTableFilterButton/index.tsx +4 -1
- package/src/components/DataTableGrouping/DataTableGrouping.spec.tsx +59 -2
- package/src/components/DataTableGrouping/DataTableGrouping.stories.tsx +17 -5
- package/src/components/DataTableGrouping/index.tsx +1 -0
- package/src/components/DataTablePagination/DataTablePagination.stories.tsx +34 -20
- package/src/components/DataTableToolbar/index.tsx +1 -0
- package/src/components/DataTableViewOptions/DataTableViewOptions.stories.tsx +2 -1
- package/src/components/FilterManager.tsx +21 -13
- package/src/components/TableInput/index.native.tsx +3 -0
- package/src/components/__scratch__/scratch.spec.tsx +46 -0
- package/src/hooks/useDataTable.ts +27 -1
- package/src/types.ts +25 -0
- package/src/utils/rowPress.ts +58 -0
- package/types/components/ColumnHeaderFilter/index.d.ts.map +1 -1
- package/types/components/DataTable/DataTableMobileCards.d.ts +13 -1
- package/types/components/DataTable/DataTableMobileCards.d.ts.map +1 -1
- package/types/components/DataTable/DataTableRoot.d.ts +1 -1
- package/types/components/DataTable/DataTableRoot.d.ts.map +1 -1
- package/types/components/DataTable/DataTableVirtualized.d.ts +7 -1
- package/types/components/DataTable/DataTableVirtualized.d.ts.map +1 -1
- package/types/components/DataTable/index.native.d.ts +1 -1
- package/types/components/DataTable/index.native.d.ts.map +1 -1
- package/types/components/DataTableBulkActions/index.d.ts.map +1 -1
- package/types/components/DataTableCell/CellModalEditor.d.ts.map +1 -1
- package/types/components/DataTableCell/index.d.ts.map +1 -1
- package/types/components/DataTableColumnPinning/index.d.ts.map +1 -1
- package/types/components/DataTableFilterButton/index.d.ts.map +1 -1
- package/types/components/DataTableGrouping/index.d.ts +8 -0
- package/types/components/DataTableGrouping/index.d.ts.map +1 -1
- package/types/components/DataTableToolbar/index.d.ts.map +1 -1
- package/types/components/FilterManager.d.ts +7 -1
- package/types/components/FilterManager.d.ts.map +1 -1
- package/types/components/TableInput/index.native.d.ts.map +1 -1
- package/types/hooks/useDataTable.d.ts.map +1 -1
- package/types/types.d.ts +23 -0
- package/types/types.d.ts.map +1 -1
- package/types/utils/rowPress.d.ts +20 -0
- package/types/utils/rowPress.d.ts.map +1 -0
|
@@ -2,8 +2,14 @@ import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
|
|
|
2
2
|
import { fn } from "storybook/test";
|
|
3
3
|
import { createColumnHelper } from "@tanstack/react-table";
|
|
4
4
|
import React, { useMemo } from "react";
|
|
5
|
+
import {
|
|
6
|
+
formatAbsoluteDate,
|
|
7
|
+
formatCurrency,
|
|
8
|
+
type GuardrailSpecimenParameter,
|
|
9
|
+
} from "@multiplatform.one/theme";
|
|
5
10
|
import { Button } from "@multiplatform.one/forms";
|
|
6
|
-
import { Avatar
|
|
11
|
+
import { Avatar } from "@multiplatform.one/components";
|
|
12
|
+
import { Text, View, YStack } from "tamagui";
|
|
7
13
|
import {
|
|
8
14
|
type DataTableColumn,
|
|
9
15
|
type DataTableData,
|
|
@@ -84,7 +90,7 @@ const columns: DataTableColumn<User>[] = [
|
|
|
84
90
|
columnHelper.accessor("avatar", {
|
|
85
91
|
header: "Avatar",
|
|
86
92
|
cell: (info) => (
|
|
87
|
-
<Avatar circular size="$3">
|
|
93
|
+
<Avatar circular size="$3" backgroundColor="$gray6">
|
|
88
94
|
<Avatar.Image alt="User avatar" src={info.getValue()} />
|
|
89
95
|
<Avatar.Fallback backgroundColor="$gray6" />
|
|
90
96
|
</Avatar>
|
|
@@ -143,7 +149,11 @@ const columns: DataTableColumn<User>[] = [
|
|
|
143
149
|
// Salary Column
|
|
144
150
|
columnHelper.accessor("salary", {
|
|
145
151
|
header: "Salary",
|
|
146
|
-
cell: (info) =>
|
|
152
|
+
cell: (info) => (
|
|
153
|
+
<Text>
|
|
154
|
+
{formatCurrency(info.getValue() as number, { symbol: "$", fractionDigits: "auto" })}
|
|
155
|
+
</Text>
|
|
156
|
+
),
|
|
147
157
|
filterFn: "inNumberRange",
|
|
148
158
|
}) as DataTableColumn<User>,
|
|
149
159
|
|
|
@@ -179,14 +189,14 @@ const columns: DataTableColumn<User>[] = [
|
|
|
179
189
|
// Join Date Column
|
|
180
190
|
columnHelper.accessor("joinDate", {
|
|
181
191
|
header: "Join Date",
|
|
182
|
-
cell: (info) => <Text>{
|
|
192
|
+
cell: (info) => <Text>{formatAbsoluteDate(info.getValue() as string)}</Text>,
|
|
183
193
|
filterFn: "includesString",
|
|
184
194
|
}) as DataTableColumn<User>,
|
|
185
195
|
|
|
186
196
|
// Last Login Column
|
|
187
197
|
columnHelper.accessor("lastLogin", {
|
|
188
198
|
header: "Last Login",
|
|
189
|
-
cell: (info) => <Text>{
|
|
199
|
+
cell: (info) => <Text>{formatAbsoluteDate(info.getValue() as string)}</Text>,
|
|
190
200
|
filterFn: "includesString",
|
|
191
201
|
}) as DataTableColumn<User>,
|
|
192
202
|
|
|
@@ -802,10 +812,14 @@ const editableColumns: DataTableColumn<EditablePerson>[] = [
|
|
|
802
812
|
header: "Category",
|
|
803
813
|
field: "select",
|
|
804
814
|
fieldProps: {
|
|
815
|
+
// >5 options: shorter single-select lists trip `select-too-few-options` (DG-CTRL-01).
|
|
805
816
|
options: [
|
|
806
817
|
{ label: "Electronics", value: "electronics" },
|
|
807
818
|
{ label: "Clothing", value: "clothing" },
|
|
808
819
|
{ label: "Food", value: "food" },
|
|
820
|
+
{ label: "Books", value: "books" },
|
|
821
|
+
{ label: "Toys", value: "toys" },
|
|
822
|
+
{ label: "Garden", value: "garden" },
|
|
809
823
|
],
|
|
810
824
|
},
|
|
811
825
|
},
|
|
@@ -858,6 +872,15 @@ export const EditableTable: Story = {
|
|
|
858
872
|
* state (see ReadOnly).
|
|
859
873
|
*/
|
|
860
874
|
export const Disabled: Story = {
|
|
875
|
+
parameters: {
|
|
876
|
+
// LC-57 allowlist: this story IS the whole-table disabled-dial demo — every
|
|
877
|
+
// piece of chrome rests disabled by design, and per-control reasons would
|
|
878
|
+
// say nothing beyond what the story title already does.
|
|
879
|
+
guardrailSpecimen: {
|
|
880
|
+
warns: ["bare-disabled"],
|
|
881
|
+
reason: "Disabled-dial specimen: the entire table (all chrome) rests disabled by design.",
|
|
882
|
+
} satisfies GuardrailSpecimenParameter,
|
|
883
|
+
},
|
|
861
884
|
args: {
|
|
862
885
|
data: editableData as unknown as Record<string, any>[],
|
|
863
886
|
columns: editableColumns as DataTableColumn<Record<string, any>>[],
|
|
@@ -1278,6 +1301,7 @@ const selectFieldData: SelectFieldRow[] = [
|
|
|
1278
1301
|
{ id: 3, category: "food", priority: "low", status: "inactive" },
|
|
1279
1302
|
];
|
|
1280
1303
|
|
|
1304
|
+
// >5 options per list: shorter single-select lists trip `select-too-few-options` (DG-CTRL-01).
|
|
1281
1305
|
const selectFieldColumns: DataTableColumn<SelectFieldRow>[] = [
|
|
1282
1306
|
{
|
|
1283
1307
|
accessorKey: "category",
|
|
@@ -1288,6 +1312,9 @@ const selectFieldColumns: DataTableColumn<SelectFieldRow>[] = [
|
|
|
1288
1312
|
{ label: "Electronics", value: "electronics" },
|
|
1289
1313
|
{ label: "Clothing", value: "clothing" },
|
|
1290
1314
|
{ label: "Food", value: "food" },
|
|
1315
|
+
{ label: "Books", value: "books" },
|
|
1316
|
+
{ label: "Toys", value: "toys" },
|
|
1317
|
+
{ label: "Garden", value: "garden" },
|
|
1291
1318
|
],
|
|
1292
1319
|
},
|
|
1293
1320
|
},
|
|
@@ -1297,9 +1324,12 @@ const selectFieldColumns: DataTableColumn<SelectFieldRow>[] = [
|
|
|
1297
1324
|
field: "select",
|
|
1298
1325
|
fieldProps: {
|
|
1299
1326
|
options: [
|
|
1327
|
+
{ label: "Highest", value: "highest" },
|
|
1300
1328
|
{ label: "High", value: "high" },
|
|
1301
1329
|
{ label: "Medium", value: "medium" },
|
|
1302
1330
|
{ label: "Low", value: "low" },
|
|
1331
|
+
{ label: "Lowest", value: "lowest" },
|
|
1332
|
+
{ label: "Deferred", value: "deferred" },
|
|
1303
1333
|
],
|
|
1304
1334
|
},
|
|
1305
1335
|
},
|
|
@@ -1312,6 +1342,9 @@ const selectFieldColumns: DataTableColumn<SelectFieldRow>[] = [
|
|
|
1312
1342
|
{ label: "Active", value: "active" },
|
|
1313
1343
|
{ label: "Pending", value: "pending" },
|
|
1314
1344
|
{ label: "Inactive", value: "inactive" },
|
|
1345
|
+
{ label: "Draft", value: "draft" },
|
|
1346
|
+
{ label: "Archived", value: "archived" },
|
|
1347
|
+
{ label: "Blocked", value: "blocked" },
|
|
1315
1348
|
],
|
|
1316
1349
|
},
|
|
1317
1350
|
},
|
|
@@ -2105,12 +2138,14 @@ const searchableColumns: DataTableColumn<SearchableRow>[] = [
|
|
|
2105
2138
|
header: "Department",
|
|
2106
2139
|
field: "select",
|
|
2107
2140
|
fieldProps: {
|
|
2141
|
+
// >5 options: shorter single-select lists trip `select-too-few-options` (DG-CTRL-01).
|
|
2108
2142
|
options: [
|
|
2109
2143
|
{ label: "Engineering", value: "Engineering" },
|
|
2110
2144
|
{ label: "Marketing", value: "Marketing" },
|
|
2111
2145
|
{ label: "Sales", value: "Sales" },
|
|
2112
2146
|
{ label: "HR", value: "HR" },
|
|
2113
2147
|
{ label: "Finance", value: "Finance" },
|
|
2148
|
+
{ label: "Legal", value: "Legal" },
|
|
2114
2149
|
],
|
|
2115
2150
|
},
|
|
2116
2151
|
},
|
|
@@ -2773,10 +2808,14 @@ const hiddenFilterColumns: DataTableColumn<User>[] = [
|
|
|
2773
2808
|
header: "Status",
|
|
2774
2809
|
field: "select",
|
|
2775
2810
|
fieldProps: {
|
|
2811
|
+
// >5 options: shorter single-select lists trip `select-too-few-options` (DG-CTRL-01).
|
|
2776
2812
|
options: [
|
|
2777
2813
|
{ label: "Active", value: "active" },
|
|
2778
2814
|
{ label: "Inactive", value: "inactive" },
|
|
2779
2815
|
{ label: "Pending", value: "pending" },
|
|
2816
|
+
{ label: "Draft", value: "draft" },
|
|
2817
|
+
{ label: "Archived", value: "archived" },
|
|
2818
|
+
{ label: "Blocked", value: "blocked" },
|
|
2780
2819
|
],
|
|
2781
2820
|
},
|
|
2782
2821
|
},
|
|
@@ -2875,3 +2914,149 @@ const CompoundCompositionStory = () => {
|
|
|
2875
2914
|
export const CompoundComposition: Story = {
|
|
2876
2915
|
render: () => <CompoundCompositionStory />,
|
|
2877
2916
|
};
|
|
2917
|
+
|
|
2918
|
+
// ============================================================================
|
|
2919
|
+
// ROW PRESS (onRowPress — first-class row activation)
|
|
2920
|
+
// ============================================================================
|
|
2921
|
+
|
|
2922
|
+
/**
|
|
2923
|
+
* onRowPress makes each row ONE pressable unit (LC-49/LC-50): click/tap
|
|
2924
|
+
* anywhere in the row activates, the row set exposes a single roving tab
|
|
2925
|
+
* stop (ArrowUp/Down + Home/End move it, Enter AND Space activate), and
|
|
2926
|
+
* `rowLabel` names each row for AT. Inner interactive controls — the
|
|
2927
|
+
* selection checkboxes and the per-row Edit button here — stay isolated:
|
|
2928
|
+
* pressing them never fires the row press.
|
|
2929
|
+
*/
|
|
2930
|
+
const RowPressStory = () => {
|
|
2931
|
+
const data = useMemo(() => generateUsers(8), []);
|
|
2932
|
+
// Explicit ids on every column: DataTable seeds columnOrder from
|
|
2933
|
+
// `col.id || ""`, so mixing id-less accessor columns with id'd display
|
|
2934
|
+
// columns would reorder the id'd ones first.
|
|
2935
|
+
const rowPressColumns = useMemo<DataTableColumn<User>[]>(
|
|
2936
|
+
() => [
|
|
2937
|
+
{ id: "firstName", accessorKey: "firstName", header: "First Name" },
|
|
2938
|
+
{ id: "department", accessorKey: "department", header: "Department" },
|
|
2939
|
+
{
|
|
2940
|
+
id: "salary",
|
|
2941
|
+
accessorKey: "salary",
|
|
2942
|
+
header: "Salary",
|
|
2943
|
+
align: "right",
|
|
2944
|
+
cell: (info) => (
|
|
2945
|
+
<Text fontWeight="600">
|
|
2946
|
+
{formatCurrency(info.getValue() as number, { symbol: "$", fractionDigits: "auto" })}
|
|
2947
|
+
</Text>
|
|
2948
|
+
),
|
|
2949
|
+
},
|
|
2950
|
+
{
|
|
2951
|
+
id: "row_actions",
|
|
2952
|
+
header: "Actions",
|
|
2953
|
+
cell: () => (
|
|
2954
|
+
<Button size="$2" onPress={fn()}>
|
|
2955
|
+
Edit
|
|
2956
|
+
</Button>
|
|
2957
|
+
),
|
|
2958
|
+
},
|
|
2959
|
+
],
|
|
2960
|
+
[],
|
|
2961
|
+
);
|
|
2962
|
+
return (
|
|
2963
|
+
<DataTable
|
|
2964
|
+
data={data}
|
|
2965
|
+
columns={rowPressColumns as DataTableColumn<Record<string, any>>[]}
|
|
2966
|
+
enableRowSelection
|
|
2967
|
+
enableFiltering={false}
|
|
2968
|
+
enableGlobalSearch={false}
|
|
2969
|
+
enablePagination={false}
|
|
2970
|
+
onRowPress={fn()}
|
|
2971
|
+
rowLabel={(row) => (row as User).firstName}
|
|
2972
|
+
aria-label="Row press table"
|
|
2973
|
+
/>
|
|
2974
|
+
);
|
|
2975
|
+
};
|
|
2976
|
+
|
|
2977
|
+
export const RowPress: Story = {
|
|
2978
|
+
render: () => <RowPressStory />,
|
|
2979
|
+
parameters: {
|
|
2980
|
+
docs: {
|
|
2981
|
+
description: {
|
|
2982
|
+
story:
|
|
2983
|
+
'First-class row activation: `onRowPress(row, index)` fires on click/tap anywhere in a row and on Enter/Space while the row is focused. One roving tab stop per row set (LC-49), arrow keys move it, and inner controls (selection checkboxes, buttons) never trigger the row press. `rowLabel` names rows and their selection checkboxes ("Select row User3").',
|
|
2984
|
+
},
|
|
2985
|
+
},
|
|
2986
|
+
},
|
|
2987
|
+
};
|
|
2988
|
+
|
|
2989
|
+
// ============================================================================
|
|
2990
|
+
// CUSTOM-CELL ALIGNMENT (DG-TBL-01 for custom renderers)
|
|
2991
|
+
// ============================================================================
|
|
2992
|
+
|
|
2993
|
+
/**
|
|
2994
|
+
* Custom `cell` renderers inherit the column `align` through the table's
|
|
2995
|
+
* alignment container — no self-alignment. In the semantic-table
|
|
2996
|
+
* displayMode (columnLayout="auto") the cell box is display:table-cell
|
|
2997
|
+
* where flex justifyContent is a no-op; the wrapper restores the column
|
|
2998
|
+
* line for custom content (numerics share one right edge, LC-44).
|
|
2999
|
+
*/
|
|
3000
|
+
const CustomCellAlignmentStory = () => {
|
|
3001
|
+
const data = useMemo(() => generateUsers(6), []);
|
|
3002
|
+
const alignColumns = useMemo<DataTableColumn<User>[]>(
|
|
3003
|
+
() => [
|
|
3004
|
+
{
|
|
3005
|
+
id: "firstName",
|
|
3006
|
+
accessorKey: "firstName",
|
|
3007
|
+
header: "Name (left)",
|
|
3008
|
+
cell: (info) => <Text fontWeight="600">{String(info.getValue())}</Text>,
|
|
3009
|
+
},
|
|
3010
|
+
{
|
|
3011
|
+
id: "age",
|
|
3012
|
+
accessorKey: "age",
|
|
3013
|
+
header: "Age (right)",
|
|
3014
|
+
align: "right",
|
|
3015
|
+
cell: (info) => <Text>{String(info.getValue())}</Text>,
|
|
3016
|
+
},
|
|
3017
|
+
{
|
|
3018
|
+
id: "salary",
|
|
3019
|
+
accessorKey: "salary",
|
|
3020
|
+
header: "Salary (right)",
|
|
3021
|
+
align: "right",
|
|
3022
|
+
cell: (info) => (
|
|
3023
|
+
<Text fontWeight="600">
|
|
3024
|
+
{formatCurrency(info.getValue() as number, { symbol: "$", fractionDigits: "auto" })}
|
|
3025
|
+
</Text>
|
|
3026
|
+
),
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
id: "status",
|
|
3030
|
+
accessorKey: "status",
|
|
3031
|
+
header: "Status (center)",
|
|
3032
|
+
align: "center",
|
|
3033
|
+
cell: (info) => <Text>{String(info.getValue())}</Text>,
|
|
3034
|
+
},
|
|
3035
|
+
],
|
|
3036
|
+
[],
|
|
3037
|
+
);
|
|
3038
|
+
return (
|
|
3039
|
+
<DataTable
|
|
3040
|
+
data={data}
|
|
3041
|
+
columns={alignColumns as DataTableColumn<Record<string, any>>[]}
|
|
3042
|
+
columnLayout="auto"
|
|
3043
|
+
enableFiltering={false}
|
|
3044
|
+
enableGlobalSearch={false}
|
|
3045
|
+
enablePagination={false}
|
|
3046
|
+
readOnly
|
|
3047
|
+
aria-label="Custom cell alignment table"
|
|
3048
|
+
/>
|
|
3049
|
+
);
|
|
3050
|
+
};
|
|
3051
|
+
|
|
3052
|
+
export const CustomCellAlignment: Story = {
|
|
3053
|
+
render: () => <CustomCellAlignmentStory />,
|
|
3054
|
+
parameters: {
|
|
3055
|
+
docs: {
|
|
3056
|
+
description: {
|
|
3057
|
+
story:
|
|
3058
|
+
"Column `align` applies to CUSTOM cell renderers exactly like built-in field cells: the table wraps flexRender output in an alignment container (`data-cell-align`), so numeric custom cells right-align to one shared edge without any consumer alignment code.",
|
|
3059
|
+
},
|
|
3060
|
+
},
|
|
3061
|
+
},
|
|
3062
|
+
};
|
|
@@ -50,6 +50,18 @@ export interface DataTableMobileCardsProps<TData> {
|
|
|
50
50
|
selectAllIndeterminate?: boolean;
|
|
51
51
|
onToggleSelectAll?: () => void;
|
|
52
52
|
compact?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Accessible name for a row's selection checkbox ("Select row {identity}",
|
|
55
|
+
* built by DataTableRoot so cards and grid share one naming source).
|
|
56
|
+
*/
|
|
57
|
+
selectRowLabel?: (row: any, rowIndex: number) => string;
|
|
58
|
+
/**
|
|
59
|
+
* onRowPress support: press/keyboard/AT props for one pressable row
|
|
60
|
+
* (built by DataTableRoot). Cards live outside the table tree, so they
|
|
61
|
+
* take the `card` variant (role="button") with the same activation,
|
|
62
|
+
* roving focus, and inner-control isolation as grid rows.
|
|
63
|
+
*/
|
|
64
|
+
getRowPressProps?: (row: any, rowIndex: number, variant?: "row" | "card") => Record<string, any>;
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
export function DataTableMobileCards<TData extends Record<string, any>>({
|
|
@@ -68,6 +80,8 @@ export function DataTableMobileCards<TData extends Record<string, any>>({
|
|
|
68
80
|
selectAllIndeterminate = false,
|
|
69
81
|
onToggleSelectAll,
|
|
70
82
|
compact = false,
|
|
83
|
+
selectRowLabel,
|
|
84
|
+
getRowPressProps,
|
|
71
85
|
}: DataTableMobileCardsProps<TData>) {
|
|
72
86
|
const { t } = useTranslation();
|
|
73
87
|
const { knobProps } = useResolvedKnobs();
|
|
@@ -92,6 +106,7 @@ export function DataTableMobileCards<TData extends Record<string, any>>({
|
|
|
92
106
|
{...({
|
|
93
107
|
"data-table-zebra": tableZebraOn ? (index % 2 === 0 ? "even" : "odd") : "off",
|
|
94
108
|
} as any)}
|
|
109
|
+
{...(getRowPressProps ? (getRowPressProps(row, index, "card") as any) : {})}
|
|
95
110
|
>
|
|
96
111
|
{/* Card header: selection + primary-column title + row number + delete */}
|
|
97
112
|
<XStack
|
|
@@ -115,9 +130,11 @@ export function DataTableMobileCards<TData extends Record<string, any>>({
|
|
|
115
130
|
}}
|
|
116
131
|
disabled={disabled}
|
|
117
132
|
checkboxProps={{
|
|
118
|
-
"aria-label":
|
|
119
|
-
row
|
|
120
|
-
|
|
133
|
+
"aria-label":
|
|
134
|
+
selectRowLabel?.(row, index) ??
|
|
135
|
+
withInterp(t("Select row {{row}}", { row: index + 1 }), {
|
|
136
|
+
row: index + 1,
|
|
137
|
+
}),
|
|
121
138
|
}}
|
|
122
139
|
compact={compact}
|
|
123
140
|
/>
|
|
@@ -198,11 +215,20 @@ export function DataTableMobileCards<TData extends Record<string, any>>({
|
|
|
198
215
|
knobProps,
|
|
199
216
|
tableZebraOn,
|
|
200
217
|
t,
|
|
218
|
+
selectRowLabel,
|
|
219
|
+
getRowPressProps,
|
|
201
220
|
],
|
|
202
221
|
);
|
|
203
222
|
|
|
204
223
|
return (
|
|
205
|
-
<View
|
|
224
|
+
<View
|
|
225
|
+
flexDirection="column"
|
|
226
|
+
{...knobProps.gap}
|
|
227
|
+
testID="data-table-cards"
|
|
228
|
+
// Roving-focus DOM scope for onRowPress arrow keys (LC-49) — keeps
|
|
229
|
+
// ArrowUp/Down/Home/End inside THIS table's card list.
|
|
230
|
+
{...(getRowPressProps ? ({ "data-row-press-scope": "true" } as any) : {})}
|
|
231
|
+
>
|
|
206
232
|
{enableRowSelection && tableRows.length > 0 && (
|
|
207
233
|
<XStack alignItems="center" gap="$2" paddingBottom="$2">
|
|
208
234
|
<Checkbox
|
|
@@ -62,6 +62,7 @@ import { DataTableVirtualized } from "./DataTableVirtualized";
|
|
|
62
62
|
import { alignToFlex, getDefaultColumnAlign } from "../../utils/columnAlign";
|
|
63
63
|
import { mapFieldToFilterType } from "../../utils/filterFields";
|
|
64
64
|
import { INFINITE_TRIGGER_ROWS } from "../../utils/paginationDefaults";
|
|
65
|
+
import { isInteractiveInnerTarget } from "../../utils/rowPress";
|
|
65
66
|
import { bidiIsolate, withInterp } from "../../utils/withInterp";
|
|
66
67
|
|
|
67
68
|
const SELECTION_COL_WIDTH = 40;
|
|
@@ -134,6 +135,8 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
134
135
|
maxPinnedColumns = 3,
|
|
135
136
|
enableGrouping = false,
|
|
136
137
|
enableKeyboardNavigation = false,
|
|
138
|
+
onRowPress,
|
|
139
|
+
rowLabel,
|
|
137
140
|
enableRowSelection = false,
|
|
138
141
|
selectAllScope: selectAllScopeProp,
|
|
139
142
|
bulkActions,
|
|
@@ -473,6 +476,159 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
473
476
|
: undefined,
|
|
474
477
|
});
|
|
475
478
|
|
|
479
|
+
const isSSR = typeof window === "undefined";
|
|
480
|
+
|
|
481
|
+
// ---- Row press (onRowPress): the ROW is one pressable unit ----
|
|
482
|
+
|
|
483
|
+
const rowPressActive = Boolean(onRowPress) && !disabled;
|
|
484
|
+
// LC-49 roving anchor: the row set exposes exactly one tab stop — the
|
|
485
|
+
// focused row while focus is inside the set, else the first row.
|
|
486
|
+
const [rowPressAnchor, setRowPressAnchor] = useState(0);
|
|
487
|
+
const effectiveRowPressAnchor = Math.min(rowPressAnchor, Math.max(tableRows.length - 1, 0));
|
|
488
|
+
|
|
489
|
+
// Row identity for accessible names (DG-A11Y-06): consumer accessor →
|
|
490
|
+
// first visible column's cell value → undefined (caller picks its own
|
|
491
|
+
// positional fallback). Shared by the row-press label and the selection
|
|
492
|
+
// checkbox name so "which row is this control for" reads the same
|
|
493
|
+
// everywhere.
|
|
494
|
+
const deriveRowIdentity = useCallback(
|
|
495
|
+
(row: any): string | undefined => {
|
|
496
|
+
const fromAccessor = rowLabel?.(row.original as TData);
|
|
497
|
+
if (fromAccessor) return fromAccessor;
|
|
498
|
+
let firstCellValue: unknown;
|
|
499
|
+
try {
|
|
500
|
+
firstCellValue = row.getVisibleCells()[0]?.getValue();
|
|
501
|
+
} catch {
|
|
502
|
+
firstCellValue = undefined;
|
|
503
|
+
}
|
|
504
|
+
if (
|
|
505
|
+
(typeof firstCellValue === "string" && firstCellValue.length > 0) ||
|
|
506
|
+
typeof firstCellValue === "number"
|
|
507
|
+
) {
|
|
508
|
+
return String(firstCellValue);
|
|
509
|
+
}
|
|
510
|
+
return undefined;
|
|
511
|
+
},
|
|
512
|
+
[rowLabel],
|
|
513
|
+
);
|
|
514
|
+
|
|
515
|
+
// Accessible name per pressable row: identity, else positional "Row {{row}}".
|
|
516
|
+
const deriveRowLabel = useCallback(
|
|
517
|
+
(row: any, rowIndex: number): string =>
|
|
518
|
+
deriveRowIdentity(row) ??
|
|
519
|
+
withInterp(t("Row {{row}}", { row: rowIndex + 1 }), { row: rowIndex + 1 }),
|
|
520
|
+
[deriveRowIdentity, t],
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
// Selection-toggle name: row identity beats a bare index ("Select row
|
|
524
|
+
// Bulbasaur", falling back to "Select row 3") so AT and automation can
|
|
525
|
+
// target a specific row's checkbox by name.
|
|
526
|
+
const deriveSelectRowLabel = useCallback(
|
|
527
|
+
(row: any, rowIndex: number): string => {
|
|
528
|
+
const identity = deriveRowIdentity(row) ?? String(rowIndex + 1);
|
|
529
|
+
return withInterp(t("Select row {{row}}", { row: identity }), { row: identity });
|
|
530
|
+
},
|
|
531
|
+
[deriveRowIdentity, t],
|
|
532
|
+
);
|
|
533
|
+
|
|
534
|
+
const activateRowPress = useCallback(
|
|
535
|
+
(row: any, rowIndex: number) => {
|
|
536
|
+
onRowPress?.(row.original as TData, rowIndex);
|
|
537
|
+
},
|
|
538
|
+
[onRowPress],
|
|
539
|
+
);
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Press/keyboard/AT props for one pressable row (grid `<tr>`, virtualized
|
|
543
|
+
* row host, or mobile card). Spread LAST so the roving tabIndex overrides
|
|
544
|
+
* the static -1 the grid row carries otherwise.
|
|
545
|
+
*
|
|
546
|
+
* - Pointer: activation skips presses originating on inner interactive
|
|
547
|
+
* elements (isInteractiveInnerTarget — the stopPropagation contract's
|
|
548
|
+
* defensive arm).
|
|
549
|
+
* - Keyboard (LC-50): Enter AND Space each synthesize exactly one
|
|
550
|
+
* activation (repeat + defaultPrevented guarded); arrows/Home/End rove
|
|
551
|
+
* within the row set; Shift+Tab exits (no key trap).
|
|
552
|
+
*/
|
|
553
|
+
const getRowPressProps = useCallback(
|
|
554
|
+
(row: any, rowIndex: number, variant: "row" | "card" = "row") => {
|
|
555
|
+
if (!rowPressActive) return {};
|
|
556
|
+
const handlePress = (event: any) => {
|
|
557
|
+
if (event?.defaultPrevented) return;
|
|
558
|
+
const targetEl = event?.target ?? event?.nativeEvent?.target;
|
|
559
|
+
if (isWeb && typeof Element !== "undefined" && targetEl instanceof Element) {
|
|
560
|
+
const boundary = targetEl.closest('[data-row-press="true"]');
|
|
561
|
+
if (isInteractiveInnerTarget(targetEl, boundary)) return;
|
|
562
|
+
}
|
|
563
|
+
activateRowPress(row, rowIndex);
|
|
564
|
+
};
|
|
565
|
+
return {
|
|
566
|
+
"aria-label": deriveRowLabel(row, rowIndex),
|
|
567
|
+
onPress: handlePress,
|
|
568
|
+
cursor: "pointer" as const,
|
|
569
|
+
pressStyle: { backgroundColor: "$color4" },
|
|
570
|
+
...(variant === "card" ? { role: "button" as const } : {}),
|
|
571
|
+
...(isWeb && !isSSR
|
|
572
|
+
? {
|
|
573
|
+
tabIndex: rowIndex === effectiveRowPressAnchor ? 0 : -1,
|
|
574
|
+
focusVisibleStyle: ensureFocusVisibleRing({ outlineOffset: -2 }),
|
|
575
|
+
"data-row-press": "true",
|
|
576
|
+
onFocus: (e: React.FocusEvent) => {
|
|
577
|
+
// Only a focused ROW moves the anchor; focus on an inner
|
|
578
|
+
// control (own tab stop) leaves the roving state alone.
|
|
579
|
+
if (e.target === e.currentTarget) setRowPressAnchor(rowIndex);
|
|
580
|
+
},
|
|
581
|
+
onBlur: (e: React.FocusEvent) => {
|
|
582
|
+
const next = e.relatedTarget;
|
|
583
|
+
if (!(next instanceof Element) || !next.closest('[data-row-press="true"]')) {
|
|
584
|
+
setRowPressAnchor(0);
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
onKeyDown: (e: React.KeyboardEvent) => {
|
|
588
|
+
if (e.defaultPrevented) return;
|
|
589
|
+
// Keys on focused inner controls belong to those controls.
|
|
590
|
+
if (e.target !== e.currentTarget) return;
|
|
591
|
+
const key = e.key;
|
|
592
|
+
if (key === "Enter" || key === " " || key === "Spacebar") {
|
|
593
|
+
// preventDefault stops Space page-scroll; stopPropagation
|
|
594
|
+
// keeps the container-level keyboard nav (Excel mode) from
|
|
595
|
+
// double-activating the same physical key.
|
|
596
|
+
e.preventDefault();
|
|
597
|
+
e.stopPropagation();
|
|
598
|
+
if (e.repeat) return;
|
|
599
|
+
activateRowPress(row, rowIndex);
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
if (key === "ArrowDown" || key === "ArrowUp" || key === "Home" || key === "End") {
|
|
603
|
+
e.preventDefault();
|
|
604
|
+
e.stopPropagation();
|
|
605
|
+
const rowEl = e.currentTarget as HTMLElement;
|
|
606
|
+
const scope =
|
|
607
|
+
rowEl.closest('[data-row-press-scope="true"]') ?? rowEl.ownerDocument;
|
|
608
|
+
const pressRows = Array.from(
|
|
609
|
+
scope.querySelectorAll('[data-row-press="true"]'),
|
|
610
|
+
) as HTMLElement[];
|
|
611
|
+
const currentIdx = pressRows.indexOf(rowEl);
|
|
612
|
+
if (currentIdx < 0) return;
|
|
613
|
+
const nextIdx =
|
|
614
|
+
key === "Home"
|
|
615
|
+
? 0
|
|
616
|
+
: key === "End"
|
|
617
|
+
? pressRows.length - 1
|
|
618
|
+
: Math.min(
|
|
619
|
+
Math.max(currentIdx + (key === "ArrowDown" ? 1 : -1), 0),
|
|
620
|
+
pressRows.length - 1,
|
|
621
|
+
);
|
|
622
|
+
pressRows[nextIdx]?.focus();
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
}
|
|
626
|
+
: {}),
|
|
627
|
+
};
|
|
628
|
+
},
|
|
629
|
+
[rowPressActive, deriveRowLabel, activateRowPress, effectiveRowPressAnchor, isSSR],
|
|
630
|
+
);
|
|
631
|
+
|
|
476
632
|
const handleCellChange = useCallback(
|
|
477
633
|
async (rowIndex: number, columnId: string, newValue: any) => {
|
|
478
634
|
if (readOnly || disabled) return;
|
|
@@ -519,7 +675,28 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
519
675
|
const value = cell.getValue();
|
|
520
676
|
|
|
521
677
|
if (columnDef.cell && !columnDef.field) {
|
|
522
|
-
|
|
678
|
+
// DG-TBL-01 for CUSTOM cell renderers: the cell box's own
|
|
679
|
+
// justifyContent no-ops in the semantic-table displayMode
|
|
680
|
+
// (display: table-cell is not a flex container), so the column's
|
|
681
|
+
// resolved alignment rides this full-width flex container instead —
|
|
682
|
+
// consumers never self-align. The built-in DataTableCell branch
|
|
683
|
+
// below aligns internally (CellWrapper) and stays unwrapped.
|
|
684
|
+
const customAlign = resolveColumnAlign({
|
|
685
|
+
...(columnDef as DataTableColumn),
|
|
686
|
+
id: cell.column.id,
|
|
687
|
+
});
|
|
688
|
+
return (
|
|
689
|
+
<View
|
|
690
|
+
width="100%"
|
|
691
|
+
minWidth={0}
|
|
692
|
+
flexDirection="row"
|
|
693
|
+
alignItems="center"
|
|
694
|
+
justifyContent={alignToFlex(customAlign)}
|
|
695
|
+
{...({ "data-cell-align": customAlign } as any)}
|
|
696
|
+
>
|
|
697
|
+
{flexRender(columnDef.cell, cell.getContext())}
|
|
698
|
+
</View>
|
|
699
|
+
);
|
|
523
700
|
}
|
|
524
701
|
|
|
525
702
|
const columnField = getColumnField(columnDef);
|
|
@@ -556,8 +733,6 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
556
733
|
[handleCellChange, readOnly, disabled, knobProps.sizeToken, isCompact],
|
|
557
734
|
);
|
|
558
735
|
|
|
559
|
-
const isSSR = typeof window === "undefined";
|
|
560
|
-
|
|
561
736
|
const extraColumnsBefore =
|
|
562
737
|
(enableRowSelection ? 1 : 0) + (showRowNumbers ? 1 : 0) + (enableRowExpansion ? 1 : 0);
|
|
563
738
|
const extraColumnsAfter = showDeleteRow && !readOnly ? 1 : 0;
|
|
@@ -651,10 +826,9 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
651
826
|
disabled={disabled}
|
|
652
827
|
checkboxProps={{
|
|
653
828
|
// Row identity in the name so repeated per-row actions are
|
|
654
|
-
// differentiated for screen readers (DG-A11Y-06).
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}),
|
|
829
|
+
// differentiated for screen readers (DG-A11Y-06). The
|
|
830
|
+
// aria-label rides the role="checkbox" frame itself.
|
|
831
|
+
"aria-label": deriveSelectRowLabel(row, rowIndex),
|
|
658
832
|
}}
|
|
659
833
|
compact={isCompact}
|
|
660
834
|
/>
|
|
@@ -840,6 +1014,7 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
840
1014
|
minRows,
|
|
841
1015
|
isCompact,
|
|
842
1016
|
t,
|
|
1017
|
+
deriveSelectRowLabel,
|
|
843
1018
|
ExpandCaretIcon,
|
|
844
1019
|
expandedCaretRotation,
|
|
845
1020
|
clipBodyCells,
|
|
@@ -1084,6 +1259,8 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
1084
1259
|
selectAllIndeterminate={selectAllIndeterminate}
|
|
1085
1260
|
onToggleSelectAll={toggleSelectAll}
|
|
1086
1261
|
compact={isCompact}
|
|
1262
|
+
selectRowLabel={deriveSelectRowLabel}
|
|
1263
|
+
{...(rowPressActive ? { getRowPressProps } : {})}
|
|
1087
1264
|
/>
|
|
1088
1265
|
</>
|
|
1089
1266
|
) : (
|
|
@@ -1099,7 +1276,13 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
1099
1276
|
}}
|
|
1100
1277
|
flexDirection="column"
|
|
1101
1278
|
width="100%"
|
|
1102
|
-
|
|
1279
|
+
// Grow 0 / shrink 1 / basis auto: the grid frame hugs its
|
|
1280
|
+
// rows and only compresses (into internal scroll) when the
|
|
1281
|
+
// parent is shorter. flexGrow 1 stretched the frame to fill
|
|
1282
|
+
// tall parents, painting a dead zone between the last row
|
|
1283
|
+
// and the frame's bottom border on short pages (the frame
|
|
1284
|
+
// claimed data area that held no data — Axiom 6/LC-37).
|
|
1285
|
+
flexGrow={0}
|
|
1103
1286
|
flexShrink={1}
|
|
1104
1287
|
flexBasis="auto"
|
|
1105
1288
|
minHeight={0}
|
|
@@ -1144,6 +1327,8 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
1144
1327
|
// to it instead of the scrolling content View. Content
|
|
1145
1328
|
// fits the max-content box, so nothing needs the clip.
|
|
1146
1329
|
{...(hScroll && enableColumnPinning ? { overflow: "visible" as any } : {})}
|
|
1330
|
+
// Roving-focus DOM scope for onRowPress arrow keys (LC-49).
|
|
1331
|
+
{...(rowPressActive ? ({ "data-row-press-scope": "true" } as any) : {})}
|
|
1147
1332
|
>
|
|
1148
1333
|
{/* Table Header */}
|
|
1149
1334
|
<Table.Head zIndex="$1" aria-label={t("Table headers")}>
|
|
@@ -1553,6 +1738,7 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
1553
1738
|
extraColumnsAfter={extraColumnsAfter}
|
|
1554
1739
|
table={table}
|
|
1555
1740
|
hasInfiniteTail={hasInfiniteTail}
|
|
1741
|
+
{...(rowPressActive ? { getRowPressProps } : {})}
|
|
1556
1742
|
/>
|
|
1557
1743
|
</Table.Cell>
|
|
1558
1744
|
</Table.Row>
|
|
@@ -1646,6 +1832,7 @@ export function DataTableRoot<TData extends Record<string, any> = Record<string,
|
|
|
1646
1832
|
: "odd"
|
|
1647
1833
|
: "off",
|
|
1648
1834
|
} as any)}
|
|
1835
|
+
{...(getRowPressProps(row, index) as any)}
|
|
1649
1836
|
>
|
|
1650
1837
|
{renderRowContent(row, index, isLastRow)}
|
|
1651
1838
|
</Table.Row>
|
|
@@ -42,6 +42,12 @@ export interface DataTableVirtualizedProps {
|
|
|
42
42
|
* scroll range so appended pages grow geometry seamlessly.
|
|
43
43
|
*/
|
|
44
44
|
hasInfiniteTail?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* onRowPress support: press/keyboard/AT props for one pressable row
|
|
47
|
+
* (built by DataTableRoot; spread on the row host so virtual rows keep
|
|
48
|
+
* the same activation + roving-focus contract as grid rows).
|
|
49
|
+
*/
|
|
50
|
+
getRowPressProps?: (row: any, rowIndex: number, variant?: "row" | "card") => Record<string, any>;
|
|
45
51
|
}
|
|
46
52
|
|
|
47
53
|
export function DataTableVirtualized({
|
|
@@ -60,6 +66,7 @@ export function DataTableVirtualized({
|
|
|
60
66
|
getColSizeProps,
|
|
61
67
|
renderRowContent,
|
|
62
68
|
hasInfiniteTail = false,
|
|
69
|
+
getRowPressProps,
|
|
63
70
|
}: DataTableVirtualizedProps) {
|
|
64
71
|
return (
|
|
65
72
|
<div
|
|
@@ -188,6 +195,7 @@ export function DataTableVirtualized({
|
|
|
188
195
|
}
|
|
189
196
|
role="row"
|
|
190
197
|
aria-rowindex={virtualRow.index + 1}
|
|
198
|
+
{...(getRowPressProps ? (getRowPressProps(row, virtualRow.index) as any) : {})}
|
|
191
199
|
>
|
|
192
200
|
{/* div cells (role="cell" via the primitive): a real <td> is
|
|
193
201
|
not a valid child of the absolutely-positioned div rows */}
|