@multiplatform.one/table 6.6.0 → 7.0.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/README.md +4 -3
- package/dist/cjs/components/ChildTable/index.cjs +2 -1
- package/dist/cjs/components/ChildTable/index.native.js +3 -2
- package/dist/cjs/components/ChildTable/index.native.js.map +1 -1
- package/dist/cjs/components/ColumnHeaderFilter/index.cjs +17 -9
- package/dist/cjs/components/ColumnHeaderFilter/index.native.js +33 -12
- 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/DataTableDocumentList.cjs +222 -0
- package/dist/cjs/components/DataTable/DataTableDocumentList.native.js +237 -0
- package/dist/cjs/components/DataTable/DataTableDocumentList.native.js.map +1 -0
- package/dist/cjs/components/DataTable/DataTableMobileCards.cjs +5 -2
- package/dist/cjs/components/DataTable/DataTableMobileCards.native.js +6 -2
- package/dist/cjs/components/DataTable/DataTableMobileCards.native.js.map +1 -1
- package/dist/cjs/components/DataTable/DataTableRoot.cjs +92 -41
- package/dist/cjs/components/DataTable/DataTableRoot.native.js +104 -50
- 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 +8 -2
- package/dist/cjs/components/DataTable/DataTableVirtualized.native.js +9 -3
- package/dist/cjs/components/DataTable/DataTableVirtualized.native.js.map +1 -1
- package/dist/cjs/components/DataTable/documentListSlots.cjs +59 -0
- package/dist/cjs/components/DataTable/documentListSlots.native.js +85 -0
- package/dist/cjs/components/DataTable/documentListSlots.native.js.map +1 -0
- package/dist/cjs/components/DataTable/index.native.js +84 -69
- package/dist/cjs/components/DataTable/index.native.js.map +1 -1
- package/dist/cjs/components/DataTable/rowStateChrome.cjs +55 -0
- package/dist/cjs/components/DataTable/rowStateChrome.native.js +59 -0
- package/dist/cjs/components/DataTable/rowStateChrome.native.js.map +1 -0
- package/dist/cjs/components/DataTableBulkActions/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableCell/CellModalEditor.cjs +24 -3
- package/dist/cjs/components/DataTableCell/CellModalEditor.native.js +6 -1
- package/dist/cjs/components/DataTableCell/CellModalEditor.native.js.map +1 -1
- package/dist/cjs/components/DataTableCell/CellOptionsEditor.cjs +9 -2
- package/dist/cjs/components/DataTableCell/CellOptionsEditor.native.js +11 -2
- package/dist/cjs/components/DataTableCell/CellOptionsEditor.native.js.map +1 -1
- package/dist/cjs/components/DataTableCell/index.cjs +74 -63
- package/dist/cjs/components/DataTableCell/index.native.js +94 -82
- package/dist/cjs/components/DataTableCell/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableColumnPinning/index.cjs +54 -37
- package/dist/cjs/components/DataTableColumnPinning/index.native.js +59 -38
- package/dist/cjs/components/DataTableColumnPinning/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableDateFilter/index.cjs +33 -14
- package/dist/cjs/components/DataTableDateFilter/index.native.js +33 -12
- package/dist/cjs/components/DataTableDateFilter/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableExport/index.cjs +35 -7
- package/dist/cjs/components/DataTableExport/index.native.js +42 -7
- package/dist/cjs/components/DataTableExport/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableFacetMenu/index.cjs +140 -0
- package/dist/cjs/components/DataTableFacetMenu/index.native.js +156 -0
- package/dist/cjs/components/DataTableFacetMenu/index.native.js.map +1 -0
- package/dist/cjs/components/DataTableFilterButton/index.cjs +51 -32
- package/dist/cjs/components/DataTableFilterButton/index.native.js +64 -41
- package/dist/cjs/components/DataTableFilterButton/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableFilterChips/FilterChip.cjs +143 -0
- package/dist/cjs/components/DataTableFilterChips/FilterChip.native.js +148 -0
- package/dist/cjs/components/DataTableFilterChips/FilterChip.native.js.map +1 -0
- package/dist/cjs/components/DataTableFilterChips/index.cjs +9 -31
- package/dist/cjs/components/DataTableFilterChips/index.native.js +9 -32
- package/dist/cjs/components/DataTableFilterChips/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableFilters/index.cjs +145 -502
- package/dist/cjs/components/DataTableFilters/index.native.js +171 -544
- package/dist/cjs/components/DataTableFilters/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableGrouping/index.cjs +273 -108
- package/dist/cjs/components/DataTableGrouping/index.native.js +310 -157
- package/dist/cjs/components/DataTableGrouping/index.native.js.map +1 -1
- package/dist/cjs/components/DataTablePagination/index.cjs +147 -95
- package/dist/cjs/components/DataTablePagination/index.native.js +159 -106
- package/dist/cjs/components/DataTablePagination/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableSearch/index.cjs +251 -210
- package/dist/cjs/components/DataTableSearch/index.native.js +292 -243
- package/dist/cjs/components/DataTableSearch/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableToolbar/index.cjs +141 -115
- package/dist/cjs/components/DataTableToolbar/index.native.js +164 -149
- package/dist/cjs/components/DataTableToolbar/index.native.js.map +1 -1
- package/dist/cjs/components/DataTableViewOptions/index.cjs +25 -21
- package/dist/cjs/components/DataTableViewOptions/index.native.js +6 -4
- package/dist/cjs/components/DataTableViewOptions/index.native.js.map +1 -1
- 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 +336 -46
- package/dist/cjs/components/SimpleTable/index.native.js +356 -48
- package/dist/cjs/components/SimpleTable/index.native.js.map +1 -1
- package/dist/cjs/components/TableInput/index.cjs +147 -38
- package/dist/cjs/components/TableInput/index.native.js +55 -39
- package/dist/cjs/components/TableInput/index.native.js.map +1 -1
- package/dist/cjs/components/TableInput/shared.cjs +36 -1
- package/dist/cjs/components/TableInput/shared.native.js +35 -0
- package/dist/cjs/components/TableInput/shared.native.js.map +1 -1
- package/dist/cjs/hooks/useDataTable.cjs +33 -2
- package/dist/cjs/hooks/useDataTable.native.js +41 -2
- 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.cjs +20 -3
- package/dist/cjs/hooks/useInfiniteRows.native.js +20 -3
- 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/index.cjs +2 -0
- package/dist/cjs/index.native.js +2 -0
- package/dist/cjs/index.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.cjs +12 -5
- package/dist/cjs/utils/filterUtils.native.js +20 -5
- 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.native.js.map +1 -1
- 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/ChildTable/index.mjs +2 -1
- package/dist/esm/components/ChildTable/index.mjs.map +1 -1
- package/dist/esm/components/ChildTable/index.native.js +2 -1
- package/dist/esm/components/ChildTable/index.native.js.map +1 -1
- package/dist/esm/components/ColumnHeaderFilter/index.mjs +17 -9
- package/dist/esm/components/ColumnHeaderFilter/index.mjs.map +1 -1
- package/dist/esm/components/ColumnHeaderFilter/index.native.js +32 -11
- package/dist/esm/components/ColumnHeaderFilter/index.native.js.map +1 -1
- package/dist/esm/components/DataTable/DataTableDocumentList.mjs +196 -0
- package/dist/esm/components/DataTable/DataTableDocumentList.mjs.map +1 -0
- package/dist/esm/components/DataTable/DataTableDocumentList.native.js +208 -0
- package/dist/esm/components/DataTable/DataTableDocumentList.native.js.map +1 -0
- package/dist/esm/components/DataTable/DataTableMobileCards.mjs +5 -2
- package/dist/esm/components/DataTable/DataTableMobileCards.mjs.map +1 -1
- package/dist/esm/components/DataTable/DataTableMobileCards.native.js +6 -2
- package/dist/esm/components/DataTable/DataTableMobileCards.native.js.map +1 -1
- package/dist/esm/components/DataTable/DataTableRoot.mjs +93 -42
- package/dist/esm/components/DataTable/DataTableRoot.mjs.map +1 -1
- package/dist/esm/components/DataTable/DataTableRoot.native.js +98 -44
- package/dist/esm/components/DataTable/DataTableRoot.native.js.map +1 -1
- package/dist/esm/components/DataTable/DataTableVirtualized.mjs +8 -2
- package/dist/esm/components/DataTable/DataTableVirtualized.mjs.map +1 -1
- package/dist/esm/components/DataTable/DataTableVirtualized.native.js +9 -3
- package/dist/esm/components/DataTable/DataTableVirtualized.native.js.map +1 -1
- package/dist/esm/components/DataTable/documentListSlots.mjs +33 -0
- package/dist/esm/components/DataTable/documentListSlots.mjs.map +1 -0
- package/dist/esm/components/DataTable/documentListSlots.native.js +56 -0
- package/dist/esm/components/DataTable/documentListSlots.native.js.map +1 -0
- package/dist/esm/components/DataTable/index.native.js +52 -37
- package/dist/esm/components/DataTable/index.native.js.map +1 -1
- package/dist/esm/components/DataTable/rowStateChrome.mjs +28 -0
- package/dist/esm/components/DataTable/rowStateChrome.mjs.map +1 -0
- package/dist/esm/components/DataTable/rowStateChrome.native.js +29 -0
- package/dist/esm/components/DataTable/rowStateChrome.native.js.map +1 -0
- package/dist/esm/components/DataTableCell/CellModalEditor.mjs +25 -4
- package/dist/esm/components/DataTableCell/CellModalEditor.mjs.map +1 -1
- package/dist/esm/components/DataTableCell/CellModalEditor.native.js +6 -1
- package/dist/esm/components/DataTableCell/CellModalEditor.native.js.map +1 -1
- package/dist/esm/components/DataTableCell/CellOptionsEditor.mjs +9 -2
- package/dist/esm/components/DataTableCell/CellOptionsEditor.mjs.map +1 -1
- package/dist/esm/components/DataTableCell/CellOptionsEditor.native.js +11 -2
- package/dist/esm/components/DataTableCell/CellOptionsEditor.native.js.map +1 -1
- package/dist/esm/components/DataTableCell/index.mjs +75 -64
- package/dist/esm/components/DataTableCell/index.mjs.map +1 -1
- package/dist/esm/components/DataTableCell/index.native.js +95 -83
- package/dist/esm/components/DataTableCell/index.native.js.map +1 -1
- package/dist/esm/components/DataTableColumnPinning/index.mjs +54 -37
- package/dist/esm/components/DataTableColumnPinning/index.mjs.map +1 -1
- package/dist/esm/components/DataTableColumnPinning/index.native.js +59 -38
- package/dist/esm/components/DataTableColumnPinning/index.native.js.map +1 -1
- package/dist/esm/components/DataTableDateFilter/index.mjs +34 -15
- package/dist/esm/components/DataTableDateFilter/index.mjs.map +1 -1
- package/dist/esm/components/DataTableDateFilter/index.native.js +34 -13
- package/dist/esm/components/DataTableDateFilter/index.native.js.map +1 -1
- package/dist/esm/components/DataTableExport/index.mjs +36 -8
- package/dist/esm/components/DataTableExport/index.mjs.map +1 -1
- package/dist/esm/components/DataTableExport/index.native.js +43 -8
- package/dist/esm/components/DataTableExport/index.native.js.map +1 -1
- package/dist/esm/components/DataTableFacetMenu/index.mjs +115 -0
- package/dist/esm/components/DataTableFacetMenu/index.mjs.map +1 -0
- package/dist/esm/components/DataTableFacetMenu/index.native.js +128 -0
- package/dist/esm/components/DataTableFacetMenu/index.native.js.map +1 -0
- package/dist/esm/components/DataTableFilterButton/index.mjs +54 -35
- package/dist/esm/components/DataTableFilterButton/index.mjs.map +1 -1
- package/dist/esm/components/DataTableFilterButton/index.native.js +66 -43
- package/dist/esm/components/DataTableFilterButton/index.native.js.map +1 -1
- package/dist/esm/components/DataTableFilterChips/FilterChip.mjs +118 -0
- package/dist/esm/components/DataTableFilterChips/FilterChip.mjs.map +1 -0
- package/dist/esm/components/DataTableFilterChips/FilterChip.native.js +120 -0
- package/dist/esm/components/DataTableFilterChips/FilterChip.native.js.map +1 -0
- package/dist/esm/components/DataTableFilterChips/index.mjs +9 -32
- package/dist/esm/components/DataTableFilterChips/index.mjs.map +1 -1
- package/dist/esm/components/DataTableFilterChips/index.native.js +9 -33
- package/dist/esm/components/DataTableFilterChips/index.native.js.map +1 -1
- package/dist/esm/components/DataTableFilters/index.mjs +149 -506
- package/dist/esm/components/DataTableFilters/index.mjs.map +1 -1
- package/dist/esm/components/DataTableFilters/index.native.js +175 -548
- package/dist/esm/components/DataTableFilters/index.native.js.map +1 -1
- package/dist/esm/components/DataTableGrouping/index.mjs +275 -110
- package/dist/esm/components/DataTableGrouping/index.mjs.map +1 -1
- package/dist/esm/components/DataTableGrouping/index.native.js +287 -134
- package/dist/esm/components/DataTableGrouping/index.native.js.map +1 -1
- package/dist/esm/components/DataTablePagination/index.mjs +148 -96
- package/dist/esm/components/DataTablePagination/index.mjs.map +1 -1
- package/dist/esm/components/DataTablePagination/index.native.js +160 -107
- package/dist/esm/components/DataTablePagination/index.native.js.map +1 -1
- package/dist/esm/components/DataTableSearch/index.mjs +256 -215
- package/dist/esm/components/DataTableSearch/index.mjs.map +1 -1
- package/dist/esm/components/DataTableSearch/index.native.js +297 -248
- package/dist/esm/components/DataTableSearch/index.native.js.map +1 -1
- package/dist/esm/components/DataTableToolbar/index.mjs +145 -119
- package/dist/esm/components/DataTableToolbar/index.mjs.map +1 -1
- package/dist/esm/components/DataTableToolbar/index.native.js +167 -152
- package/dist/esm/components/DataTableToolbar/index.native.js.map +1 -1
- package/dist/esm/components/DataTableViewOptions/index.mjs +26 -22
- package/dist/esm/components/DataTableViewOptions/index.mjs.map +1 -1
- package/dist/esm/components/DataTableViewOptions/index.native.js +7 -5
- package/dist/esm/components/DataTableViewOptions/index.native.js.map +1 -1
- package/dist/esm/components/SimpleTable/index.mjs +338 -48
- package/dist/esm/components/SimpleTable/index.mjs.map +1 -1
- package/dist/esm/components/SimpleTable/index.native.js +358 -50
- package/dist/esm/components/SimpleTable/index.native.js.map +1 -1
- package/dist/esm/components/TableInput/index.mjs +150 -41
- package/dist/esm/components/TableInput/index.mjs.map +1 -1
- package/dist/esm/components/TableInput/index.native.js +55 -39
- package/dist/esm/components/TableInput/index.native.js.map +1 -1
- package/dist/esm/components/TableInput/shared.mjs +34 -1
- package/dist/esm/components/TableInput/shared.mjs.map +1 -1
- package/dist/esm/components/TableInput/shared.native.js +34 -1
- package/dist/esm/components/TableInput/shared.native.js.map +1 -1
- package/dist/esm/hooks/useDataTable.mjs +33 -2
- package/dist/esm/hooks/useDataTable.mjs.map +1 -1
- package/dist/esm/hooks/useDataTable.native.js +41 -2
- package/dist/esm/hooks/useDataTable.native.js.map +1 -1
- package/dist/esm/hooks/useInfiniteRows.mjs +20 -3
- package/dist/esm/hooks/useInfiniteRows.mjs.map +1 -1
- package/dist/esm/hooks/useInfiniteRows.native.js +20 -3
- package/dist/esm/hooks/useInfiniteRows.native.js.map +1 -1
- package/dist/esm/index.mjs +2 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +2 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/utils/filterUtils.mjs +12 -5
- package/dist/esm/utils/filterUtils.mjs.map +1 -1
- package/dist/esm/utils/filterUtils.native.js +20 -5
- package/dist/esm/utils/filterUtils.native.js.map +1 -1
- package/dist/jsx/components/ChildTable/index.mjs +2 -1
- package/dist/jsx/components/ChildTable/index.mjs.map +1 -1
- package/dist/jsx/components/ChildTable/index.native.js +2 -1
- package/dist/jsx/components/ChildTable/index.native.js.map +1 -1
- package/dist/jsx/components/ColumnHeaderFilter/index.mjs +17 -9
- package/dist/jsx/components/ColumnHeaderFilter/index.mjs.map +1 -1
- package/dist/jsx/components/ColumnHeaderFilter/index.native.js +32 -11
- package/dist/jsx/components/ColumnHeaderFilter/index.native.js.map +1 -1
- package/dist/jsx/components/DataTable/DataTableDocumentList.mjs +196 -0
- package/dist/jsx/components/DataTable/DataTableDocumentList.mjs.map +1 -0
- package/dist/jsx/components/DataTable/DataTableDocumentList.native.js +237 -0
- package/dist/jsx/components/DataTable/DataTableDocumentList.native.js.map +1 -0
- package/dist/jsx/components/DataTable/DataTableMobileCards.mjs +5 -2
- package/dist/jsx/components/DataTable/DataTableMobileCards.mjs.map +1 -1
- package/dist/jsx/components/DataTable/DataTableMobileCards.native.js +6 -2
- package/dist/jsx/components/DataTable/DataTableMobileCards.native.js.map +1 -1
- package/dist/jsx/components/DataTable/DataTableRoot.mjs +93 -42
- package/dist/jsx/components/DataTable/DataTableRoot.mjs.map +1 -1
- package/dist/jsx/components/DataTable/DataTableRoot.native.js +97 -43
- package/dist/jsx/components/DataTable/DataTableRoot.native.js.map +1 -1
- package/dist/jsx/components/DataTable/DataTableVirtualized.mjs +8 -2
- package/dist/jsx/components/DataTable/DataTableVirtualized.mjs.map +1 -1
- package/dist/jsx/components/DataTable/DataTableVirtualized.native.js +9 -3
- package/dist/jsx/components/DataTable/DataTableVirtualized.native.js.map +1 -1
- package/dist/jsx/components/DataTable/documentListSlots.mjs +33 -0
- package/dist/jsx/components/DataTable/documentListSlots.mjs.map +1 -0
- package/dist/jsx/components/DataTable/documentListSlots.native.js +85 -0
- package/dist/jsx/components/DataTable/documentListSlots.native.js.map +1 -0
- package/dist/jsx/components/DataTable/index.native.js +74 -59
- package/dist/jsx/components/DataTable/index.native.js.map +1 -1
- package/dist/jsx/components/DataTable/rowStateChrome.mjs +28 -0
- package/dist/jsx/components/DataTable/rowStateChrome.mjs.map +1 -0
- package/dist/jsx/components/DataTable/rowStateChrome.native.js +59 -0
- package/dist/jsx/components/DataTable/rowStateChrome.native.js.map +1 -0
- package/dist/jsx/components/DataTableCell/CellModalEditor.mjs +25 -4
- package/dist/jsx/components/DataTableCell/CellModalEditor.mjs.map +1 -1
- package/dist/jsx/components/DataTableCell/CellModalEditor.native.js +6 -1
- package/dist/jsx/components/DataTableCell/CellModalEditor.native.js.map +1 -1
- package/dist/jsx/components/DataTableCell/CellOptionsEditor.mjs +9 -2
- package/dist/jsx/components/DataTableCell/CellOptionsEditor.mjs.map +1 -1
- package/dist/jsx/components/DataTableCell/CellOptionsEditor.native.js +11 -2
- package/dist/jsx/components/DataTableCell/CellOptionsEditor.native.js.map +1 -1
- package/dist/jsx/components/DataTableCell/index.mjs +75 -64
- package/dist/jsx/components/DataTableCell/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableCell/index.native.js +94 -82
- package/dist/jsx/components/DataTableCell/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableColumnPinning/index.mjs +54 -37
- package/dist/jsx/components/DataTableColumnPinning/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableColumnPinning/index.native.js +59 -38
- package/dist/jsx/components/DataTableColumnPinning/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableDateFilter/index.mjs +34 -15
- package/dist/jsx/components/DataTableDateFilter/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableDateFilter/index.native.js +33 -12
- package/dist/jsx/components/DataTableDateFilter/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableExport/index.mjs +36 -8
- package/dist/jsx/components/DataTableExport/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableExport/index.native.js +42 -7
- package/dist/jsx/components/DataTableExport/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableFacetMenu/index.mjs +115 -0
- package/dist/jsx/components/DataTableFacetMenu/index.mjs.map +1 -0
- package/dist/jsx/components/DataTableFacetMenu/index.native.js +156 -0
- package/dist/jsx/components/DataTableFacetMenu/index.native.js.map +1 -0
- package/dist/jsx/components/DataTableFilterButton/index.mjs +54 -35
- package/dist/jsx/components/DataTableFilterButton/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableFilterButton/index.native.js +63 -40
- package/dist/jsx/components/DataTableFilterButton/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableFilterChips/FilterChip.mjs +118 -0
- package/dist/jsx/components/DataTableFilterChips/FilterChip.mjs.map +1 -0
- package/dist/jsx/components/DataTableFilterChips/FilterChip.native.js +148 -0
- package/dist/jsx/components/DataTableFilterChips/FilterChip.native.js.map +1 -0
- package/dist/jsx/components/DataTableFilterChips/index.mjs +9 -32
- package/dist/jsx/components/DataTableFilterChips/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableFilterChips/index.native.js +9 -32
- package/dist/jsx/components/DataTableFilterChips/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableFilters/index.mjs +149 -506
- package/dist/jsx/components/DataTableFilters/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableFilters/index.native.js +171 -544
- package/dist/jsx/components/DataTableFilters/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableGrouping/index.mjs +275 -110
- package/dist/jsx/components/DataTableGrouping/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableGrouping/index.native.js +310 -157
- package/dist/jsx/components/DataTableGrouping/index.native.js.map +1 -1
- package/dist/jsx/components/DataTablePagination/index.mjs +148 -96
- package/dist/jsx/components/DataTablePagination/index.mjs.map +1 -1
- package/dist/jsx/components/DataTablePagination/index.native.js +159 -106
- package/dist/jsx/components/DataTablePagination/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableSearch/index.mjs +256 -215
- package/dist/jsx/components/DataTableSearch/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableSearch/index.native.js +292 -243
- package/dist/jsx/components/DataTableSearch/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableToolbar/index.mjs +145 -119
- package/dist/jsx/components/DataTableToolbar/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableToolbar/index.native.js +163 -148
- package/dist/jsx/components/DataTableToolbar/index.native.js.map +1 -1
- package/dist/jsx/components/DataTableViewOptions/index.mjs +26 -22
- package/dist/jsx/components/DataTableViewOptions/index.mjs.map +1 -1
- package/dist/jsx/components/DataTableViewOptions/index.native.js +6 -4
- package/dist/jsx/components/DataTableViewOptions/index.native.js.map +1 -1
- package/dist/jsx/components/SimpleTable/index.mjs +338 -48
- package/dist/jsx/components/SimpleTable/index.mjs.map +1 -1
- package/dist/jsx/components/SimpleTable/index.native.js +356 -48
- package/dist/jsx/components/SimpleTable/index.native.js.map +1 -1
- package/dist/jsx/components/TableInput/index.mjs +150 -41
- package/dist/jsx/components/TableInput/index.mjs.map +1 -1
- package/dist/jsx/components/TableInput/index.native.js +54 -38
- package/dist/jsx/components/TableInput/index.native.js.map +1 -1
- package/dist/jsx/components/TableInput/shared.mjs +34 -1
- package/dist/jsx/components/TableInput/shared.mjs.map +1 -1
- package/dist/jsx/components/TableInput/shared.native.js +35 -0
- package/dist/jsx/components/TableInput/shared.native.js.map +1 -1
- package/dist/jsx/hooks/useDataTable.mjs +33 -2
- package/dist/jsx/hooks/useDataTable.mjs.map +1 -1
- package/dist/jsx/hooks/useDataTable.native.js +41 -2
- package/dist/jsx/hooks/useDataTable.native.js.map +1 -1
- package/dist/jsx/hooks/useInfiniteRows.mjs +20 -3
- package/dist/jsx/hooks/useInfiniteRows.mjs.map +1 -1
- package/dist/jsx/hooks/useInfiniteRows.native.js +20 -3
- package/dist/jsx/hooks/useInfiniteRows.native.js.map +1 -1
- package/dist/jsx/index.js +2 -1
- package/dist/jsx/index.js.map +1 -1
- package/dist/jsx/index.mjs +2 -1
- package/dist/jsx/index.mjs.map +1 -1
- package/dist/jsx/index.native.js +2 -0
- package/dist/jsx/index.native.js.map +1 -1
- package/dist/jsx/utils/filterUtils.mjs +12 -5
- package/dist/jsx/utils/filterUtils.mjs.map +1 -1
- package/dist/jsx/utils/filterUtils.native.js +20 -5
- package/dist/jsx/utils/filterUtils.native.js.map +1 -1
- package/package.json +16 -16
- package/src/components/ChildTable/index.tsx +1 -0
- package/src/components/ColumnHeaderFilter/ColumnHeaderFilter.spec.tsx +85 -0
- package/src/components/ColumnHeaderFilter/index.tsx +28 -10
- package/src/components/DataTable/DataTable.stories.tsx +30 -0
- package/src/components/DataTable/DataTableDocumentList.tsx +224 -0
- package/src/components/DataTable/DataTableMobileCards.tsx +20 -8
- package/src/components/DataTable/DataTableRoot.tsx +135 -58
- package/src/components/DataTable/DataTableVirtualized.tsx +8 -11
- package/src/components/DataTable/cardLayout.spec.tsx +89 -0
- package/src/components/DataTable/documentListSlots.ts +57 -0
- package/src/components/DataTable/index.native.tsx +76 -50
- package/src/components/DataTable/keepPreviousData.spec.tsx +137 -0
- package/src/components/DataTable/rowRing.spec.tsx +118 -0
- package/src/components/DataTable/rowStateChrome.ts +38 -0
- package/src/components/DataTableCell/CellModalEditor.native.tsx +4 -0
- package/src/components/DataTableCell/CellModalEditor.tsx +31 -3
- package/src/components/DataTableCell/CellOptionsEditor.tsx +29 -12
- package/src/components/DataTableCell/DataTableCell.stories.tsx +3 -3
- package/src/components/DataTableCell/cellDraftPolicy.spec.tsx +131 -4
- package/src/components/DataTableCell/dataTableCell.spec.tsx +36 -1
- package/src/components/DataTableCell/index.tsx +121 -86
- package/src/components/DataTableColumnPinning/DataTableColumnPinning.spec.tsx +66 -0
- package/src/components/DataTableColumnPinning/index.tsx +32 -17
- package/src/components/DataTableDateFilter/DataTableDateFilter.spec.tsx +9 -1
- package/src/components/DataTableDateFilter/dateFilterZones.spec.ts +316 -0
- package/src/components/DataTableDateFilter/index.tsx +42 -22
- package/src/components/DataTableExport/exportDateZones.spec.tsx +348 -0
- package/src/components/DataTableExport/index.tsx +107 -63
- package/src/components/DataTableFacetMenu/DataTableFacetMenu.spec.tsx +264 -0
- package/src/components/DataTableFacetMenu/DataTableFacetMenu.stories.tsx +212 -0
- package/src/components/DataTableFacetMenu/index.tsx +202 -0
- package/src/components/DataTableFilterButton/index.tsx +66 -49
- package/src/components/DataTableFilterChips/DataTableFilterChips.spec.tsx +22 -0
- package/src/components/DataTableFilterChips/FilterChip.tsx +122 -0
- package/src/components/DataTableFilterChips/index.tsx +13 -29
- package/src/components/DataTableFilters/DataTableFilters.spec.tsx +56 -0
- package/src/components/DataTableFilters/index.tsx +169 -584
- package/src/components/DataTableGrouping/DataTableGrouping.spec.tsx +85 -0
- package/src/components/DataTableGrouping/index.tsx +270 -130
- package/src/components/DataTablePagination/DataTablePagination.spec.tsx +79 -4
- package/src/components/DataTablePagination/index.tsx +168 -112
- package/src/components/DataTableSearch/DataTableSearch.spec.tsx +40 -0
- package/src/components/DataTableSearch/DataTableSearch.stories.tsx +1 -1
- package/src/components/DataTableSearch/index.tsx +192 -163
- package/src/components/DataTableToolbar/DataTableToolbar.spec.tsx +48 -18
- package/src/components/DataTableToolbar/DataTableToolbar.stories.tsx +5 -45
- package/src/components/DataTableToolbar/index.tsx +128 -99
- package/src/components/DataTableViewOptions/index.tsx +29 -22
- package/src/components/SimpleTable/SimpleTable.stories.tsx +29 -5
- package/src/components/SimpleTable/index.tsx +442 -61
- package/src/components/SimpleTable/simpleTable.spec.tsx +140 -12
- package/src/components/TableInput/index.native.tsx +91 -81
- package/src/components/TableInput/index.tsx +191 -50
- package/src/components/TableInput/shared.ts +57 -0
- package/src/components/TableInput/tableInput.spec.tsx +104 -0
- package/src/hooks/useDataTable.spec.ts +100 -3
- package/src/hooks/useDataTable.ts +44 -1
- package/src/hooks/useInfiniteRows.spec.tsx +37 -0
- package/src/hooks/useInfiniteRows.ts +34 -4
- package/src/index.ts +7 -0
- package/src/types.ts +54 -3
- package/src/utils/filterUtils.ts +27 -5
- package/types/components/ChildTable/index.d.ts.map +1 -1
- package/types/components/ColumnHeaderFilter/index.d.ts.map +1 -1
- package/types/components/DataTable/DataTableDocumentList.d.ts +32 -0
- package/types/components/DataTable/DataTableDocumentList.d.ts.map +1 -0
- package/types/components/DataTable/DataTableMobileCards.d.ts +3 -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 +1 -2
- package/types/components/DataTable/DataTableVirtualized.d.ts.map +1 -1
- package/types/components/DataTable/documentListSlots.d.ts +26 -0
- package/types/components/DataTable/documentListSlots.d.ts.map +1 -0
- package/types/components/DataTable/index.native.d.ts +1 -1
- package/types/components/DataTable/index.native.d.ts.map +1 -1
- package/types/components/DataTable/rowStateChrome.d.ts +18 -0
- package/types/components/DataTable/rowStateChrome.d.ts.map +1 -0
- package/types/components/DataTableCell/CellModalEditor.d.ts +6 -1
- package/types/components/DataTableCell/CellModalEditor.d.ts.map +1 -1
- package/types/components/DataTableCell/CellModalEditor.native.d.ts +1 -1
- package/types/components/DataTableCell/CellModalEditor.native.d.ts.map +1 -1
- package/types/components/DataTableCell/CellOptionsEditor.d.ts +11 -3
- package/types/components/DataTableCell/CellOptionsEditor.d.ts.map +1 -1
- package/types/components/DataTableCell/index.d.ts +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/DataTableDateFilter/index.d.ts.map +1 -1
- package/types/components/DataTableExport/index.d.ts +17 -6
- package/types/components/DataTableExport/index.d.ts.map +1 -1
- package/types/components/DataTableFacetMenu/index.d.ts +84 -0
- package/types/components/DataTableFacetMenu/index.d.ts.map +1 -0
- package/types/components/DataTableFilterButton/index.d.ts.map +1 -1
- package/types/components/DataTableFilterChips/FilterChip.d.ts +15 -0
- package/types/components/DataTableFilterChips/FilterChip.d.ts.map +1 -0
- package/types/components/DataTableFilterChips/index.d.ts +5 -0
- package/types/components/DataTableFilterChips/index.d.ts.map +1 -1
- package/types/components/DataTableFilters/index.d.ts +11 -0
- package/types/components/DataTableFilters/index.d.ts.map +1 -1
- package/types/components/DataTableGrouping/index.d.ts.map +1 -1
- package/types/components/DataTablePagination/index.d.ts +5 -0
- package/types/components/DataTablePagination/index.d.ts.map +1 -1
- package/types/components/DataTableSearch/index.d.ts.map +1 -1
- package/types/components/DataTableToolbar/index.d.ts +2 -0
- package/types/components/DataTableToolbar/index.d.ts.map +1 -1
- package/types/components/SimpleTable/index.d.ts +27 -5
- package/types/components/SimpleTable/index.d.ts.map +1 -1
- package/types/components/TableInput/index.d.ts +6 -1
- package/types/components/TableInput/index.d.ts.map +1 -1
- package/types/components/TableInput/index.native.d.ts +6 -1
- package/types/components/TableInput/index.native.d.ts.map +1 -1
- package/types/components/TableInput/shared.d.ts +38 -0
- package/types/components/TableInput/shared.d.ts.map +1 -1
- package/types/hooks/useDataTable.d.ts +1 -1
- package/types/hooks/useDataTable.d.ts.map +1 -1
- package/types/hooks/useInfiniteRows.d.ts +8 -1
- package/types/hooks/useInfiniteRows.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/types.d.ts +54 -3
- package/types/types.d.ts.map +1 -1
- package/types/utils/filterUtils.d.ts.map +1 -1
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the export writes for a date-bearing column, across timezones.
|
|
3
|
+
*
|
|
4
|
+
* Every date cell in the grid displays through `formatAbsoluteDate`, which
|
|
5
|
+
* renders a `Date` in LOCAL time. The export rendered the same value with
|
|
6
|
+
* `toISOString()` — the UTC instant — so the exported date part named a
|
|
7
|
+
* different calendar day than the cell it came from whenever the value's
|
|
8
|
+
* local time of day sat across the UTC date boundary: the day BEFORE east of
|
|
9
|
+
* Greenwich, the day after west of it. A CSV that disagrees with the grid is
|
|
10
|
+
* what people reconcile against, so the day is the assertion here.
|
|
11
|
+
*
|
|
12
|
+
* Two frozen instants, because the span from UTC−7 to UTC+14 is 21 hours —
|
|
13
|
+
* under a day — so no single instant has UTC disagreeing with both extremes.
|
|
14
|
+
* Each matrix is paired with a negative control that runs the old
|
|
15
|
+
* `toISOString()` formulation through the identical expectation and asserts
|
|
16
|
+
* the exact set of cells where it disagrees, so the matrix cannot pass
|
|
17
|
+
* vacuously on values every zone happens to render the same way.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { fireEvent, screen, waitFor } from "@testing-library/react";
|
|
21
|
+
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
22
|
+
import { formatAbsoluteDate } from "@multiplatform.one/theme";
|
|
23
|
+
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
|
24
|
+
import { DataTableExport } from "./index";
|
|
25
|
+
|
|
26
|
+
// Spans UTC, two negative offsets and the far positive extreme (UTC+14), so a
|
|
27
|
+
// serializer that leans on the host zone fails somewhere in this list.
|
|
28
|
+
const ZONES = ["UTC", "America/Los_Angeles", "America/New_York", "Pacific/Kiritimati"] as const;
|
|
29
|
+
type Zone = (typeof ZONES)[number];
|
|
30
|
+
|
|
31
|
+
/** Late evening in Los Angeles; still the 15th everywhere else. */
|
|
32
|
+
const INSTANT_A = "2026-08-15T05:00:00.000Z";
|
|
33
|
+
/** The small hours of the 15th in Kiritimati; still the 14th everywhere else. */
|
|
34
|
+
const INSTANT_B = "2026-08-14T11:00:00.000Z";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* What the export must write, per zone. The `day` column is a calendar day —
|
|
38
|
+
* a `datepicker` hands back local midnight — and the two instant columns are
|
|
39
|
+
* real timestamps, kept as full ISO-8601 but stamped with the local offset so
|
|
40
|
+
* the day they lead with is the day the cell shows.
|
|
41
|
+
*/
|
|
42
|
+
const EXPECTED: Record<Zone, { day: string; instantA: string; instantB: string }> = {
|
|
43
|
+
UTC: {
|
|
44
|
+
day: "2026-08-15",
|
|
45
|
+
instantA: "2026-08-15T05:00:00.000Z",
|
|
46
|
+
instantB: "2026-08-14T11:00:00.000Z",
|
|
47
|
+
},
|
|
48
|
+
"America/Los_Angeles": {
|
|
49
|
+
day: "2026-08-15",
|
|
50
|
+
instantA: "2026-08-14T22:00:00.000-07:00",
|
|
51
|
+
instantB: "2026-08-14T04:00:00.000-07:00",
|
|
52
|
+
},
|
|
53
|
+
"America/New_York": {
|
|
54
|
+
day: "2026-08-15",
|
|
55
|
+
instantA: "2026-08-15T01:00:00.000-04:00",
|
|
56
|
+
instantB: "2026-08-14T07:00:00.000-04:00",
|
|
57
|
+
},
|
|
58
|
+
"Pacific/Kiritimati": {
|
|
59
|
+
day: "2026-08-15",
|
|
60
|
+
instantA: "2026-08-15T19:00:00.000+14:00",
|
|
61
|
+
instantB: "2026-08-15T01:00:00.000+14:00",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const mockCreateObjectURL = vi.fn(() => "mock-url");
|
|
66
|
+
|
|
67
|
+
beforeAll(() => {
|
|
68
|
+
Object.defineProperty(window.URL, "createObjectURL", {
|
|
69
|
+
writable: true,
|
|
70
|
+
value: mockCreateObjectURL,
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(window.URL, "revokeObjectURL", { writable: true, value: vi.fn() });
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const originalTZ = process.env.TZ;
|
|
76
|
+
afterEach(() => {
|
|
77
|
+
if (originalTZ === undefined) delete process.env.TZ;
|
|
78
|
+
else process.env.TZ = originalTZ;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
function inZone<T>(timeZone: string, read: () => T): T {
|
|
82
|
+
const previous = process.env.TZ;
|
|
83
|
+
process.env.TZ = timeZone;
|
|
84
|
+
try {
|
|
85
|
+
return read();
|
|
86
|
+
} finally {
|
|
87
|
+
if (previous === undefined) delete process.env.TZ;
|
|
88
|
+
else process.env.TZ = previous;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** The single data row of the CSV the component just wrote. */
|
|
93
|
+
async function exportRow(data: any[], columns: any[]): Promise<string[]> {
|
|
94
|
+
mockCreateObjectURL.mockClear();
|
|
95
|
+
renderWithProviders(<DataTableExport data={data} columns={columns} />);
|
|
96
|
+
fireEvent.click(screen.getByText("CSV"));
|
|
97
|
+
await waitFor(() => expect(mockCreateObjectURL).toHaveBeenCalledWith(expect.any(Blob)));
|
|
98
|
+
const blob = (mockCreateObjectURL.mock.calls.at(-1) as unknown as [Blob])[0];
|
|
99
|
+
const text = await blob.text();
|
|
100
|
+
return text.trim().split("\n")[1]!.split(",");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** The old formulation, verbatim, for the negative controls. */
|
|
104
|
+
function legacyExportValue(value: any): string {
|
|
105
|
+
if (value == null) return "";
|
|
106
|
+
if (value instanceof Date) return value.toISOString();
|
|
107
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
108
|
+
return String(value);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const dayPart = (iso: string) => iso.slice(0, 10);
|
|
112
|
+
|
|
113
|
+
describe("DataTableExport date rendering across timezones", () => {
|
|
114
|
+
describe.each(ZONES)("%s", (zone) => {
|
|
115
|
+
beforeEach(() => {
|
|
116
|
+
process.env.TZ = zone;
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("writes the calendar day the cell displays, for days and for instants", async () => {
|
|
120
|
+
// What a DatePicker hands back: local midnight standing in for a day.
|
|
121
|
+
const day = new Date(2026, 7, 15);
|
|
122
|
+
const row = {
|
|
123
|
+
day,
|
|
124
|
+
instantA: new Date(INSTANT_A),
|
|
125
|
+
instantB: new Date(INSTANT_B),
|
|
126
|
+
// No declared field — the export cannot know the class, so it keeps a
|
|
127
|
+
// full instant, and still leads with the displayed day.
|
|
128
|
+
loose: new Date(INSTANT_A),
|
|
129
|
+
};
|
|
130
|
+
const columns = [
|
|
131
|
+
{ accessorKey: "day", header: "Day", field: "datepicker" as const },
|
|
132
|
+
{ accessorKey: "instantA", header: "A", field: "datetimepicker" as const },
|
|
133
|
+
{ accessorKey: "instantB", header: "B", field: "datetimepicker" as const },
|
|
134
|
+
{ accessorKey: "loose", header: "Loose" },
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
const [dayCell, aCell, bCell, looseCell] = await exportRow([row], columns);
|
|
138
|
+
|
|
139
|
+
expect(dayCell).toBe(EXPECTED[zone].day);
|
|
140
|
+
expect(aCell).toBe(EXPECTED[zone].instantA);
|
|
141
|
+
expect(bCell).toBe(EXPECTED[zone].instantB);
|
|
142
|
+
expect(looseCell).toBe(EXPECTED[zone].instantA);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("agrees with the display register on every date-bearing column", async () => {
|
|
146
|
+
const row = {
|
|
147
|
+
day: new Date(2026, 7, 15),
|
|
148
|
+
instantA: new Date(INSTANT_A),
|
|
149
|
+
instantB: new Date(INSTANT_B),
|
|
150
|
+
};
|
|
151
|
+
const columns = [
|
|
152
|
+
{ accessorKey: "day", header: "Day", field: "datepicker" as const },
|
|
153
|
+
{ accessorKey: "instantA", header: "A", field: "datetimepicker" as const },
|
|
154
|
+
{ accessorKey: "instantB", header: "B", field: "datetimepicker" as const },
|
|
155
|
+
];
|
|
156
|
+
|
|
157
|
+
const cells = await exportRow([row], columns);
|
|
158
|
+
|
|
159
|
+
// The exported day, read back through the house register, is the label
|
|
160
|
+
// the cell renders for the same value. Stated in the register's own
|
|
161
|
+
// terms rather than by re-deriving local parts the way the fix does.
|
|
162
|
+
for (const [index, key] of (["day", "instantA", "instantB"] as const).entries()) {
|
|
163
|
+
expect(formatAbsoluteDate(dayPart(cells[index]!), { year: "always" })).toBe(
|
|
164
|
+
formatAbsoluteDate(row[key], { year: "always" }),
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("keeps instants lossless — the exported string re-reads as the same moment", async () => {
|
|
170
|
+
const instants = [new Date(INSTANT_A), new Date(INSTANT_B)];
|
|
171
|
+
const cells = await exportRow(
|
|
172
|
+
[{ a: instants[0], b: instants[1] }],
|
|
173
|
+
[
|
|
174
|
+
{ accessorKey: "a", header: "A", field: "datetimepicker" as const },
|
|
175
|
+
{ accessorKey: "b", header: "B", field: "datetimepicker" as const },
|
|
176
|
+
],
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
expect(cells.map((cell) => new Date(cell).getTime())).toEqual(
|
|
180
|
+
instants.map((instant) => instant.getTime()),
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("host guard: TZ actually moves the in-process reading", () => {
|
|
186
|
+
// Without this, a host that stopped honouring TZ would make every matrix
|
|
187
|
+
// above pass by rendering the same thing four times. The negative control
|
|
188
|
+
// cannot cover it — toISOString() is UTC on a broken host too, so it would
|
|
189
|
+
// keep "disagreeing" in exactly the right places.
|
|
190
|
+
expect(inZone("America/Los_Angeles", () => new Date(INSTANT_A).getDate())).toBe(14);
|
|
191
|
+
expect(inZone("Pacific/Kiritimati", () => new Date(INSTANT_B).getDate())).toBe(15);
|
|
192
|
+
expect(
|
|
193
|
+
inZone("Pacific/Kiritimati", () => new Date(2026, 7, 15).toISOString().slice(0, 10)),
|
|
194
|
+
).toBe("2026-08-14");
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("negative control: the old toISOString() names the wrong day in exactly three cells", () => {
|
|
198
|
+
const disagreements: string[] = [];
|
|
199
|
+
for (const zone of ZONES) {
|
|
200
|
+
inZone(zone, () => {
|
|
201
|
+
const cells = {
|
|
202
|
+
day: { value: new Date(2026, 7, 15), want: EXPECTED[zone].day },
|
|
203
|
+
instantA: { value: new Date(INSTANT_A), want: dayPart(EXPECTED[zone].instantA) },
|
|
204
|
+
instantB: { value: new Date(INSTANT_B), want: dayPart(EXPECTED[zone].instantB) },
|
|
205
|
+
};
|
|
206
|
+
for (const [name, { value, want }] of Object.entries(cells)) {
|
|
207
|
+
const wrote = dayPart(legacyExportValue(value));
|
|
208
|
+
if (wrote !== want) disagreements.push(`${zone}/${name}: wrote ${wrote} want ${want}`);
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// A calendar day written as UTC lands a day early east of Greenwich; an
|
|
214
|
+
// instant rendered in UTC lands a day late west of it. Nine of the twelve
|
|
215
|
+
// cells agree, which is why this shipped — and why the matrix above is
|
|
216
|
+
// discriminating rather than a restatement of toISOString().
|
|
217
|
+
expect(disagreements).toEqual([
|
|
218
|
+
"America/Los_Angeles/instantA: wrote 2026-08-15 want 2026-08-14",
|
|
219
|
+
"Pacific/Kiritimati/day: wrote 2026-08-14 want 2026-08-15",
|
|
220
|
+
"Pacific/Kiritimati/instantB: wrote 2026-08-14 want 2026-08-15",
|
|
221
|
+
]);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("negative control: the old formulation was lossless too — only the day was wrong", () => {
|
|
225
|
+
// Names what did NOT change, so the fix is not read as trading precision
|
|
226
|
+
// for a readable day. Both formulations denote the same instant; only one
|
|
227
|
+
// of them leads with the day the user was looking at.
|
|
228
|
+
for (const zone of ZONES) {
|
|
229
|
+
inZone(zone, () => {
|
|
230
|
+
const instant = new Date(INSTANT_B);
|
|
231
|
+
expect(new Date(legacyExportValue(instant)).getTime()).toBe(instant.getTime());
|
|
232
|
+
expect(new Date(EXPECTED[zone].instantB).getTime()).toBe(instant.getTime());
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe("DataTableExport date rendering, other channels", () => {
|
|
239
|
+
beforeEach(() => {
|
|
240
|
+
process.env.TZ = "Pacific/Kiritimati";
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("copies string values verbatim — the export never reinterprets source text", async () => {
|
|
244
|
+
const cells = await exportRow(
|
|
245
|
+
[{ wireDay: "2026-08-15", wireStamp: INSTANT_A, code: "5-1" }],
|
|
246
|
+
[
|
|
247
|
+
{ accessorKey: "wireDay", header: "Day", field: "datepicker" as const },
|
|
248
|
+
{ accessorKey: "wireStamp", header: "Stamp", field: "datetimepicker" as const },
|
|
249
|
+
{ accessorKey: "code", header: "Code" },
|
|
250
|
+
],
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
// A bare calendar day already names its day and the grid renders it in
|
|
254
|
+
// UTC, so the two already agree. `code` is the reason the export does not
|
|
255
|
+
// sniff strings for dates: "5-1" is a product code that Date.parse would
|
|
256
|
+
// happily read as the 1st of May.
|
|
257
|
+
expect(cells).toEqual(["2026-08-15", INSTANT_A, "5-1"]);
|
|
258
|
+
expect(new Date("5-1").getMonth()).toBe(4);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("renders Dates nested in a range or a multi-date array, not their UTC day", async () => {
|
|
262
|
+
const cells = await exportRow(
|
|
263
|
+
[
|
|
264
|
+
{
|
|
265
|
+
range: { start: new Date(2026, 7, 15), end: new Date(2026, 7, 17) },
|
|
266
|
+
days: [new Date(2026, 7, 15), new Date(2026, 7, 16)],
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
[
|
|
270
|
+
{ accessorKey: "range", header: "Range", field: "daterangepicker" as const },
|
|
271
|
+
{ accessorKey: "days", header: "Days", field: "multidatepicker" as const },
|
|
272
|
+
],
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
// JSON.stringify reaches Date.prototype.toJSON, which is toISOString() —
|
|
276
|
+
// the same UTC shift, one level down. At +14 these each read a day early.
|
|
277
|
+
expect(cells.join(",")).toBe(
|
|
278
|
+
'"{""start"":""2026-08-15"",""end"":""2026-08-17""}","[""2026-08-15"",""2026-08-16""]"',
|
|
279
|
+
);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("writes the displayed day in the JSON export, and leaves other types native", async () => {
|
|
283
|
+
mockCreateObjectURL.mockClear();
|
|
284
|
+
renderWithProviders(
|
|
285
|
+
<DataTableExport
|
|
286
|
+
data={[{ due: new Date(2026, 7, 15), at: new Date(INSTANT_B), qty: 3, ok: false }]}
|
|
287
|
+
columns={[
|
|
288
|
+
{ accessorKey: "due", header: "Due", field: "datepicker" },
|
|
289
|
+
{ accessorKey: "at", header: "At", field: "datetimepicker" },
|
|
290
|
+
{ accessorKey: "qty", header: "Qty" },
|
|
291
|
+
{ accessorKey: "ok", header: "Ok" },
|
|
292
|
+
]}
|
|
293
|
+
exportFormats={[
|
|
294
|
+
{
|
|
295
|
+
id: "json",
|
|
296
|
+
label: "JSON",
|
|
297
|
+
icon: null,
|
|
298
|
+
extension: "json",
|
|
299
|
+
mimeType: "application/json",
|
|
300
|
+
description: "JSON",
|
|
301
|
+
enabled: true,
|
|
302
|
+
},
|
|
303
|
+
]}
|
|
304
|
+
/>,
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
fireEvent.click(screen.getByText("JSON"));
|
|
308
|
+
await waitFor(() => expect(mockCreateObjectURL).toHaveBeenCalledWith(expect.any(Blob)));
|
|
309
|
+
const blob = (mockCreateObjectURL.mock.calls.at(-1) as unknown as [Blob])[0];
|
|
310
|
+
|
|
311
|
+
expect(JSON.parse(await blob.text())).toEqual([
|
|
312
|
+
{ due: "2026-08-15", at: "2026-08-15T01:00:00.000+14:00", qty: 3, ok: false },
|
|
313
|
+
]);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it("prints the same day it exports", async () => {
|
|
317
|
+
const printDoc = document.implementation.createHTMLDocument("print");
|
|
318
|
+
const print = vi.fn();
|
|
319
|
+
vi.spyOn(window, "open").mockReturnValue({ document: printDoc, print } as any);
|
|
320
|
+
|
|
321
|
+
renderWithProviders(
|
|
322
|
+
<DataTableExport
|
|
323
|
+
data={[{ due: new Date(2026, 7, 15) }]}
|
|
324
|
+
columns={[{ accessorKey: "due", header: "Due", field: "datepicker" }]}
|
|
325
|
+
/>,
|
|
326
|
+
);
|
|
327
|
+
fireEvent.click(screen.getByText("Print"));
|
|
328
|
+
|
|
329
|
+
await waitFor(() => expect(print).toHaveBeenCalled());
|
|
330
|
+
expect(printDoc.querySelector("td")?.textContent).toBe("2026-08-15");
|
|
331
|
+
vi.restoreAllMocks();
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it("blanks an unparseable Date instead of failing the whole export", async () => {
|
|
335
|
+
// toISOString() throws RangeError on an invalid Date, which surfaced as
|
|
336
|
+
// "Export failed" for the entire file rather than one empty cell.
|
|
337
|
+
expect(() => legacyExportValue(new Date("nonsense"))).toThrow(RangeError);
|
|
338
|
+
|
|
339
|
+
const cells = await exportRow(
|
|
340
|
+
[{ due: new Date("nonsense"), name: "Widget" }],
|
|
341
|
+
[
|
|
342
|
+
{ accessorKey: "due", header: "Due", field: "datepicker" as const },
|
|
343
|
+
{ accessorKey: "name", header: "Name" },
|
|
344
|
+
],
|
|
345
|
+
);
|
|
346
|
+
expect(cells).toEqual(["", "Widget"]);
|
|
347
|
+
});
|
|
348
|
+
});
|
|
@@ -6,10 +6,11 @@ import {
|
|
|
6
6
|
GearIcon,
|
|
7
7
|
} from "@phosphor-icons/react";
|
|
8
8
|
import { downloadBlob } from "@multiplatform.one/platform";
|
|
9
|
-
import { useResolvedKnobs } from "@multiplatform.one/theme";
|
|
9
|
+
import { formatCalendarDate, useResolvedKnobs } from "@multiplatform.one/theme";
|
|
10
10
|
import { useState } from "react";
|
|
11
11
|
import { Button, Checkbox, Input } from "@multiplatform.one/forms";
|
|
12
12
|
import { Popover, ScrollView, Separator, Text, XStack, YStack } from "tamagui";
|
|
13
|
+
import type { DataTableField } from "../../types";
|
|
13
14
|
import { getViewLeafRows } from "../../utils/viewData";
|
|
14
15
|
import { useDataTableState } from "../DataTable/DataTableStateContext";
|
|
15
16
|
|
|
@@ -37,14 +38,25 @@ export interface ExportFormat {
|
|
|
37
38
|
enabled: boolean;
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Column metadata the export needs. Structurally a subset of
|
|
43
|
+
* `DataTableColumn`, so table column defs pass straight through.
|
|
44
|
+
*/
|
|
45
|
+
export interface ExportColumn {
|
|
46
|
+
accessorKey?: string;
|
|
47
|
+
header?: string;
|
|
48
|
+
id?: string;
|
|
49
|
+
cell?: (info: any) => any;
|
|
50
|
+
/**
|
|
51
|
+
* The column's editor type. Only read to tell a calendar day apart from an
|
|
52
|
+
* instant when serializing `Date` values — see `toExportValue`.
|
|
53
|
+
*/
|
|
54
|
+
field?: DataTableField;
|
|
55
|
+
}
|
|
56
|
+
|
|
40
57
|
export interface DataTableExportProps<T = any> {
|
|
41
58
|
data?: T[];
|
|
42
|
-
columns?:
|
|
43
|
-
accessorKey?: string;
|
|
44
|
-
header?: string;
|
|
45
|
-
id?: string;
|
|
46
|
-
cell?: (info: any) => any;
|
|
47
|
-
}>;
|
|
59
|
+
columns?: ExportColumn[];
|
|
48
60
|
filename?: string;
|
|
49
61
|
exportFormats?: ExportFormat[];
|
|
50
62
|
onExport?: (options: ExportOptions) => Promise<void>;
|
|
@@ -223,14 +235,14 @@ export function DataTableExport<T = any>(props: DataTableExportProps<T>) {
|
|
|
223
235
|
// Extract column metadata from TanStack Table instance for context fallback.
|
|
224
236
|
// Visible leaf columns only, in display order — hidden columns are excluded
|
|
225
237
|
// from the export and column reordering/pinning is honored.
|
|
226
|
-
function extractColumnsFromTable(
|
|
227
|
-
table: any,
|
|
228
|
-
): Array<{ accessorKey?: string; header?: string; id?: string }> {
|
|
238
|
+
function extractColumnsFromTable(table: any): ExportColumn[] {
|
|
229
239
|
try {
|
|
230
240
|
return table.getVisibleLeafColumns().map((col: any) => ({
|
|
231
241
|
id: col.id,
|
|
232
242
|
accessorKey: col.id,
|
|
233
243
|
header: typeof col.columnDef.header === "string" ? col.columnDef.header : col.id,
|
|
244
|
+
// Carried so date columns export the calendar day the cell renders.
|
|
245
|
+
field: col.columnDef.field,
|
|
234
246
|
}));
|
|
235
247
|
} catch {
|
|
236
248
|
return [];
|
|
@@ -247,12 +259,7 @@ interface ExportOptionsPopoverProps {
|
|
|
247
259
|
onPrint: () => void;
|
|
248
260
|
disabled: boolean;
|
|
249
261
|
isExporting: string | null;
|
|
250
|
-
columns:
|
|
251
|
-
accessorKey?: string;
|
|
252
|
-
header?: string;
|
|
253
|
-
id?: string;
|
|
254
|
-
cell?: (info: any) => any;
|
|
255
|
-
}>;
|
|
262
|
+
columns: ExportColumn[];
|
|
256
263
|
}
|
|
257
264
|
|
|
258
265
|
function ExportOptionsPopover({
|
|
@@ -437,12 +444,7 @@ function ExportOptionsPopover({
|
|
|
437
444
|
|
|
438
445
|
async function defaultExport<T>(
|
|
439
446
|
data: T[],
|
|
440
|
-
columns:
|
|
441
|
-
accessorKey?: string;
|
|
442
|
-
header?: string;
|
|
443
|
-
id?: string;
|
|
444
|
-
cell?: (info: any) => any;
|
|
445
|
-
}>,
|
|
447
|
+
columns: ExportColumn[],
|
|
446
448
|
options: ExportOptions,
|
|
447
449
|
): Promise<void> {
|
|
448
450
|
const { format, selectedColumns } = options;
|
|
@@ -466,18 +468,85 @@ async function defaultExport<T>(
|
|
|
466
468
|
}
|
|
467
469
|
}
|
|
468
470
|
|
|
471
|
+
/**
|
|
472
|
+
* Editor types whose value is a calendar DAY rather than an instant. A
|
|
473
|
+
* `datepicker` hands back `new Date(y, m, d)` — local midnight standing in for
|
|
474
|
+
* a day with no time in it — so the export writes the day and nothing else.
|
|
475
|
+
* Every other date editor (`datetimepicker`) means a real timestamp.
|
|
476
|
+
*/
|
|
477
|
+
const CALENDAR_DAY_FIELDS: ReadonlySet<DataTableField> = new Set<DataTableField>([
|
|
478
|
+
"datepicker",
|
|
479
|
+
"daterangepicker",
|
|
480
|
+
"multidatepicker",
|
|
481
|
+
]);
|
|
482
|
+
|
|
483
|
+
function isCalendarDayColumn(column?: ExportColumn): boolean {
|
|
484
|
+
return column?.field != null && CALENDAR_DAY_FIELDS.has(column.field);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const pad2 = (n: number) => String(n).padStart(2, "0");
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Render a `Date` onto the LOCAL calendar, which is the calendar the grid
|
|
491
|
+
* shows: every date cell displays through `formatAbsoluteDate`, and that
|
|
492
|
+
* formats a `Date` in local time. `toISOString()` renders the UTC instant
|
|
493
|
+
* instead, so east of Greenwich the exported date part named the day BEFORE
|
|
494
|
+
* the one in the cell the user was looking at (and west of it, the day after).
|
|
495
|
+
*
|
|
496
|
+
* A calendar-day column emits the bare day. An instant keeps full ISO-8601 —
|
|
497
|
+
* still lossless and still `Date.parse`-able — but stamped with the local
|
|
498
|
+
* offset rather than `Z`, so the same instant now leads with the displayed
|
|
499
|
+
* day. At UTC the two renderings are byte-identical, which is why this only
|
|
500
|
+
* ever looked correct.
|
|
501
|
+
*/
|
|
502
|
+
function serializeExportDate(value: Date, calendarDay: boolean): string {
|
|
503
|
+
if (Number.isNaN(value.getTime())) return "";
|
|
504
|
+
if (calendarDay) return formatCalendarDate(value, "date");
|
|
505
|
+
const offsetMinutes = -value.getTimezoneOffset();
|
|
506
|
+
const sign = offsetMinutes < 0 ? "-" : "+";
|
|
507
|
+
const abs = Math.abs(offsetMinutes);
|
|
508
|
+
const offset =
|
|
509
|
+
offsetMinutes === 0 ? "Z" : `${sign}${pad2(Math.trunc(abs / 60))}:${pad2(abs % 60)}`;
|
|
510
|
+
const ms = String(value.getMilliseconds()).padStart(3, "0");
|
|
511
|
+
return `${formatCalendarDate(value, "datetime").replace(" ", "T")}.${ms}${offset}`;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Replace every `Date` reachable inside an array or plain object (a picked
|
|
516
|
+
* `{start,end}` range, a multi-date array) before it reaches JSON.
|
|
517
|
+
* `JSON.stringify` calls `Date.prototype.toJSON`, which is `toISOString()` —
|
|
518
|
+
* the same UTC day-shift, one level down.
|
|
519
|
+
*/
|
|
520
|
+
function withExportDates(value: any, calendarDay: boolean): any {
|
|
521
|
+
if (value instanceof Date) return serializeExportDate(value, calendarDay);
|
|
522
|
+
if (Array.isArray(value)) return value.map((item) => withExportDates(item, calendarDay));
|
|
523
|
+
if (value != null && typeof value === "object") {
|
|
524
|
+
const proto = Object.getPrototypeOf(value);
|
|
525
|
+
if (proto !== Object.prototype && proto !== null) return value;
|
|
526
|
+
return Object.fromEntries(
|
|
527
|
+
Object.entries(value).map(([key, item]) => [key, withExportDates(item, calendarDay)]),
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
return value;
|
|
531
|
+
}
|
|
532
|
+
|
|
469
533
|
/**
|
|
470
534
|
* Serialize a raw cell value for export. Nullish → empty string, but falsy
|
|
471
535
|
* values like 0 and false survive (String(value || "") used to blank them).
|
|
472
|
-
* Dates
|
|
473
|
-
* as "[object Object]".
|
|
536
|
+
* Dates render on the calendar the cell displays and plain objects become
|
|
537
|
+
* JSON so nothing ever exports as "[object Object]".
|
|
538
|
+
*
|
|
539
|
+
* Values already held as strings are copied verbatim — the export never
|
|
540
|
+
* reinterprets source text. It only picks a rendering where the row leaves it
|
|
541
|
+
* no choice, which is when the value is a `Date`.
|
|
474
542
|
*/
|
|
475
|
-
function toExportValue(value: any): string {
|
|
543
|
+
function toExportValue(value: any, column?: ExportColumn): string {
|
|
476
544
|
if (value == null) return "";
|
|
477
|
-
|
|
545
|
+
const calendarDay = isCalendarDayColumn(column);
|
|
546
|
+
if (value instanceof Date) return serializeExportDate(value, calendarDay);
|
|
478
547
|
if (typeof value === "object") {
|
|
479
548
|
try {
|
|
480
|
-
return JSON.stringify(value);
|
|
549
|
+
return JSON.stringify(withExportDates(value, calendarDay));
|
|
481
550
|
} catch {
|
|
482
551
|
return String(value);
|
|
483
552
|
}
|
|
@@ -504,12 +573,7 @@ function guardCsvInjection(raw: any, value: string): string {
|
|
|
504
573
|
// CSV Export
|
|
505
574
|
async function exportAsCSV<T>(
|
|
506
575
|
data: T[],
|
|
507
|
-
columns:
|
|
508
|
-
accessorKey?: string;
|
|
509
|
-
header?: string;
|
|
510
|
-
id?: string;
|
|
511
|
-
cell?: (info: any) => any;
|
|
512
|
-
}>,
|
|
576
|
+
columns: ExportColumn[],
|
|
513
577
|
options: ExportOptions,
|
|
514
578
|
): Promise<void> {
|
|
515
579
|
const { includeHeaders = true, filename = "export" } = options;
|
|
@@ -532,7 +596,7 @@ async function exportAsCSV<T>(
|
|
|
532
596
|
// stringifies to "[object Object]") and bake presentation into the data,
|
|
533
597
|
// so they are intentionally NOT invoked here.
|
|
534
598
|
const raw = (row as any)[key];
|
|
535
|
-
return escapeCsvField(guardCsvInjection(raw, toExportValue(raw)));
|
|
599
|
+
return escapeCsvField(guardCsvInjection(raw, toExportValue(raw, col)));
|
|
536
600
|
});
|
|
537
601
|
csvContent += `${values.join(",")}\n`;
|
|
538
602
|
});
|
|
@@ -543,12 +607,7 @@ async function exportAsCSV<T>(
|
|
|
543
607
|
// JSON Export
|
|
544
608
|
async function exportAsJSON<T>(
|
|
545
609
|
data: T[],
|
|
546
|
-
columns:
|
|
547
|
-
accessorKey?: string;
|
|
548
|
-
header?: string;
|
|
549
|
-
id?: string;
|
|
550
|
-
cell?: (info: any) => any;
|
|
551
|
-
}>,
|
|
610
|
+
columns: ExportColumn[],
|
|
552
611
|
options: ExportOptions,
|
|
553
612
|
): Promise<void> {
|
|
554
613
|
const { filename = "export" } = options;
|
|
@@ -557,7 +616,10 @@ async function exportAsJSON<T>(
|
|
|
557
616
|
const obj: any = {};
|
|
558
617
|
columns.forEach((col) => {
|
|
559
618
|
const key = col.accessorKey || col.id || "";
|
|
560
|
-
|
|
619
|
+
// Non-date values stay native JSON types (numbers are numbers); only
|
|
620
|
+
// Dates are rendered, because JSON.stringify would otherwise reach
|
|
621
|
+
// Date.prototype.toJSON and emit the UTC day.
|
|
622
|
+
obj[key] = withExportDates((row as any)[key], isCalendarDayColumn(col));
|
|
561
623
|
});
|
|
562
624
|
return obj;
|
|
563
625
|
});
|
|
@@ -583,12 +645,7 @@ async function exportAsJSON<T>(
|
|
|
583
645
|
// />
|
|
584
646
|
async function exportAsExcel<T>(
|
|
585
647
|
_data: T[],
|
|
586
|
-
_columns:
|
|
587
|
-
accessorKey?: string;
|
|
588
|
-
header?: string;
|
|
589
|
-
id?: string;
|
|
590
|
-
cell?: (info: any) => any;
|
|
591
|
-
}>,
|
|
648
|
+
_columns: ExportColumn[],
|
|
592
649
|
_options: ExportOptions,
|
|
593
650
|
): Promise<void> {
|
|
594
651
|
throw new Error(
|
|
@@ -602,12 +659,7 @@ async function exportAsExcel<T>(
|
|
|
602
659
|
// users can "Save as PDF" from there.
|
|
603
660
|
async function exportAsPDF<T>(
|
|
604
661
|
_data: T[],
|
|
605
|
-
_columns:
|
|
606
|
-
accessorKey?: string;
|
|
607
|
-
header?: string;
|
|
608
|
-
id?: string;
|
|
609
|
-
cell?: (info: any) => any;
|
|
610
|
-
}>,
|
|
662
|
+
_columns: ExportColumn[],
|
|
611
663
|
_options: ExportOptions,
|
|
612
664
|
): Promise<void> {
|
|
613
665
|
throw new Error(
|
|
@@ -618,15 +670,7 @@ async function exportAsPDF<T>(
|
|
|
618
670
|
// Print functionality. Built with DOM nodes + textContent (never HTML string
|
|
619
671
|
// interpolation) so cell values containing markup cannot inject into the
|
|
620
672
|
// print document (XSS via `<img onerror>`-style data).
|
|
621
|
-
async function printTable<T>(
|
|
622
|
-
data: T[],
|
|
623
|
-
columns: Array<{
|
|
624
|
-
accessorKey?: string;
|
|
625
|
-
header?: string;
|
|
626
|
-
id?: string;
|
|
627
|
-
cell?: (info: any) => any;
|
|
628
|
-
}>,
|
|
629
|
-
): Promise<void> {
|
|
673
|
+
async function printTable<T>(data: T[], columns: ExportColumn[]): Promise<void> {
|
|
630
674
|
const printWindow = window.open("", "_blank");
|
|
631
675
|
if (!printWindow) {
|
|
632
676
|
throw new Error("Print window was blocked. Allow popups for this site and try again.");
|
|
@@ -669,7 +713,7 @@ async function printTable<T>(
|
|
|
669
713
|
const td = doc.createElement("td");
|
|
670
714
|
// Same raw-value derivation as the CSV export — cell renderers return
|
|
671
715
|
// JSX and must not reach the document.
|
|
672
|
-
td.textContent = toExportValue((row as any)[key]);
|
|
716
|
+
td.textContent = toExportValue((row as any)[key], col);
|
|
673
717
|
tr.appendChild(td);
|
|
674
718
|
}
|
|
675
719
|
tbody.appendChild(tr);
|