@economic/taco 14.0.0 → 14.1.0-EC-85807-code-report-fixes.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/charts/components/Area/AreaChart.cjs.map +1 -1
- package/dist/charts/components/Area/AreaChart.d.ts +1 -1
- package/dist/charts/components/Area/AreaChart.js.map +1 -1
- package/dist/charts/components/Bar/BarChart.cjs +2 -2
- package/dist/charts/components/Bar/BarChart.cjs.map +1 -1
- package/dist/charts/components/Bar/BarChart.d.ts +1 -1
- package/dist/charts/components/Bar/BarChart.js +2 -2
- package/dist/charts/components/Bar/BarChart.js.map +1 -1
- package/dist/charts/components/ChartWrapper.cjs.map +1 -1
- package/dist/charts/components/ChartWrapper.js.map +1 -1
- package/dist/charts/components/Composed/BarLineChart.cjs.map +1 -1
- package/dist/charts/components/Composed/BarLineChart.d.ts +2 -2
- package/dist/charts/components/Composed/BarLineChart.js.map +1 -1
- package/dist/charts/components/Donut/DonutChart.cjs.map +1 -1
- package/dist/charts/components/Donut/DonutChart.d.ts +1 -1
- package/dist/charts/components/Donut/DonutChart.js.map +1 -1
- package/dist/charts/components/LegacyDonut/ActiveShape.cjs +7 -5
- package/dist/charts/components/LegacyDonut/ActiveShape.cjs.map +1 -1
- package/dist/charts/components/LegacyDonut/ActiveShape.d.ts +6 -3
- package/dist/charts/components/LegacyDonut/ActiveShape.js +7 -5
- package/dist/charts/components/LegacyDonut/ActiveShape.js.map +1 -1
- package/dist/charts/components/LegacyDonut/CenteredLabel.cjs +1 -1
- package/dist/charts/components/LegacyDonut/CenteredLabel.cjs.map +1 -1
- package/dist/charts/components/LegacyDonut/CenteredLabel.js +1 -1
- package/dist/charts/components/LegacyDonut/CenteredLabel.js.map +1 -1
- package/dist/charts/components/LegacyDonut/LegacyDonutChart.cjs +119 -103
- package/dist/charts/components/LegacyDonut/LegacyDonutChart.cjs.map +1 -1
- package/dist/charts/components/LegacyDonut/LegacyDonutChart.d.ts +13 -2
- package/dist/charts/components/LegacyDonut/LegacyDonutChart.js +119 -103
- package/dist/charts/components/LegacyDonut/LegacyDonutChart.js.map +1 -1
- package/dist/charts/components/LegacyDonut/Legend.cjs +1 -1
- package/dist/charts/components/LegacyDonut/Legend.cjs.map +1 -1
- package/dist/charts/components/LegacyDonut/Legend.js +1 -1
- package/dist/charts/components/LegacyDonut/Legend.js.map +1 -1
- package/dist/charts/components/Legend.cjs +1 -1
- package/dist/charts/components/Legend.cjs.map +1 -1
- package/dist/charts/components/Legend.js +1 -1
- package/dist/charts/components/Legend.js.map +1 -1
- package/dist/charts/components/Line/LineChart.cjs.map +1 -1
- package/dist/charts/components/Line/LineChart.d.ts +3 -2
- package/dist/charts/components/Line/LineChart.js.map +1 -1
- package/dist/charts/components/Pie/PieChart.cjs +4 -4
- package/dist/charts/components/Pie/PieChart.cjs.map +1 -1
- package/dist/charts/components/Pie/PieChart.js +4 -4
- package/dist/charts/components/Pie/PieChart.js.map +1 -1
- package/dist/charts/components/Pie/util.cjs.map +1 -1
- package/dist/charts/components/Pie/util.d.ts +2 -1
- package/dist/charts/components/Pie/util.js.map +1 -1
- package/dist/charts/components/Tooltip.cjs.map +1 -1
- package/dist/charts/components/Tooltip.d.ts +2 -3
- package/dist/charts/components/Tooltip.js.map +1 -1
- package/dist/charts/components/types.d.ts +9 -5
- package/dist/charts/components/useChartData.cjs +5 -3
- package/dist/charts/components/useChartData.cjs.map +1 -1
- package/dist/charts/components/useChartData.d.ts +6 -2
- package/dist/charts/components/useChartData.js +5 -3
- package/dist/charts/components/useChartData.js.map +1 -1
- package/dist/charts/utils/color.cjs +6 -10
- package/dist/charts/utils/color.cjs.map +1 -1
- package/dist/charts/utils/color.js +6 -10
- package/dist/charts/utils/color.js.map +1 -1
- package/dist/charts/utils/common.cjs +10 -10
- package/dist/charts/utils/common.cjs.map +1 -1
- package/dist/charts/utils/common.d.ts +5 -6
- package/dist/charts/utils/common.js +10 -10
- package/dist/charts/utils/common.js.map +1 -1
- package/dist/components/AlertDialog/Context.cjs.map +1 -1
- package/dist/components/AlertDialog/Context.d.ts +1 -1
- package/dist/components/AlertDialog/Context.js.map +1 -1
- package/dist/components/Calendar/Calendar.cjs.map +1 -1
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Combobox/Combobox.cjs.map +1 -1
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Combobox/useCombobox.cjs +2 -4
- package/dist/components/Combobox/useCombobox.cjs.map +1 -1
- package/dist/components/Combobox/useCombobox.d.ts +1 -1
- package/dist/components/Combobox/useCombobox.js +2 -4
- package/dist/components/Combobox/useCombobox.js.map +1 -1
- package/dist/components/Datepicker/useDatepicker.cjs.map +1 -1
- package/dist/components/Datepicker/useDatepicker.js.map +1 -1
- package/dist/components/Dialog/Context.cjs.map +1 -1
- package/dist/components/Dialog/Context.d.ts +1 -1
- package/dist/components/Dialog/Context.js.map +1 -1
- package/dist/components/Dialog/components/Content.cjs.map +1 -1
- package/dist/components/Dialog/components/Content.js.map +1 -1
- package/dist/components/Drawer/components/Content.cjs +1 -1
- package/dist/components/Drawer/components/Content.cjs.map +1 -1
- package/dist/components/Drawer/components/Content.js +1 -1
- package/dist/components/Drawer/components/Content.js.map +1 -1
- package/dist/components/Drawer/useDrawerStack.cjs.map +1 -1
- package/dist/components/Drawer/useDrawerStack.js.map +1 -1
- package/dist/components/Hanger/Hanger.cjs.map +1 -1
- package/dist/components/Hanger/Hanger.js.map +1 -1
- package/dist/components/Header/Header.cjs +1 -1
- package/dist/components/Header/Header.cjs.map +1 -1
- package/dist/components/Header/Header.js +1 -1
- package/dist/components/Header/Header.js.map +1 -1
- package/dist/components/Header/components/PrimaryNavigation.cjs.map +1 -1
- package/dist/components/Header/components/PrimaryNavigation.js.map +1 -1
- package/dist/components/Icon/Icon.cjs.map +1 -1
- package/dist/components/Icon/Icon.js.map +1 -1
- package/dist/components/Layout/components/Sidebar.cjs +2 -1
- package/dist/components/Layout/components/Sidebar.cjs.map +1 -1
- package/dist/components/Layout/components/Sidebar.js +2 -1
- package/dist/components/Layout/components/Sidebar.js.map +1 -1
- package/dist/components/LegacyComponents/IconButton/IconButton.cjs.map +1 -1
- package/dist/components/LegacyComponents/IconButton/IconButton.js.map +1 -1
- package/dist/components/List/components/Toggle.cjs +0 -2
- package/dist/components/List/components/Toggle.cjs.map +1 -1
- package/dist/components/List/components/Toggle.js +0 -2
- package/dist/components/List/components/Toggle.js.map +1 -1
- package/dist/components/Listbox/Listbox.cjs +2 -5
- package/dist/components/Listbox/Listbox.cjs.map +1 -1
- package/dist/components/Listbox/Listbox.js +2 -5
- package/dist/components/Listbox/Listbox.js.map +1 -1
- package/dist/components/Listbox/useListbox.cjs +1 -1
- package/dist/components/Listbox/useListbox.cjs.map +1 -1
- package/dist/components/Listbox/useListbox.js +1 -1
- package/dist/components/Listbox/useListbox.js.map +1 -1
- package/dist/components/Listbox/useMultiListbox.cjs +1 -1
- package/dist/components/Listbox/useMultiListbox.cjs.map +1 -1
- package/dist/components/Listbox/useMultiListbox.js +1 -1
- package/dist/components/Listbox/useMultiListbox.js.map +1 -1
- package/dist/components/Listbox/util.cjs.map +1 -1
- package/dist/components/Listbox/util.js.map +1 -1
- package/dist/components/Menu/components/Content.cjs.map +1 -1
- package/dist/components/Menu/components/Content.js.map +1 -1
- package/dist/components/Menu/components/Item.cjs.map +1 -1
- package/dist/components/Menu/components/Item.d.ts +2 -2
- package/dist/components/Menu/components/Item.js.map +1 -1
- package/dist/components/Menu/components/Trigger.cjs +1 -5
- package/dist/components/Menu/components/Trigger.cjs.map +1 -1
- package/dist/components/Menu/components/Trigger.js +1 -5
- package/dist/components/Menu/components/Trigger.js.map +1 -1
- package/dist/components/Pagination/usePaginationShortcuts.cjs +0 -1
- package/dist/components/Pagination/usePaginationShortcuts.cjs.map +1 -1
- package/dist/components/Pagination/usePaginationShortcuts.js +0 -1
- package/dist/components/Pagination/usePaginationShortcuts.js.map +1 -1
- package/dist/components/Provider/Provider.cjs.map +1 -1
- package/dist/components/Provider/Provider.d.ts +1 -1
- package/dist/components/Provider/Provider.js.map +1 -1
- package/dist/components/SearchInput/SearchInput.cjs +0 -1
- package/dist/components/SearchInput/SearchInput.cjs.map +1 -1
- package/dist/components/SearchInput/SearchInput.js +0 -1
- package/dist/components/SearchInput/SearchInput.js.map +1 -1
- package/dist/components/SearchInput2/SearchInput2.cjs +0 -1
- package/dist/components/SearchInput2/SearchInput2.cjs.map +1 -1
- package/dist/components/SearchInput2/SearchInput2.js +0 -1
- package/dist/components/SearchInput2/SearchInput2.js.map +1 -1
- package/dist/components/Select2/Select2.cjs +6 -7
- package/dist/components/Select2/Select2.cjs.map +1 -1
- package/dist/components/Select2/Select2.js +6 -7
- package/dist/components/Select2/Select2.js.map +1 -1
- package/dist/components/Select2/components/Search.cjs +0 -1
- package/dist/components/Select2/components/Search.cjs.map +1 -1
- package/dist/components/Select2/components/Search.js +0 -1
- package/dist/components/Select2/components/Search.js.map +1 -1
- package/dist/components/Select2/components/Trigger.cjs +1 -1
- package/dist/components/Select2/components/Trigger.cjs.map +1 -1
- package/dist/components/Select2/components/Trigger.js +1 -1
- package/dist/components/Select2/components/Trigger.js.map +1 -1
- package/dist/components/Table3/components/Columns/Cell/EditingControlCell.cjs +1 -1
- package/dist/components/Table3/components/Columns/Cell/EditingControlCell.cjs.map +1 -1
- package/dist/components/Table3/components/Columns/Cell/EditingControlCell.js +1 -1
- package/dist/components/Table3/components/Columns/Cell/EditingControlCell.js.map +1 -1
- package/dist/components/Table3/components/Columns/Cell/util.cjs.map +1 -1
- package/dist/components/Table3/components/Columns/Cell/util.js.map +1 -1
- package/dist/components/Table3/components/Editing/Alert.cjs +4 -4
- package/dist/components/Table3/components/Editing/Alert.cjs.map +1 -1
- package/dist/components/Table3/components/Editing/Alert.js +4 -4
- package/dist/components/Table3/components/Editing/Alert.js.map +1 -1
- package/dist/components/Table3/features/useEditingState.cjs +1 -1
- package/dist/components/Table3/features/useEditingState.cjs.map +1 -1
- package/dist/components/Table3/features/useEditingState.js +1 -1
- package/dist/components/Table3/features/useEditingState.js.map +1 -1
- package/dist/components/Table3/types.d.ts +2 -2
- package/dist/components/Table3/useTable3.cjs +8 -6
- package/dist/components/Table3/useTable3.cjs.map +1 -1
- package/dist/components/Table3/useTable3.js +8 -6
- package/dist/components/Table3/useTable3.js.map +1 -1
- package/dist/components/Table3/util/editing.cjs +1 -1
- package/dist/components/Table3/util/editing.cjs.map +1 -1
- package/dist/components/Table3/util/editing.d.ts +1 -1
- package/dist/components/Table3/util/editing.js +1 -1
- package/dist/components/Table3/util/editing.js.map +1 -1
- package/dist/hooks/useBoundaryOverflowDetection.cjs.map +1 -1
- package/dist/hooks/useBoundaryOverflowDetection.d.ts +1 -1
- package/dist/hooks/useBoundaryOverflowDetection.js.map +1 -1
- package/dist/hooks/useBoundingClientRectListener.cjs.map +1 -1
- package/dist/hooks/useBoundingClientRectListener.d.ts +1 -1
- package/dist/hooks/useBoundingClientRectListener.js.map +1 -1
- package/dist/hooks/useControlled.cjs +6 -10
- package/dist/hooks/useControlled.cjs.map +1 -1
- package/dist/hooks/useControlled.js +6 -10
- package/dist/hooks/useControlled.js.map +1 -1
- package/dist/hooks/useIsFormControl.cjs.map +1 -1
- package/dist/hooks/useIsFormControl.d.ts +1 -1
- package/dist/hooks/useIsFormControl.js.map +1 -1
- package/dist/hooks/useMergedRef.cjs.map +1 -1
- package/dist/hooks/useMergedRef.js.map +1 -1
- package/dist/hooks/usePrevious.cjs.map +1 -1
- package/dist/hooks/usePrevious.js.map +1 -1
- package/dist/primitives/Button.cjs.map +1 -1
- package/dist/primitives/Button.js.map +1 -1
- package/dist/primitives/Collection/components/Root.cjs +9 -16
- package/dist/primitives/Collection/components/Root.cjs.map +1 -1
- package/dist/primitives/Collection/components/Root.js +9 -16
- package/dist/primitives/Collection/components/Root.js.map +1 -1
- package/dist/primitives/Listbox2/components/Context.cjs.map +1 -1
- package/dist/primitives/Listbox2/components/Context.d.ts +1 -0
- package/dist/primitives/Listbox2/components/Context.js.map +1 -1
- package/dist/primitives/Listbox2/components/Option.cjs +8 -2
- package/dist/primitives/Listbox2/components/Option.cjs.map +1 -1
- package/dist/primitives/Listbox2/components/Option.js +8 -2
- package/dist/primitives/Listbox2/components/Option.js.map +1 -1
- package/dist/primitives/Listbox2/components/Root.cjs +3 -2
- package/dist/primitives/Listbox2/components/Root.cjs.map +1 -1
- package/dist/primitives/Listbox2/components/Root.js +3 -2
- package/dist/primitives/Listbox2/components/Root.js.map +1 -1
- package/dist/primitives/Sortable/components/Item.cjs +2 -4
- package/dist/primitives/Sortable/components/Item.cjs.map +1 -1
- package/dist/primitives/Sortable/components/Item.js +2 -4
- package/dist/primitives/Sortable/components/Item.js.map +1 -1
- package/dist/primitives/Table/Core/components/Body/Body.cjs +4 -4
- package/dist/primitives/Table/Core/components/Body/Body.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Body/Body.js +4 -4
- package/dist/primitives/Table/Core/components/Body/Body.js.map +1 -1
- package/dist/primitives/Table/Core/components/Columns/Cell/BuiltIns/DisplayCell.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Columns/Cell/BuiltIns/DisplayCell.js.map +1 -1
- package/dist/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Columns/Cell/BuiltIns/GroupedCell.js.map +1 -1
- package/dist/primitives/Table/Core/components/Columns/Cell/util.cjs +22 -16
- package/dist/primitives/Table/Core/components/Columns/Cell/util.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Columns/Cell/util.js +22 -16
- package/dist/primitives/Table/Core/components/Columns/Cell/util.js.map +1 -1
- package/dist/primitives/Table/Core/components/Footer/Summary.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Footer/Summary.js.map +1 -1
- package/dist/primitives/Table/Core/components/Header/util.cjs +4 -3
- package/dist/primitives/Table/Core/components/Header/util.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Header/util.js +4 -3
- package/dist/primitives/Table/Core/components/Header/util.js.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/Filters.cjs +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/Filters.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/Filters.js +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/Filters.js.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/ManageFiltersPopover.cjs +4 -2
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/ManageFiltersPopover.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/ManageFiltersPopover.js +4 -2
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/ManageFiltersPopover.js.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/components/Filter.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Filters/components/Filter.js.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Print/Print.cjs +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Print/Print.cjs.map +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Print/Print.js +1 -1
- package/dist/primitives/Table/Core/components/Toolbar/components/Print/Print.js.map +1 -1
- package/dist/primitives/Table/Core/features/useTableRef.cjs +7 -0
- package/dist/primitives/Table/Core/features/useTableRef.cjs.map +1 -1
- package/dist/primitives/Table/Core/features/useTableRef.js +7 -0
- package/dist/primitives/Table/Core/features/useTableRef.js.map +1 -1
- package/dist/primitives/Table/Core/features/useTableRenderer.cjs +2 -2
- package/dist/primitives/Table/Core/features/useTableRenderer.cjs.map +1 -1
- package/dist/primitives/Table/Core/features/useTableRenderer.js +2 -2
- package/dist/primitives/Table/Core/features/useTableRenderer.js.map +1 -1
- package/dist/primitives/Table/Core/features/useTableStyleColumnFreezing.cjs +2 -2
- package/dist/primitives/Table/Core/features/useTableStyleColumnFreezing.cjs.map +1 -1
- package/dist/primitives/Table/Core/features/useTableStyleColumnFreezing.js +2 -2
- package/dist/primitives/Table/Core/features/useTableStyleColumnFreezing.js.map +1 -1
- package/dist/primitives/Table/Core/features/useTableStyleGrid.cjs.map +1 -1
- package/dist/primitives/Table/Core/features/useTableStyleGrid.js.map +1 -1
- package/dist/primitives/Table/Core/listeners/useTableRowActiveListener.cjs +2 -4
- package/dist/primitives/Table/Core/listeners/useTableRowActiveListener.cjs.map +1 -1
- package/dist/primitives/Table/Core/listeners/useTableRowActiveListener.d.ts +2 -2
- package/dist/primitives/Table/Core/listeners/useTableRowActiveListener.js +2 -4
- package/dist/primitives/Table/Core/listeners/useTableRowActiveListener.js.map +1 -1
- package/dist/primitives/Table/types.cjs.map +1 -1
- package/dist/primitives/Table/types.d.ts +6 -0
- package/dist/primitives/Table/types.js.map +1 -1
- package/dist/primitives/Table/useTableDataLoader2.cjs +36 -3
- package/dist/primitives/Table/useTableDataLoader2.cjs.map +1 -1
- package/dist/primitives/Table/useTableDataLoader2.d.ts +2 -1
- package/dist/primitives/Table/useTableDataLoader2.js +36 -3
- package/dist/primitives/Table/useTableDataLoader2.js.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowActive.cjs +0 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowActive.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowActive.d.ts +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowActive.js +0 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowActive.js.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowClick.cjs +0 -2
- package/dist/primitives/Table/useTableManager/features/useTableRowClick.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowClick.js +0 -2
- package/dist/primitives/Table/useTableManager/features/useTableRowClick.js.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowSelection.cjs +0 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowSelection.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowSelection.js +0 -1
- package/dist/primitives/Table/useTableManager/features/useTableRowSelection.js.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableServerLoading.cjs +10 -1
- package/dist/primitives/Table/useTableManager/features/useTableServerLoading.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/features/useTableServerLoading.d.ts +3 -2
- package/dist/primitives/Table/useTableManager/features/useTableServerLoading.js +10 -1
- package/dist/primitives/Table/useTableManager/features/useTableServerLoading.js.map +1 -1
- package/dist/primitives/Table/useTableManager/useTableManager.cjs +1 -5
- package/dist/primitives/Table/useTableManager/useTableManager.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/useTableManager.js +1 -5
- package/dist/primitives/Table/useTableManager/useTableManager.js.map +1 -1
- package/dist/primitives/Table/useTableManager/util/dataTypes.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/util/dataTypes.d.ts +3 -3
- package/dist/primitives/Table/useTableManager/util/dataTypes.js.map +1 -1
- package/dist/primitives/Table/useTableManager/util/filtering.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/util/filtering.js.map +1 -1
- package/dist/primitives/Table/useTableManager/util/search.cjs +1 -1
- package/dist/primitives/Table/useTableManager/util/search.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/util/search.js +1 -1
- package/dist/primitives/Table/useTableManager/util/search.js.map +1 -1
- package/dist/primitives/Table/useTableManager/util/setup.cjs +3 -3
- package/dist/primitives/Table/useTableManager/util/setup.cjs.map +1 -1
- package/dist/primitives/Table/useTableManager/util/setup.js +3 -3
- package/dist/primitives/Table/useTableManager/util/setup.js.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/dataTypes.cjs +4 -4
- package/dist/utils/dataTypes.cjs.map +1 -1
- package/dist/utils/dataTypes.d.ts +1 -1
- package/dist/utils/dataTypes.js +4 -4
- package/dist/utils/dataTypes.js.map +1 -1
- package/dist/utils/date.cjs +14 -16
- package/dist/utils/date.cjs.map +1 -1
- package/dist/utils/date.js +14 -16
- package/dist/utils/date.js.map +1 -1
- package/dist/utils/debounce.cjs.map +1 -1
- package/dist/utils/debounce.d.ts +1 -1
- package/dist/utils/debounce.js.map +1 -1
- package/dist/utils/device.cjs +1 -1
- package/dist/utils/device.cjs.map +1 -1
- package/dist/utils/device.js +1 -1
- package/dist/utils/device.js.map +1 -1
- package/dist/utils/dom.cjs +1 -1
- package/dist/utils/dom.cjs.map +1 -1
- package/dist/utils/dom.d.ts +2 -2
- package/dist/utils/dom.js +1 -1
- package/dist/utils/dom.js.map +1 -1
- package/dist/utils/hooks/useDraggable.cjs.map +1 -1
- package/dist/utils/hooks/useDraggable.d.ts +9 -1
- package/dist/utils/hooks/useDraggable.js.map +1 -1
- package/dist/utils/hooks/useListKeyboardNavigation.cjs +1 -1
- package/dist/utils/hooks/useListKeyboardNavigation.cjs.map +1 -1
- package/dist/utils/hooks/useListKeyboardNavigation.js +1 -1
- package/dist/utils/hooks/useListKeyboardNavigation.js.map +1 -1
- package/dist/utils/hooks/useListScrollTo.cjs.map +1 -1
- package/dist/utils/hooks/useListScrollTo.d.ts +4 -1
- package/dist/utils/hooks/useListScrollTo.js.map +1 -1
- package/dist/utils/hooks/useOnClickOutside.cjs.map +1 -1
- package/dist/utils/hooks/useOnClickOutside.d.ts +1 -1
- package/dist/utils/hooks/useOnClickOutside.js.map +1 -1
- package/dist/utils/hooks/useTruncated.cjs.map +1 -1
- package/dist/utils/hooks/useTruncated.d.ts +2 -1
- package/dist/utils/hooks/useTruncated.js.map +1 -1
- package/dist/utils/mergeRefs.cjs.map +1 -1
- package/dist/utils/mergeRefs.d.ts +1 -1
- package/dist/utils/mergeRefs.js.map +1 -1
- package/dist/utils/storyutils.d.ts +1 -3
- package/package.json +4 -5
- package/plugins/tailwindcss-group-peer.js +1 -1
- package/scripts/stylelint-plugin/radius.mjs +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sources":["../../../src/primitives/Table/types.ts"],"sourcesContent":["import type {\n ColumnFilter as ReactTableColumnFilter,\n ColumnFiltersState as ReactTableColumnFilterState,\n ColumnOrderState as ReactTableColumnOrderState,\n ColumnPinningState as ReactTableColumnPinningState,\n ColumnSort as ReactTableColumnSort,\n ColumnSizingState as ReactTableColumnSizingState,\n VisibilityState as ReactTableColumnVisibilityState,\n SortingState as ReactTableSortingState,\n BuiltInAggregationFn as ReactTableBuiltInAggregationFn,\n BuiltInSortingFn as ReactTableBuiltInSortingFn,\n} from '@tanstack/react-table';\n\nimport type { MenuItemProps } from '@/components';\nimport type { DotNotationPaths, FontSize, FontSizes, DotNotationPathValue } from '@/types';\n\nexport type TableRef = HTMLTableElement & {\n instance: {\n resetFiltering: () => void;\n resetRowExpansion: () => void;\n resetRowSelection: () => void;\n resetSorting: () => void;\n };\n};\n\n// filtering\nexport enum TableFilterComparator {\n Contains = 0,\n DoesNotContain = 1,\n IsEqualTo = 2,\n IsNotEqualTo = 3,\n IsGreaterThan = 4,\n IsLessThan = 5,\n IsBetween = 6,\n IsEmpty = 7,\n IsNotEmpty = 8,\n IsLessThanOrEqualTo = 9,\n IsGreaterThanOrEqualTo = 10,\n HasAnyOf = 11,\n HasAllOf = 12,\n HasNoneOf = 13,\n IsOneOf = 14,\n IsNoneOf = 15,\n}\nexport type TableFilterValue = {\n comparator: TableFilterComparator;\n value: any;\n};\nexport type TableFilter = {\n id: string;\n value: TableFilterValue;\n};\n\n// columns\nexport type TableColumnAlignment = 'left' | 'center' | 'right';\nexport type TableColumnClassNameHandler<TType = unknown> = string | ((row: TType) => string | undefined);\nexport type TableColumnDataType =\n // base\n | 'text'\n | 'boolean'\n // dates\n | 'date'\n | 'time'\n | 'datetime'\n // numbers\n | 'number'\n | 'amount'\n | 'percentage';\nexport type TableColumnFilter = ReactTableColumnFilter;\nexport type TableColumnMenu = ((columnId: string) => React.ReactNode | null)[];\nexport type TableColumnRendererArgs<TType, TValue> = TValue extends undefined\n ? { formattedValue: undefined; row: TType; value: undefined }\n : { formattedValue: string; row: TType; value: TValue };\nexport type TableColumnRenderer<TType, TValue = unknown> = (\n args: TableColumnRendererArgs<TType, TValue>\n) => React.JSX.Element | string | number | unknown | null;\nexport type TableColumnRendererAggregate<TType, TValue = unknown> = (\n args: TableColumnRendererArgs<TType, TValue>\n) => React.JSX.Element | string | number | unknown | null;\nexport type TableColumnRendererControl<TType = unknown> =\n | ((props: TableColumnRendererControlProps, row?: TType, filterState?: TableFilter[]) => React.JSX.Element | null)\n | 'datepicker'\n | 'input'\n | 'switch'\n | 'checkbox'\n | 'textarea';\nexport type TableColumnRendererControlProps = {\n className?: string;\n disabled?: boolean;\n fontSize?: FontSize;\n invalid?: boolean;\n onBlur?: (value: any) => void;\n onKeyDown?: React.KeyboardEventHandler;\n onFocus?: React.FocusEventHandler;\n readOnly?: boolean;\n ref: React.Ref<HTMLElement>;\n setValue: (value: any) => void;\n value: any;\n};\nexport type TableColumnRendererHeader = string | React.JSX.Element;\nexport type TableColumnRendererFooter<TType> = (rows: TType[]) => React.JSX.Element | string | number | null;\nexport type TableColumnSort = ReactTableColumnSort;\nexport type TableColumnSortDirection = 'asc' | 'desc';\nexport type TableColumnSortFn<TType = unknown> =\n ((rowA: TType, rowB: TType, columnId: string) => -1 | 0 | 1) | ReactTableBuiltInSortingFn | 'auto';\nexport type TableColumnWidth = number | 'grow';\n\n// rows\nexport type TableRowActionRenderer<TType = unknown> = (\n row: TType,\n helpers: {\n editing?: {\n isEditing: boolean;\n removeRowChanges: () => Promise<void>;\n save: () => Promise<boolean>;\n };\n }\n) => React.JSX.Element | null;\n\nexport type TableRowActionGroupRenderer<TType = unknown> = (rows: TType[]) => React.JSX.Element | null;\nexport type TableRowClickHandler<TType = unknown> = (row: TType) => void;\nexport type TableRowDragHandler<TType = unknown> = (\n rows: TType[],\n showPlaceholder: (text: string) => void,\n setDataTransfer: (data: string) => void\n) => void;\nexport type TableRowDropHandler<TType = unknown> = (event: React.DragEvent, row: TType) => void;\nexport type TableRowGotoHandler = (\n column: string,\n query: string,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n search: string | undefined\n) => Promise<number>;\nexport type TableRowHeight = 'short' | 'medium' | 'tall' | 'extra-tall';\nexport type TableRowActiveHandler<TType = unknown> = (row: TType | undefined) => void;\nexport type TableRowSelectHandler<TType = unknown> = (rows: TType[], ids: string[]) => void;\nexport type TableRowWithMetaData<TType = unknown> = TType & {\n _meta?: {\n layout?: 'heading' | 'summary' | 'item';\n };\n};\n\n// shortcuts\nexport type TableShortcutHandlerFn<TType = unknown> = (row: TType) => void;\nexport type TableShortcutHandlerObject<TType = unknown> = {\n handler: TableShortcutHandlerFn<TType>;\n meta?: boolean;\n shift?: boolean;\n};\n\n// table\nexport type TableSortHandler = (sorting: TableColumnSort[]) => Promise<void> | void;\nexport type TableFilterHandler = (filters: TableColumnFilter[], hiddenColumns: string[]) => Promise<void> | void;\nexport type TableSearchHandler = (search: string | undefined, hiddenColumns: string[]) => Promise<void> | void;\nexport type TableFontSize = keyof typeof FontSizes;\nexport type TablePreset = 'complex' | 'list' | 'simple';\nexport type TableRowExpansionRenderer<TType = unknown> = (row: TType) => (() => React.JSX.Element) | null;\nexport type TableScrollToIndexHandler = (index: number, options?: { align: 'start' | 'center' | 'end' | 'auto' }) => void;\nexport type TableServerLoadPageHandler = (\n pageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<void>;\nexport type TableServerLoadAllHandler = (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<void>;\nexport type TableSettingsHandler = (settings: TableSettings) => void | Promise<void>;\nexport type TablePrintSettings = {\n allRows: boolean;\n orientation: 'portrait' | 'landscape';\n size: 'A3' | 'A4' | 'A5' | 'letter' | 'legal';\n splitGroups: boolean;\n};\nexport type TablePrintHandler = (settings: TableSettings, printSettings: TablePrintSettings) => Promise<void>;\nexport type TableShortcuts<TType = unknown> = Record<string, TableShortcutHandlerFn<TType> | TableShortcutHandlerObject<TType>>;\nexport type TableCustomSettingsRenderer = (props: TableSettings) => React.ReactElement<MenuItemProps>[];\nexport type TableEmptyStateReason = 'empty' | 'filtering' | 'searching';\nexport type TableEmptyStateRenderer = (props: { reason: TableEmptyStateReason }) => React.JSX.Element | null;\nexport type TableEvent = 'editing-mode';\nexport type TableEventHandler = (event: TableEvent, data?: object) => void;\n\n// settings\nexport type TableSettings = {\n columnFilters?: ReactTableColumnFilterState;\n columnOrder?: ReactTableColumnOrderState;\n columnPinning?: ReactTableColumnPinningState;\n columnSizing?: ReactTableColumnSizingState;\n columnVisibility?: ReactTableColumnVisibilityState;\n excludeUnmatchedRecordsInSearch?: boolean;\n fontSize?: TableFontSize;\n rowHeight?: TableRowHeight;\n searchQuery?: string;\n sorting?: ReactTableSortingState;\n};\nexport type TableEnableSettingsOptions = {\n columnOrder: boolean;\n columnPinning: boolean;\n columnSizing: boolean;\n columnVisibility: boolean;\n excludeUnmatchedRecordsInSearch: boolean;\n fontSize: boolean;\n grouping: boolean;\n rowHeight: boolean;\n sorting: boolean;\n};\n\n// props\nexport type TableConditionalRowProp<TType = unknown> = boolean | ((row: TType) => boolean);\nexport type TableFeatureProps<TType = unknown> = {\n // react-table built-in\n enableFiltering?: boolean;\n enableSearch?: boolean;\n enableSorting?: boolean;\n enableColumnFreezing?: boolean;\n enableColumnHiding?: boolean;\n enableColumnResizing?: boolean;\n enableRowExpansion?: boolean;\n enableRowExpansionAll?: boolean;\n enableRowSelection?: TableConditionalRowProp<TType>;\n\n // custom -- common between all table types\n enableColumnOrdering?: boolean;\n enableFontSize?: boolean;\n enableFooter?: boolean;\n enablePrinting?: boolean;\n enableRowActions?: boolean;\n enableRowActive?: boolean;\n enableRowClick?: TableConditionalRowProp<TType>;\n enableRowDrag?: boolean;\n enableRowDrop?: boolean;\n enableRowGoto?: boolean;\n enableRowHeight?: boolean;\n enableSaveSettings?: boolean | Partial<TableEnableSettingsOptions>;\n enableSaveSettingsLocally?: boolean;\n};\n\nexport type TableChild = React.JSX.Element | React.JSX.Element[] | boolean | null | undefined;\n\n// Base props\ntype TableCommonBaseProps<TType = unknown> = TableFeatureProps<TType> & {\n children: TableChild | TableChild[];\n data: TType[];\n id: string;\n\n // misc\n customSettings?: TableCustomSettingsRenderer;\n defaultColumnFreezingIndex?: number;\n defaultRowActiveIndex?: number;\n defaultRowGroupColumnId?: keyof TType;\n defaultSettings?: TableSettings;\n emptyState?: TableEmptyStateRenderer;\n enableLocalKeyboardShortcuts?: boolean;\n preset?: TablePreset;\n rowActions?: TableRowActionRenderer<TType>[];\n rowActionsForGroup?: TableRowActionGroupRenderer<TType>[];\n rowActionsLength?: number;\n rowExpansionRenderer?: TableRowExpansionRenderer<TType>;\n shortcuts?: TableShortcuts<TType>;\n toolbarLeft?: React.JSX.Element;\n toolbarRight?: React.JSX.Element;\n toolbarPanel?: React.JSX.Element;\n\n // handlers\n onEvent?: TableEventHandler;\n onRowActive?: TableRowActiveHandler<TType>;\n onRowClick?: TableRowClickHandler<TType>;\n onRowDrag?: TableRowDragHandler<TType>;\n onRowDrop?: TableRowDropHandler<TType>;\n onRowGoto?: TableRowGotoHandler;\n onRowSelect?: TableRowSelectHandler<TType>;\n\n // state change handlers\n onChangeFilter?: TableFilterHandler;\n onChangeSearch?: TableSearchHandler;\n onChangeSettings?: TableSettingsHandler;\n onChangeSort?: TableSortHandler;\n onPrint?: TablePrintHandler;\n};\n\n// Branch 1: Client-side without controlled selection\n// selectedRows is 'never' to force TypeScript to require rowIdentityAccessor when selectedRows is used\ntype TableClientPropsBase<TType = unknown> = TableCommonBaseProps<TType> & {\n length?: never;\n loadAll?: never;\n loadPage?: never;\n pageSize?: never;\n pages?: never;\n _experimentalDataLoader2?: never;\n\n rowIdentityAccessor?: keyof TType; // Optional\n selectedRows?: never; // Forbidden\n};\n\n// Branch 2: Server-side without controlled selection\ntype TableServerPropsBase<TType = unknown> = TableCommonBaseProps<TType> & {\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n pageSize?: number;\n pages?: number[];\n _experimentalDataLoader2?: boolean;\n\n rowIdentityAccessor?: keyof TType; // Optional\n selectedRows?: never; // Forbidden\n};\n\n// Branch 3: Client-side with controlled selection\n// Both rowIdentityAccessor and selectedRows are required\ntype TableClientPropsWithSelection<TType = unknown> = TableCommonBaseProps<TType> & {\n length?: never;\n loadAll?: never;\n loadPage?: never;\n pageSize?: never;\n pages?: never;\n _experimentalDataLoader2?: never;\n\n rowIdentityAccessor: keyof TType;\n selectedRows: string[];\n};\n\n// Branch 4: Server-side with controlled selection\n// Both rowIdentityAccessor and selectedRows are required\ntype TableServerPropsWithSelection<TType = unknown> = TableCommonBaseProps<TType> & {\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n pageSize?: number;\n pages?: number[];\n _experimentalDataLoader2?: boolean;\n\n rowIdentityAccessor: keyof TType;\n selectedRows: string[];\n};\n\n// Discriminated union: providing selectedRows forces TypeScript to use branches 3/4, which require rowIdentityAccessor\nexport type TableClientProps<TType = unknown> = TableClientPropsBase<TType> | TableClientPropsWithSelection<TType>;\nexport type TableServerProps<TType = unknown> = TableServerPropsBase<TType> | TableServerPropsWithSelection<TType>;\n\n// For backward compatibility (used by hooks/internals that don't care about the constraint)\nexport type TableCommonProps<TType = unknown> = TableCommonBaseProps<TType> & {\n rowIdentityAccessor?: keyof TType;\n selectedRows?: string[];\n};\n\nexport type TableProps<TType = unknown> = TableClientProps<TType> | TableServerProps<TType>;\n\nexport type TableColumnDataTypeOptions = {\n currency?: string;\n decimals?: number;\n useGrouping?: boolean;\n};\n\nexport type TableColumnDataTypeOptionsHandler<TType = unknown, TOptions = TableColumnDataTypeOptions> =\n TOptions | ((row: TType) => TOptions);\n\nexport type TableColumnDataTypeProps<TType = unknown> =\n // number should allow currency, decimals and useGrouping\n | {\n dataType?: 'number';\n dataTypeOptions?: TableColumnDataTypeOptionsHandler<\n TType,\n Pick<TableColumnDataTypeOptions, 'currency' | 'decimals' | 'useGrouping'>\n >;\n }\n // amount should allow currency\n | {\n dataType?: 'amount';\n dataTypeOptions?: TableColumnDataTypeOptionsHandler<TType, Pick<TableColumnDataTypeOptions, 'currency'>>;\n }\n // percentage should allow decimals and useGrouping\n | {\n dataType?: 'percentage';\n dataTypeOptions?: TableColumnDataTypeOptionsHandler<\n TType,\n Pick<TableColumnDataTypeOptions, 'decimals' | 'useGrouping'>\n >;\n }\n // others should not allow options\n | {\n dataType?: Omit<TableColumnDataType, 'number' | 'amount' | 'percentage'>;\n dataTypeOptions?: never;\n };\n\nexport type TableColumnIdentifierProps<TType = unknown> =\n // type correctly if an accessor is provided\n | {\n [Key in DotNotationPaths<TType>]: {\n accessor: Key;\n id?: string;\n renderer?: TableColumnRenderer<TType, DotNotationPathValue<TType, Key>> | undefined;\n aggregate?: TableColumnRendererAggregate<TType, DotNotationPathValue<TType, Key>> | undefined;\n };\n }[DotNotationPaths<TType>]\n // otherwise fall back to unknown\n | {\n accessor?: never;\n id: string;\n renderer?: TableColumnRenderer<TType, undefined> | undefined;\n aggregate?: TableColumnRendererAggregate<TType, undefined> | undefined;\n };\n\nexport type TableColumnProps<TType = unknown> = TableColumnIdentifierProps<TType> &\n TableColumnDataTypeProps<TType> & {\n // renderers - some that require Key are below, to ensure correct typing\n control?: TableColumnRendererControl<TType> | undefined;\n footer?: TableColumnRendererFooter<TType> | undefined;\n header: TableColumnRendererHeader;\n // options\n /** Aggregation function to be used when the column is part of a grouped row */\n aggregationFn?: 'auto' | ReactTableBuiltInAggregationFn;\n align?: TableColumnAlignment;\n className?: TableColumnClassNameHandler<TType>;\n dataType?: TableColumnDataType;\n defaultHidden?: boolean;\n defaultWidth?: TableColumnWidth;\n emptyState?: React.ReactNode;\n enableEditing?: boolean;\n enableFiltering?: boolean;\n enableGrouping?: boolean;\n enableHiding?: boolean;\n enableOrdering?: boolean;\n enablePrinting?: boolean;\n enableResizing?: boolean;\n enableSearch?: boolean;\n enableSorting?: boolean;\n enableTruncate?: boolean;\n filters?: TableFilterComparator[];\n headerClassName?: string;\n menu?: TableColumnMenu;\n minWidth?: number;\n sort?: TableColumnSortDirection;\n sortFn?: TableColumnSortFn<TType>;\n tooltip?: string;\n };\n\nexport type TableGroupProps = {\n children: (React.JSX.Element | boolean | null | undefined)[];\n header: string;\n id: string;\n};\n\nexport type TableTexts = {\n columns: {\n actions: {\n tooltip: string;\n };\n drag: {\n tooltip: string;\n };\n expansion: {\n collapse: string;\n collapseAll: string;\n expand: string;\n expandAll: string;\n };\n menu: {\n editFilter: string;\n filter: string;\n freezeFirstColumn: string;\n freezeUptoColumn: string;\n gotoRow: string;\n hideColumn: string;\n unfreezeColumns: string;\n sorting: string;\n sortingOrder: {\n ascending: string;\n descending: string;\n unsorted: string;\n };\n };\n resize: {\n tooltip: string;\n };\n select: {\n deselect: string;\n deselectAll: string;\n select: string;\n selectAll: string;\n };\n };\n columnSettings: {\n button: string;\n noResults: string;\n search: string;\n tooltip: string;\n };\n filters: {\n button: string;\n buttons: {\n addFilter: string;\n clearFilters: string;\n cancel: string;\n clear: string;\n apply: string;\n };\n comparators: {\n contains: string;\n doesNotContain: string;\n isEqualTo: string;\n isNotEqualTo: string;\n isGreaterThan: string;\n isLessThan: string;\n isBetween: string;\n isOneOf: string;\n isNoneOf: string;\n isEmpty: string;\n isNotEmpty: string;\n isBefore: string;\n isAfter: string;\n isLessThanOrEqualTo: string;\n isGreaterThanOrEqualTo: string;\n isOnOrBefore: string;\n isOnOrAfter: string;\n hasAnyOf: string;\n hasAllOf: string;\n hasNoneOf: string;\n };\n conditions: {\n and: string;\n where: string;\n };\n emptyFilter: {\n condition: string;\n value: string;\n };\n hiddenColumn: string;\n hiddenGroupedColumn: string;\n tooltip: string;\n total: string;\n };\n fontSize: {\n tooltip: string;\n sizes: {\n small: string;\n medium: string;\n large: string;\n };\n };\n footer: {\n summary: {\n count: string;\n records: string;\n selected: string;\n };\n };\n print: {\n error: string;\n loading: string;\n tooltip: string;\n warningDialog: {\n title: string;\n description: string;\n checkboxVisibilityLabel: string;\n cancelButtonText: string;\n printButtonText: string;\n };\n settingsDialog: {\n title: string;\n size: string;\n sizeA5: string;\n sizeA4: string;\n sizeA3: string;\n sizeLetter: string;\n sizeLegal: string;\n orientation: string;\n orientationLandscape: string;\n orientationPortrait: string;\n rows: string;\n rowsAll: string;\n rowsSelected: string;\n layout: string;\n layoutSplitGroups: string;\n };\n };\n rowHeight: {\n tooltip: string;\n sizes: {\n short: string;\n medium: string;\n tall: string;\n extraTall: string;\n };\n };\n search: {\n excludeUnmatchedResults: string;\n placeholder: string;\n };\n otherOptions: {\n tooltip: string;\n };\n};\n"],"names":["TableFilterComparator"],"mappings":"AA0BO,IAAK,0CAAAA,2BAAL;AACHA,yBAAAA,uBAAA,cAAW,CAAA,IAAX;AACAA,yBAAAA,uBAAA,oBAAiB,CAAA,IAAjB;AACAA,yBAAAA,uBAAA,eAAY,CAAA,IAAZ;AACAA,yBAAAA,uBAAA,kBAAe,CAAA,IAAf;AACAA,yBAAAA,uBAAA,mBAAgB,CAAA,IAAhB;AACAA,yBAAAA,uBAAA,gBAAa,CAAA,IAAb;AACAA,yBAAAA,uBAAA,eAAY,CAAA,IAAZ;AACAA,yBAAAA,uBAAA,aAAU,CAAA,IAAV;AACAA,yBAAAA,uBAAA,gBAAa,CAAA,IAAb;AACAA,yBAAAA,uBAAA,yBAAsB,CAAA,IAAtB;AACAA,yBAAAA,uBAAA,4BAAyB,EAAA,IAAzB;AACAA,yBAAAA,uBAAA,cAAW,EAAA,IAAX;AACAA,yBAAAA,uBAAA,cAAW,EAAA,IAAX;AACAA,yBAAAA,uBAAA,eAAY,EAAA,IAAZ;AACAA,yBAAAA,uBAAA,aAAU,EAAA,IAAV;AACAA,yBAAAA,uBAAA,cAAW,EAAA,IAAX;AAhBQ,SAAAA;AAAA,GAAA,yBAAA,CAAA,CAAA;"}
|
|
1
|
+
{"version":3,"file":"types.js","sources":["../../../src/primitives/Table/types.ts"],"sourcesContent":["import type {\n ColumnFilter as ReactTableColumnFilter,\n ColumnFiltersState as ReactTableColumnFilterState,\n ColumnOrderState as ReactTableColumnOrderState,\n ColumnPinningState as ReactTableColumnPinningState,\n ColumnSort as ReactTableColumnSort,\n ColumnSizingState as ReactTableColumnSizingState,\n VisibilityState as ReactTableColumnVisibilityState,\n SortingState as ReactTableSortingState,\n BuiltInAggregationFn as ReactTableBuiltInAggregationFn,\n BuiltInSortingFn as ReactTableBuiltInSortingFn,\n} from '@tanstack/react-table';\n\nimport type { MenuItemProps } from '@/components';\nimport type { DotNotationPaths, FontSize, FontSizes, DotNotationPathValue } from '@/types';\n\nexport type TableRef = HTMLTableElement & {\n instance: {\n resetFiltering: () => void;\n resetPagination: () => Promise<void>;\n resetRowExpansion: () => void;\n resetRowSelection: () => void;\n resetSorting: () => void;\n };\n};\n\n// filtering\nexport enum TableFilterComparator {\n Contains = 0,\n DoesNotContain = 1,\n IsEqualTo = 2,\n IsNotEqualTo = 3,\n IsGreaterThan = 4,\n IsLessThan = 5,\n IsBetween = 6,\n IsEmpty = 7,\n IsNotEmpty = 8,\n IsLessThanOrEqualTo = 9,\n IsGreaterThanOrEqualTo = 10,\n HasAnyOf = 11,\n HasAllOf = 12,\n HasNoneOf = 13,\n IsOneOf = 14,\n IsNoneOf = 15,\n}\nexport type TableFilterValue = {\n comparator: TableFilterComparator;\n value: any;\n};\nexport type TableFilter = {\n id: string;\n value: TableFilterValue;\n};\n\n// columns\nexport type TableColumnAlignment = 'left' | 'center' | 'right';\nexport type TableColumnClassNameHandler<TType = unknown> = string | ((row: TType) => string | undefined);\nexport type TableColumnDataType =\n // base\n | 'text'\n | 'boolean'\n // dates\n | 'date'\n | 'time'\n | 'datetime'\n // numbers\n | 'number'\n | 'amount'\n | 'percentage';\nexport type TableColumnFilter = ReactTableColumnFilter;\nexport type TableColumnMenu = ((columnId: string) => React.ReactNode | null)[];\nexport type TableColumnRendererArgs<TType, TValue> = TValue extends undefined\n ? { formattedValue: undefined; row: TType; value: undefined }\n : { formattedValue: string; row: TType; value: TValue };\nexport type TableColumnRenderer<TType, TValue = unknown> = (\n args: TableColumnRendererArgs<TType, TValue>\n) => React.JSX.Element | string | number | unknown | null;\nexport type TableColumnRendererAggregate<TType, TValue = unknown> = (\n args: TableColumnRendererArgs<TType, TValue>\n) => React.JSX.Element | string | number | unknown | null;\nexport type TableColumnRendererControl<TType = unknown> =\n | ((props: TableColumnRendererControlProps, row?: TType, filterState?: TableFilter[]) => React.JSX.Element | null)\n | 'datepicker'\n | 'input'\n | 'switch'\n | 'checkbox'\n | 'textarea';\nexport type TableColumnRendererControlProps = {\n className?: string;\n disabled?: boolean;\n fontSize?: FontSize;\n invalid?: boolean;\n onBlur?: (value: any) => void;\n onKeyDown?: React.KeyboardEventHandler;\n onFocus?: React.FocusEventHandler;\n readOnly?: boolean;\n ref: React.Ref<HTMLElement>;\n setValue: (value: any) => void;\n value: any;\n};\nexport type TableColumnRendererHeader = string | React.JSX.Element;\nexport type TableColumnRendererFooter<TType> = (rows: TType[]) => React.JSX.Element | string | number | null;\nexport type TableColumnSort = ReactTableColumnSort;\nexport type TableColumnSortDirection = 'asc' | 'desc';\nexport type TableColumnSortFn<TType = unknown> =\n ((rowA: TType, rowB: TType, columnId: string) => -1 | 0 | 1) | ReactTableBuiltInSortingFn | 'auto';\nexport type TableColumnWidth = number | 'grow';\n\n// rows\nexport type TableRowActionRenderer<TType = unknown> = (\n row: TType,\n helpers: {\n editing?: {\n isEditing: boolean;\n removeRowChanges: () => Promise<void>;\n save: () => Promise<boolean>;\n };\n }\n) => React.JSX.Element | null;\n\nexport type TableRowActionGroupRenderer<TType = unknown> = (rows: TType[]) => React.JSX.Element | null;\nexport type TableRowClickHandler<TType = unknown> = (row: TType) => void;\nexport type TableRowDragHandler<TType = unknown> = (\n rows: TType[],\n showPlaceholder: (text: string) => void,\n setDataTransfer: (data: string) => void\n) => void;\nexport type TableRowDropHandler<TType = unknown> = (event: React.DragEvent, row: TType) => void;\nexport type TableRowGotoHandler = (\n column: string,\n query: string,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n search: string | undefined\n) => Promise<number>;\nexport type TableRowHeight = 'short' | 'medium' | 'tall' | 'extra-tall';\nexport type TableRowActiveHandler<TType = unknown> = (row: TType | undefined) => void;\nexport type TableRowSelectHandler<TType = unknown> = (rows: TType[], ids: string[]) => void;\nexport type TableRowWithMetaData<TType = unknown> = TType & {\n _meta?: {\n layout?: 'heading' | 'summary' | 'item';\n };\n};\n\n// shortcuts\nexport type TableShortcutHandlerFn<TType = unknown> = (row: TType) => void;\nexport type TableShortcutHandlerObject<TType = unknown> = {\n handler: TableShortcutHandlerFn<TType>;\n meta?: boolean;\n shift?: boolean;\n};\n\n// table\nexport type TableSortHandler = (sorting: TableColumnSort[]) => Promise<void> | void;\nexport type TableFilterHandler = (filters: TableColumnFilter[], hiddenColumns: string[]) => Promise<void> | void;\nexport type TableSearchHandler = (search: string | undefined, hiddenColumns: string[]) => Promise<void> | void;\nexport type TableFontSize = keyof typeof FontSizes;\nexport type TablePreset = 'complex' | 'list' | 'simple';\nexport type TableRowExpansionRenderer<TType = unknown> = (row: TType) => (() => React.JSX.Element) | null;\nexport type TableScrollToIndexHandler = (index: number, options?: { align: 'start' | 'center' | 'end' | 'auto' }) => void;\nexport type TableServerLoadPageHandler = (\n pageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<void>;\nexport type TableServerLoadAllHandler = (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<void>;\n// discards the currently loaded pages and loads the first page again, using the last used\n// sorting, filters, hidden columns and search\nexport type TableServerResetPaginationHandler = () => Promise<void>;\nexport type TableSettingsHandler = (settings: TableSettings) => void | Promise<void>;\nexport type TablePrintSettings = {\n allRows: boolean;\n orientation: 'portrait' | 'landscape';\n size: 'A3' | 'A4' | 'A5' | 'letter' | 'legal';\n splitGroups: boolean;\n};\nexport type TablePrintHandler = (settings: TableSettings, printSettings: TablePrintSettings) => Promise<void>;\nexport type TableShortcuts<TType = unknown> = Record<string, TableShortcutHandlerFn<TType> | TableShortcutHandlerObject<TType>>;\nexport type TableCustomSettingsRenderer = (props: TableSettings) => React.ReactElement<MenuItemProps>[];\nexport type TableEmptyStateReason = 'empty' | 'filtering' | 'searching';\nexport type TableEmptyStateRenderer = (props: { reason: TableEmptyStateReason }) => React.JSX.Element | null;\nexport type TableEvent = 'editing-mode';\nexport type TableEventHandler = (event: TableEvent, data?: object) => void;\n\n// settings\nexport type TableSettings = {\n columnFilters?: ReactTableColumnFilterState;\n columnOrder?: ReactTableColumnOrderState;\n columnPinning?: ReactTableColumnPinningState;\n columnSizing?: ReactTableColumnSizingState;\n columnVisibility?: ReactTableColumnVisibilityState;\n excludeUnmatchedRecordsInSearch?: boolean;\n fontSize?: TableFontSize;\n rowHeight?: TableRowHeight;\n searchQuery?: string;\n sorting?: ReactTableSortingState;\n};\nexport type TableEnableSettingsOptions = {\n columnOrder: boolean;\n columnPinning: boolean;\n columnSizing: boolean;\n columnVisibility: boolean;\n excludeUnmatchedRecordsInSearch: boolean;\n fontSize: boolean;\n grouping: boolean;\n rowHeight: boolean;\n sorting: boolean;\n};\n\n// props\nexport type TableConditionalRowProp<TType = unknown> = boolean | ((row: TType) => boolean);\nexport type TableFeatureProps<TType = unknown> = {\n // react-table built-in\n enableFiltering?: boolean;\n enableSearch?: boolean;\n enableSorting?: boolean;\n enableColumnFreezing?: boolean;\n enableColumnHiding?: boolean;\n enableColumnResizing?: boolean;\n enableRowExpansion?: boolean;\n enableRowExpansionAll?: boolean;\n enableRowSelection?: TableConditionalRowProp<TType>;\n\n // custom -- common between all table types\n enableColumnOrdering?: boolean;\n enableFontSize?: boolean;\n enableFooter?: boolean;\n enablePrinting?: boolean;\n enableRowActions?: boolean;\n enableRowActive?: boolean;\n enableRowClick?: TableConditionalRowProp<TType>;\n enableRowDrag?: boolean;\n enableRowDrop?: boolean;\n enableRowGoto?: boolean;\n enableRowHeight?: boolean;\n enableSaveSettings?: boolean | Partial<TableEnableSettingsOptions>;\n enableSaveSettingsLocally?: boolean;\n};\n\nexport type TableChild = React.JSX.Element | React.JSX.Element[] | boolean | null | undefined;\n\n// Base props\ntype TableCommonBaseProps<TType = unknown> = TableFeatureProps<TType> & {\n children: TableChild | TableChild[];\n data: TType[];\n id: string;\n\n // misc\n customSettings?: TableCustomSettingsRenderer;\n defaultColumnFreezingIndex?: number;\n defaultRowActiveIndex?: number;\n defaultRowGroupColumnId?: keyof TType;\n defaultSettings?: TableSettings;\n emptyState?: TableEmptyStateRenderer;\n enableLocalKeyboardShortcuts?: boolean;\n preset?: TablePreset;\n rowActions?: TableRowActionRenderer<TType>[];\n rowActionsForGroup?: TableRowActionGroupRenderer<TType>[];\n rowActionsLength?: number;\n rowExpansionRenderer?: TableRowExpansionRenderer<TType>;\n shortcuts?: TableShortcuts<TType>;\n toolbarLeft?: React.JSX.Element;\n toolbarRight?: React.JSX.Element;\n toolbarPanel?: React.JSX.Element;\n\n // handlers\n onEvent?: TableEventHandler;\n onRowActive?: TableRowActiveHandler<TType>;\n onRowClick?: TableRowClickHandler<TType>;\n onRowDrag?: TableRowDragHandler<TType>;\n onRowDrop?: TableRowDropHandler<TType>;\n onRowGoto?: TableRowGotoHandler;\n onRowSelect?: TableRowSelectHandler<TType>;\n\n // state change handlers\n onChangeFilter?: TableFilterHandler;\n onChangeSearch?: TableSearchHandler;\n onChangeSettings?: TableSettingsHandler;\n onChangeSort?: TableSortHandler;\n onPrint?: TablePrintHandler;\n};\n\n// Branch 1: Client-side without controlled selection\n// selectedRows is 'never' to force TypeScript to require rowIdentityAccessor when selectedRows is used\ntype TableClientPropsBase<TType = unknown> = TableCommonBaseProps<TType> & {\n length?: never;\n loadAll?: never;\n loadPage?: never;\n pageSize?: never;\n pages?: never;\n resetPagination?: never;\n _experimentalDataLoader2?: never;\n\n rowIdentityAccessor?: keyof TType;\n selectedRows?: never;\n};\n\n// Branch 2: Server-side without controlled selection\ntype TableServerPropsBase<TType = unknown> = TableCommonBaseProps<TType> & {\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n pageSize?: number;\n pages?: number[];\n resetPagination?: TableServerResetPaginationHandler;\n _experimentalDataLoader2?: boolean;\n\n rowIdentityAccessor?: keyof TType;\n selectedRows?: never;\n};\n\n// Branch 3: Client-side with controlled selection\n// Both rowIdentityAccessor and selectedRows are required\ntype TableClientPropsWithSelection<TType = unknown> = TableCommonBaseProps<TType> & {\n length?: never;\n loadAll?: never;\n loadPage?: never;\n pageSize?: never;\n pages?: never;\n resetPagination?: never;\n _experimentalDataLoader2?: never;\n\n rowIdentityAccessor: keyof TType;\n selectedRows: string[];\n};\n\n// Branch 4: Server-side with controlled selection\n// Both rowIdentityAccessor and selectedRows are required\ntype TableServerPropsWithSelection<TType = unknown> = TableCommonBaseProps<TType> & {\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n pageSize?: number;\n pages?: number[];\n resetPagination?: TableServerResetPaginationHandler;\n _experimentalDataLoader2?: boolean;\n\n rowIdentityAccessor: keyof TType;\n selectedRows: string[];\n};\n\n// Discriminated union: providing selectedRows forces TypeScript to use branches 3/4, which require rowIdentityAccessor\nexport type TableClientProps<TType = unknown> = TableClientPropsBase<TType> | TableClientPropsWithSelection<TType>;\nexport type TableServerProps<TType = unknown> = TableServerPropsBase<TType> | TableServerPropsWithSelection<TType>;\n\n// For backward compatibility (used by hooks/internals that don't care about the constraint)\nexport type TableCommonProps<TType = unknown> = TableCommonBaseProps<TType> & {\n rowIdentityAccessor?: keyof TType;\n selectedRows?: string[];\n};\n\nexport type TableProps<TType = unknown> = TableClientProps<TType> | TableServerProps<TType>;\n\nexport type TableColumnDataTypeOptions = {\n currency?: string;\n decimals?: number;\n useGrouping?: boolean;\n};\n\nexport type TableColumnDataTypeOptionsHandler<TType = unknown, TOptions = TableColumnDataTypeOptions> =\n TOptions | ((row: TType) => TOptions);\n\nexport type TableColumnDataTypeProps<TType = unknown> =\n // number should allow currency, decimals and useGrouping\n | {\n dataType?: 'number';\n dataTypeOptions?: TableColumnDataTypeOptionsHandler<\n TType,\n Pick<TableColumnDataTypeOptions, 'currency' | 'decimals' | 'useGrouping'>\n >;\n }\n // amount should allow currency\n | {\n dataType?: 'amount';\n dataTypeOptions?: TableColumnDataTypeOptionsHandler<TType, Pick<TableColumnDataTypeOptions, 'currency'>>;\n }\n // percentage should allow decimals and useGrouping\n | {\n dataType?: 'percentage';\n dataTypeOptions?: TableColumnDataTypeOptionsHandler<\n TType,\n Pick<TableColumnDataTypeOptions, 'decimals' | 'useGrouping'>\n >;\n }\n // others should not allow options\n | {\n dataType?: Omit<TableColumnDataType, 'number' | 'amount' | 'percentage'>;\n dataTypeOptions?: never;\n };\n\nexport type TableColumnIdentifierProps<TType = unknown> =\n // type correctly if an accessor is provided\n | {\n [Key in DotNotationPaths<TType>]: {\n accessor: Key;\n id?: string;\n renderer?: TableColumnRenderer<TType, DotNotationPathValue<TType, Key>> | undefined;\n aggregate?: TableColumnRendererAggregate<TType, DotNotationPathValue<TType, Key>> | undefined;\n };\n }[DotNotationPaths<TType>]\n // otherwise fall back to unknown\n | {\n accessor?: never;\n id: string;\n renderer?: TableColumnRenderer<TType, undefined> | undefined;\n aggregate?: TableColumnRendererAggregate<TType, undefined> | undefined;\n };\n\nexport type TableColumnProps<TType = unknown> = TableColumnIdentifierProps<TType> &\n TableColumnDataTypeProps<TType> & {\n // renderers - some that require Key are below, to ensure correct typing\n control?: TableColumnRendererControl<TType> | undefined;\n footer?: TableColumnRendererFooter<TType> | undefined;\n header: TableColumnRendererHeader;\n // options\n /** Aggregation function to be used when the column is part of a grouped row */\n aggregationFn?: 'auto' | ReactTableBuiltInAggregationFn;\n align?: TableColumnAlignment;\n className?: TableColumnClassNameHandler<TType>;\n dataType?: TableColumnDataType;\n defaultHidden?: boolean;\n defaultWidth?: TableColumnWidth;\n emptyState?: React.ReactNode;\n enableEditing?: boolean;\n enableFiltering?: boolean;\n enableGrouping?: boolean;\n enableHiding?: boolean;\n enableOrdering?: boolean;\n enablePrinting?: boolean;\n enableResizing?: boolean;\n enableSearch?: boolean;\n enableSorting?: boolean;\n enableTruncate?: boolean;\n filters?: TableFilterComparator[];\n headerClassName?: string;\n menu?: TableColumnMenu;\n minWidth?: number;\n sort?: TableColumnSortDirection;\n sortFn?: TableColumnSortFn<TType>;\n tooltip?: string;\n };\n\nexport type TableGroupProps = {\n children: (React.JSX.Element | boolean | null | undefined)[];\n header: string;\n id: string;\n};\n\nexport type TableTexts = {\n columns: {\n actions: {\n tooltip: string;\n };\n drag: {\n tooltip: string;\n };\n expansion: {\n collapse: string;\n collapseAll: string;\n expand: string;\n expandAll: string;\n };\n menu: {\n editFilter: string;\n filter: string;\n freezeFirstColumn: string;\n freezeUptoColumn: string;\n gotoRow: string;\n hideColumn: string;\n unfreezeColumns: string;\n sorting: string;\n sortingOrder: {\n ascending: string;\n descending: string;\n unsorted: string;\n };\n };\n resize: {\n tooltip: string;\n };\n select: {\n deselect: string;\n deselectAll: string;\n select: string;\n selectAll: string;\n };\n };\n columnSettings: {\n button: string;\n noResults: string;\n search: string;\n tooltip: string;\n };\n filters: {\n button: string;\n buttons: {\n addFilter: string;\n clearFilters: string;\n cancel: string;\n clear: string;\n apply: string;\n };\n comparators: {\n contains: string;\n doesNotContain: string;\n isEqualTo: string;\n isNotEqualTo: string;\n isGreaterThan: string;\n isLessThan: string;\n isBetween: string;\n isOneOf: string;\n isNoneOf: string;\n isEmpty: string;\n isNotEmpty: string;\n isBefore: string;\n isAfter: string;\n isLessThanOrEqualTo: string;\n isGreaterThanOrEqualTo: string;\n isOnOrBefore: string;\n isOnOrAfter: string;\n hasAnyOf: string;\n hasAllOf: string;\n hasNoneOf: string;\n };\n conditions: {\n and: string;\n where: string;\n };\n emptyFilter: {\n condition: string;\n value: string;\n };\n hiddenColumn: string;\n hiddenGroupedColumn: string;\n tooltip: string;\n total: string;\n };\n fontSize: {\n tooltip: string;\n sizes: {\n small: string;\n medium: string;\n large: string;\n };\n };\n footer: {\n summary: {\n count: string;\n records: string;\n selected: string;\n };\n };\n print: {\n error: string;\n loading: string;\n tooltip: string;\n warningDialog: {\n title: string;\n description: string;\n checkboxVisibilityLabel: string;\n cancelButtonText: string;\n printButtonText: string;\n };\n settingsDialog: {\n title: string;\n size: string;\n sizeA5: string;\n sizeA4: string;\n sizeA3: string;\n sizeLetter: string;\n sizeLegal: string;\n orientation: string;\n orientationLandscape: string;\n orientationPortrait: string;\n rows: string;\n rowsAll: string;\n rowsSelected: string;\n layout: string;\n layoutSplitGroups: string;\n };\n };\n rowHeight: {\n tooltip: string;\n sizes: {\n short: string;\n medium: string;\n tall: string;\n extraTall: string;\n };\n };\n search: {\n excludeUnmatchedResults: string;\n placeholder: string;\n };\n otherOptions: {\n tooltip: string;\n };\n};\n"],"names":["TableFilterComparator"],"mappings":"AA2BO,IAAK,0CAAAA,2BAAL;AACHA,yBAAAA,uBAAA,cAAW,CAAA,IAAX;AACAA,yBAAAA,uBAAA,oBAAiB,CAAA,IAAjB;AACAA,yBAAAA,uBAAA,eAAY,CAAA,IAAZ;AACAA,yBAAAA,uBAAA,kBAAe,CAAA,IAAf;AACAA,yBAAAA,uBAAA,mBAAgB,CAAA,IAAhB;AACAA,yBAAAA,uBAAA,gBAAa,CAAA,IAAb;AACAA,yBAAAA,uBAAA,eAAY,CAAA,IAAZ;AACAA,yBAAAA,uBAAA,aAAU,CAAA,IAAV;AACAA,yBAAAA,uBAAA,gBAAa,CAAA,IAAb;AACAA,yBAAAA,uBAAA,yBAAsB,CAAA,IAAtB;AACAA,yBAAAA,uBAAA,4BAAyB,EAAA,IAAzB;AACAA,yBAAAA,uBAAA,cAAW,EAAA,IAAX;AACAA,yBAAAA,uBAAA,cAAW,EAAA,IAAX;AACAA,yBAAAA,uBAAA,eAAY,EAAA,IAAZ;AACAA,yBAAAA,uBAAA,aAAU,EAAA,IAAV;AACAA,yBAAAA,uBAAA,cAAW,EAAA,IAAX;AAhBQ,SAAAA;AAAA,GAAA,yBAAA,CAAA,CAAA;"}
|
|
@@ -68,7 +68,7 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: useTable
|
|
|
68
68
|
delete nextCache[unloadedPage];
|
|
69
69
|
}
|
|
70
70
|
} else if (direction === "backward" && currentData.rows.length >= DATASET_SIZE) {
|
|
71
|
-
const unloadedPage = currentData.pages
|
|
71
|
+
const unloadedPage = currentData.pages.at(-1);
|
|
72
72
|
if (unloadedPage !== void 0) {
|
|
73
73
|
delete nextCache[unloadedPage];
|
|
74
74
|
}
|
|
@@ -138,7 +138,7 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: useTable
|
|
|
138
138
|
cache: nextCache,
|
|
139
139
|
pages: nextPages,
|
|
140
140
|
rows,
|
|
141
|
-
lastFetchedPage: pageIndexes
|
|
141
|
+
lastFetchedPage: pageIndexes.at(-1)
|
|
142
142
|
});
|
|
143
143
|
requestAnimationFrame(() => {
|
|
144
144
|
_pendingPageRequests.current = {};
|
|
@@ -170,6 +170,38 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: useTable
|
|
|
170
170
|
const handleSearch = async (search, hiddenColumns) => {
|
|
171
171
|
return await loadPage(0, _lastUsedSorting.current, _lastUsedFilters.current, hiddenColumns, search);
|
|
172
172
|
};
|
|
173
|
+
const resetPagination = async () => {
|
|
174
|
+
const sorting = _lastUsedSorting.current;
|
|
175
|
+
const filters = _lastUsedFilters.current;
|
|
176
|
+
const hiddenColumns = _lastUsedHiddenColumns.current;
|
|
177
|
+
const search = _lastUsedSearch.current;
|
|
178
|
+
const dataKey = getDataKey(sorting, filters, hiddenColumns, search);
|
|
179
|
+
const pageIndexes = [0, 1];
|
|
180
|
+
_pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});
|
|
181
|
+
try {
|
|
182
|
+
const responses = await Promise.all(
|
|
183
|
+
pageIndexes.map((pageIndex) => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))
|
|
184
|
+
);
|
|
185
|
+
length.current = responses[0]?.length;
|
|
186
|
+
const pageCount = Math.ceil((responses[0]?.length ?? 0) / pageSize);
|
|
187
|
+
const nextPages = pageIndexes.filter((pageIndex) => pageIndex === 0 || pageIndex < pageCount);
|
|
188
|
+
const nextCache = nextPages.reduce(
|
|
189
|
+
(acc, pageIndex) => ({ ...acc, [pageIndex]: responses[pageIndex]?.data ?? [] }),
|
|
190
|
+
{}
|
|
191
|
+
);
|
|
192
|
+
const rows = Object.values(nextCache).flat();
|
|
193
|
+
setData({
|
|
194
|
+
cache: nextCache,
|
|
195
|
+
pages: nextPages,
|
|
196
|
+
rows,
|
|
197
|
+
lastFetchedPage: nextPages.at(-1)
|
|
198
|
+
});
|
|
199
|
+
requestAnimationFrame(() => {
|
|
200
|
+
_pendingPageRequests.current = {};
|
|
201
|
+
});
|
|
202
|
+
} catch {
|
|
203
|
+
}
|
|
204
|
+
};
|
|
173
205
|
return [
|
|
174
206
|
{
|
|
175
207
|
data: data.rows,
|
|
@@ -181,6 +213,7 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: useTable
|
|
|
181
213
|
onChangeSearch: handleSearch,
|
|
182
214
|
onChangeSort: handleSort,
|
|
183
215
|
pageSize,
|
|
216
|
+
resetPagination,
|
|
184
217
|
_experimentalDataLoader2: true
|
|
185
218
|
},
|
|
186
219
|
invalidate
|
|
@@ -195,7 +228,7 @@ function getCurrentPage(currentPages) {
|
|
|
195
228
|
}
|
|
196
229
|
function getDirection(pageIndex, currentPages) {
|
|
197
230
|
if (currentPages.length) {
|
|
198
|
-
const lastPageIndex = currentPages
|
|
231
|
+
const lastPageIndex = currentPages.at(-1);
|
|
199
232
|
if (lastPageIndex !== void 0 && pageIndex === lastPageIndex + 1) {
|
|
200
233
|
return "forward";
|
|
201
234
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableDataLoader2.cjs","sources":["../../../src/primitives/Table/useTableDataLoader2.ts"],"sourcesContent":["import React from 'react';\n\nimport type {\n TableColumnFilter,\n TableColumnSort,\n TableFilterHandler,\n TableServerLoadPageHandler,\n TableServerLoadAllHandler,\n TableSortHandler,\n TableSearchHandler,\n} from './types';\nimport type { useTableDataLoaderOptions } from './useTableDataLoader';\nimport { DEFAULT_PAGE_SIZE } from './useTableDataLoader';\n\nconst DATASET_SIZE_MULTIPLIER = 15;\n\nexport type useTableDataPageFetcher2<TType = unknown> = (\n pageIndex: number,\n pageSize: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataAllFetcher2<TType = unknown> = (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataLoaderValues2<TType = unknown> = {\n data: TType[];\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n onChangeFilter: TableFilterHandler;\n onChangeSearch: TableSearchHandler;\n onChangeSort: TableSortHandler;\n pageSize: number;\n pages: number[];\n _experimentalDataLoader2: boolean;\n};\n\ntype Data<TType = unknown> = {\n rows: TType[];\n pages: number[];\n cache: Record<number, TType[]>;\n lastFetchedPage: number | undefined;\n};\ntype Direction = 'forward' | 'backward' | undefined;\n\nfunction getDataKey(\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) {\n return [JSON.stringify(sorting), JSON.stringify(filters), JSON.stringify(hiddenColumns), JSON.stringify(search)].join('_');\n}\n\nexport function useTableDataLoader2<TType = unknown>(\n fetchPage: useTableDataPageFetcher2<TType>,\n fetchAll: useTableDataAllFetcher2<TType>,\n options: useTableDataLoaderOptions = { pageSize: DEFAULT_PAGE_SIZE }\n): [useTableDataLoaderValues2<TType>, () => Promise<void>] {\n const { pageSize } = options;\n const DATASET_SIZE = DATASET_SIZE_MULTIPLIER * pageSize;\n\n // track the data length, we don't know it until the first request\n const length = React.useRef<number>(undefined);\n // data will be filled after the first request\n const [data, setData] = React.useState<Data<TType>>({ rows: [], pages: [], cache: {}, lastFetchedPage: undefined });\n // track which pages have been loaded to dedupe requests\n const _pendingPageRequests = React.useRef<Record<number, string>>({});\n // store last used properties\n const _lastUsedSorting = React.useRef<TableColumnSort[]>([]);\n const _lastUsedFilters = React.useRef<TableColumnFilter[]>([]);\n const _lastUsedHiddenColumns = React.useRef<string[]>([]);\n const _lastUsedSearch = React.useRef<string | undefined>(undefined);\n\n async function loadPage(\n pageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const hasDataChanged =\n JSON.stringify(sorting) !== JSON.stringify(_lastUsedSorting.current) ||\n JSON.stringify(filters) !== JSON.stringify(_lastUsedFilters.current) ||\n JSON.stringify(hiddenColumns) !== JSON.stringify(_lastUsedHiddenColumns.current) ||\n search !== _lastUsedSearch.current;\n\n if (hasDataChanged) {\n // set values so we can use them for invalidate\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // ideally we would have requests to abort, but we don't perform the fetch\n _pendingPageRequests.current = {};\n\n // we don't reset cached data here because it would result in a flicker of no data for the user,\n // instead we reset it in setState below when we have the new data to replace with\n } else {\n // if a request is already pending for this page, skip the load\n if (_pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n // if the page is already loaded, abort\n if (data.cache[pageIndex] && data.cache[pageIndex][0]) {\n return;\n }\n }\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the page as loading, so that subsequent requests don't retrigger it\n _pendingPageRequests.current[pageIndex] = dataKey;\n\n try {\n // fetch the page\n const response = await fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search);\n\n // ensure the data hasn't changed since the fetch was initiated, exit if it has\n // ideally we would use an abort controller here to abort the request, but we don't perform the fetch\n if (dataKey !== _pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n length.current = response.length;\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData(currentData => {\n const direction = getDirection(pageIndex, currentData.pages);\n const nextPages = getPages(\n pageIndex,\n currentData.lastFetchedPage,\n hasDataChanged ? [] : currentData.pages,\n direction\n );\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n let nextCache: Record<number, TType[]>;\n\n if (hasDataChanged || !direction) {\n nextCache = nextPages.reduce(\n (acc, p) => ({ ...acc, [p]: Array.from({ length: pageSize }).fill(undefined) }),\n {}\n );\n } else {\n nextCache = { ...currentData.cache };\n }\n\n nextCache[pageIndex] = response.data;\n\n // cleanup \"unloaded\" pages\n if (direction === 'forward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages[0];\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n } else if (direction === 'backward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages[currentData.pages.length - 1];\n\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n }\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n return {\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndex,\n };\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n delete _pendingPageRequests.current[pageIndex];\n });\n } catch {\n //\n }\n }\n\n const loadAll = async (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) => {\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n try {\n const response = await fetchAll(sorting, filters, hiddenColumns, search);\n length.current = response.length;\n\n const pages: number[] = [];\n const cache: Record<number, TType[]> = {};\n const pageCount = Math.ceil(response.length / pageSize);\n\n Array.from(Array.from({ length: pageCount }).keys()).forEach((index: number) => {\n pages.push(index);\n const startIndex = index * pageSize;\n cache[index] = response.data.slice(startIndex, startIndex + pageSize);\n });\n\n setData({\n cache,\n pages,\n rows: response.data,\n lastFetchedPage: undefined,\n });\n } catch {\n //\n } finally {\n // reset pending requests\n _pendingPageRequests.current = {};\n }\n };\n\n async function reloadCurrentPages(\n currentPageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const index = data.pages.indexOf(currentPageIndex);\n const pageIndexes = [data.pages[index - 1], currentPageIndex, data.pages[index + 1]].filter(x => x !== undefined);\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the pages as loading, so that subsequent requests don't retrigger them\n _pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});\n\n try {\n // fetch the page\n const responses = await Promise.all(\n pageIndexes.map(pageIndex => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))\n );\n\n length.current = responses[0]?.length;\n\n const nextPages = pageIndexes;\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n const nextCache: Record<number, TType[]> = nextPages.reduce(\n (acc, p, index) => ({ ...acc, [p]: responses[index]?.data ?? [] }),\n {}\n );\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData({\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndexes[pageIndexes.length - 1],\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n _pendingPageRequests.current = {};\n });\n } catch {\n //\n }\n }\n\n const invalidate = async () => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n _lastUsedSorting.current,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n\n const handleSort = async (sorting: TableColumnSort[]) => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n sorting,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n const handleFilter = async (filters: TableColumnFilter[], hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, filters, hiddenColumns, _lastUsedSearch.current);\n };\n const handleSearch = async (search: string | undefined, hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, _lastUsedFilters.current, hiddenColumns, search);\n };\n\n return [\n {\n data: data.rows,\n pages: data.pages,\n length: length.current,\n loadAll,\n loadPage,\n onChangeFilter: handleFilter,\n onChangeSearch: handleSearch,\n onChangeSort: handleSort,\n pageSize,\n _experimentalDataLoader2: true,\n },\n invalidate,\n ];\n}\n\nfunction getCurrentPage(currentPages: number[]) {\n if (currentPages.length <= 2 && currentPages[0] !== undefined) {\n return currentPages[0];\n }\n\n // for even page lengths we can't know which is the current visible page - it could even be both\n // so we load one of them and rely on the \"load next/previous page\" functionality in row\n const middle = Math.floor(currentPages.length / 2);\n return currentPages[middle] as number;\n}\n\nfunction getDirection(pageIndex: number, currentPages: number[]): Direction {\n if (currentPages.length) {\n const lastPageIndex = currentPages[currentPages.length - 1];\n\n if (lastPageIndex !== undefined && pageIndex === lastPageIndex + 1) {\n return 'forward';\n }\n\n const firstPageIndex = currentPages[0];\n\n if (\n (firstPageIndex !== undefined && pageIndex === firstPageIndex - 1) ||\n (currentPages.length === 2 && currentPages[0] !== 0 && pageIndex === currentPages[0])\n ) {\n return 'backward';\n }\n }\n\n return undefined;\n}\n\nfunction getPages(pageIndex: number, lastUsedPageIndex: number | undefined, currentPages: number[], direction: Direction) {\n if (currentPages.length && (pageIndex === lastUsedPageIndex || currentPages.includes(pageIndex))) {\n return currentPages;\n }\n\n if (direction === 'forward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(1) : currentPages;\n return nextPages.concat(pageIndex);\n }\n\n if (direction === 'backward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(0, -1) : currentPages;\n return [pageIndex].concat(nextPages);\n }\n\n return [pageIndex];\n}\n"],"names":["DEFAULT_PAGE_SIZE","index"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useTableDataLoader2.cjs","sources":["../../../src/primitives/Table/useTableDataLoader2.ts"],"sourcesContent":["import React from 'react';\n\nimport type {\n TableColumnFilter,\n TableColumnSort,\n TableFilterHandler,\n TableServerLoadPageHandler,\n TableServerLoadAllHandler,\n TableServerResetPaginationHandler,\n TableSortHandler,\n TableSearchHandler,\n} from './types';\nimport type { useTableDataLoaderOptions } from './useTableDataLoader';\nimport { DEFAULT_PAGE_SIZE } from './useTableDataLoader';\n\nconst DATASET_SIZE_MULTIPLIER = 15;\n\nexport type useTableDataPageFetcher2<TType = unknown> = (\n pageIndex: number,\n pageSize: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataAllFetcher2<TType = unknown> = (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataLoaderValues2<TType = unknown> = {\n data: TType[];\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n onChangeFilter: TableFilterHandler;\n onChangeSearch: TableSearchHandler;\n onChangeSort: TableSortHandler;\n pageSize: number;\n pages: number[];\n resetPagination: TableServerResetPaginationHandler;\n _experimentalDataLoader2: boolean;\n};\n\ntype Data<TType = unknown> = {\n rows: TType[];\n pages: number[];\n cache: Record<number, TType[]>;\n lastFetchedPage: number | undefined;\n};\ntype Direction = 'forward' | 'backward' | undefined;\n\nfunction getDataKey(\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) {\n return [JSON.stringify(sorting), JSON.stringify(filters), JSON.stringify(hiddenColumns), JSON.stringify(search)].join('_');\n}\n\nexport function useTableDataLoader2<TType = unknown>(\n fetchPage: useTableDataPageFetcher2<TType>,\n fetchAll: useTableDataAllFetcher2<TType>,\n options: useTableDataLoaderOptions = { pageSize: DEFAULT_PAGE_SIZE }\n): [useTableDataLoaderValues2<TType>, () => Promise<void>] {\n const { pageSize } = options;\n const DATASET_SIZE = DATASET_SIZE_MULTIPLIER * pageSize;\n\n // track the data length, we don't know it until the first request\n const length = React.useRef<number>(undefined);\n // data will be filled after the first request\n const [data, setData] = React.useState<Data<TType>>({ rows: [], pages: [], cache: {}, lastFetchedPage: undefined });\n // track which pages have been loaded to dedupe requests\n const _pendingPageRequests = React.useRef<Record<number, string>>({});\n // store last used properties\n const _lastUsedSorting = React.useRef<TableColumnSort[]>([]);\n const _lastUsedFilters = React.useRef<TableColumnFilter[]>([]);\n const _lastUsedHiddenColumns = React.useRef<string[]>([]);\n const _lastUsedSearch = React.useRef<string | undefined>(undefined);\n\n async function loadPage(\n pageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const hasDataChanged =\n JSON.stringify(sorting) !== JSON.stringify(_lastUsedSorting.current) ||\n JSON.stringify(filters) !== JSON.stringify(_lastUsedFilters.current) ||\n JSON.stringify(hiddenColumns) !== JSON.stringify(_lastUsedHiddenColumns.current) ||\n search !== _lastUsedSearch.current;\n\n if (hasDataChanged) {\n // set values so we can use them for invalidate\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // ideally we would have requests to abort, but we don't perform the fetch\n _pendingPageRequests.current = {};\n\n // we don't reset cached data here because it would result in a flicker of no data for the user,\n // instead we reset it in setState below when we have the new data to replace with\n } else {\n // if a request is already pending for this page, skip the load\n if (_pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n // if the page is already loaded, abort\n if (data.cache[pageIndex] && data.cache[pageIndex][0]) {\n return;\n }\n }\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the page as loading, so that subsequent requests don't retrigger it\n _pendingPageRequests.current[pageIndex] = dataKey;\n\n try {\n // fetch the page\n const response = await fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search);\n\n // ensure the data hasn't changed since the fetch was initiated, exit if it has\n // ideally we would use an abort controller here to abort the request, but we don't perform the fetch\n if (dataKey !== _pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n length.current = response.length;\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData(currentData => {\n const direction = getDirection(pageIndex, currentData.pages);\n const nextPages = getPages(\n pageIndex,\n currentData.lastFetchedPage,\n hasDataChanged ? [] : currentData.pages,\n direction\n );\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n let nextCache: Record<number, TType[]>;\n\n if (hasDataChanged || !direction) {\n nextCache = nextPages.reduce(\n (acc, p) => ({ ...acc, [p]: Array.from({ length: pageSize }).fill(undefined) }),\n {}\n );\n } else {\n nextCache = { ...currentData.cache };\n }\n\n nextCache[pageIndex] = response.data;\n\n // cleanup \"unloaded\" pages\n if (direction === 'forward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages[0];\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n } else if (direction === 'backward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages.at(-1);\n\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n }\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n return {\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndex,\n };\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n delete _pendingPageRequests.current[pageIndex];\n });\n } catch {\n //\n }\n }\n\n const loadAll = async (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) => {\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n try {\n const response = await fetchAll(sorting, filters, hiddenColumns, search);\n length.current = response.length;\n\n const pages: number[] = [];\n const cache: Record<number, TType[]> = {};\n const pageCount = Math.ceil(response.length / pageSize);\n\n Array.from(Array.from({ length: pageCount }).keys()).forEach((index: number) => {\n pages.push(index);\n const startIndex = index * pageSize;\n cache[index] = response.data.slice(startIndex, startIndex + pageSize);\n });\n\n setData({\n cache,\n pages,\n rows: response.data,\n lastFetchedPage: undefined,\n });\n } catch {\n //\n } finally {\n // reset pending requests\n _pendingPageRequests.current = {};\n }\n };\n\n async function reloadCurrentPages(\n currentPageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const index = data.pages.indexOf(currentPageIndex);\n const pageIndexes = [data.pages[index - 1], currentPageIndex, data.pages[index + 1]].filter(x => x !== undefined);\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the pages as loading, so that subsequent requests don't retrigger them\n _pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});\n\n try {\n // fetch the page\n const responses = await Promise.all(\n pageIndexes.map(pageIndex => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))\n );\n\n length.current = responses[0]?.length;\n\n const nextPages = pageIndexes;\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n const nextCache: Record<number, TType[]> = nextPages.reduce(\n (acc, p, index) => ({ ...acc, [p]: responses[index]?.data ?? [] }),\n {}\n );\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData({\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndexes.at(-1),\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n _pendingPageRequests.current = {};\n });\n } catch {\n //\n }\n }\n\n const invalidate = async () => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n _lastUsedSorting.current,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n\n const handleSort = async (sorting: TableColumnSort[]) => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n sorting,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n const handleFilter = async (filters: TableColumnFilter[], hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, filters, hiddenColumns, _lastUsedSearch.current);\n };\n const handleSearch = async (search: string | undefined, hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, _lastUsedFilters.current, hiddenColumns, search);\n };\n\n // discards the currently loaded pages and loads the first page(s) again, keeping the last used\n // sorting, filters, hidden columns and search. this is useful after mutations which change the\n // length of the data (e.g. a bulk delete), where the currently loaded pages may no longer exist\n const resetPagination = async () => {\n const sorting = _lastUsedSorting.current;\n const filters = _lastUsedFilters.current;\n const hiddenColumns = _lastUsedHiddenColumns.current;\n const search = _lastUsedSearch.current;\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // ideally we would have requests to abort, but we don't perform the fetch. any in flight request\n // belongs to a page we are about to discard, so mark only the pages we are about to load as pending\n const pageIndexes = [0, 1];\n _pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});\n\n try {\n const responses = await Promise.all(\n pageIndexes.map(pageIndex => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))\n );\n\n length.current = responses[0]?.length;\n\n const pageCount = Math.ceil((responses[0]?.length ?? 0) / pageSize);\n // always keep the first page, even when there is no data, so that the table can render an empty state\n const nextPages = pageIndexes.filter(pageIndex => pageIndex === 0 || pageIndex < pageCount);\n\n const nextCache: Record<number, TType[]> = nextPages.reduce(\n (acc, pageIndex) => ({ ...acc, [pageIndex]: responses[pageIndex]?.data ?? [] }),\n {}\n );\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n setData({\n cache: nextCache,\n pages: nextPages,\n rows,\n lastFetchedPage: nextPages.at(-1),\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n _pendingPageRequests.current = {};\n });\n } catch {\n //\n }\n };\n\n return [\n {\n data: data.rows,\n pages: data.pages,\n length: length.current,\n loadAll,\n loadPage,\n onChangeFilter: handleFilter,\n onChangeSearch: handleSearch,\n onChangeSort: handleSort,\n pageSize,\n resetPagination,\n _experimentalDataLoader2: true,\n },\n invalidate,\n ];\n}\n\nfunction getCurrentPage(currentPages: number[]) {\n if (currentPages.length <= 2 && currentPages[0] !== undefined) {\n return currentPages[0];\n }\n\n // for even page lengths we can't know which is the current visible page - it could even be both\n // so we load one of them and rely on the \"load next/previous page\" functionality in row\n const middle = Math.floor(currentPages.length / 2);\n return currentPages[middle] as number;\n}\n\nfunction getDirection(pageIndex: number, currentPages: number[]): Direction {\n if (currentPages.length) {\n const lastPageIndex = currentPages.at(-1);\n\n if (lastPageIndex !== undefined && pageIndex === lastPageIndex + 1) {\n return 'forward';\n }\n\n const firstPageIndex = currentPages[0];\n\n if (\n (firstPageIndex !== undefined && pageIndex === firstPageIndex - 1) ||\n (currentPages.length === 2 && currentPages[0] !== 0 && pageIndex === currentPages[0])\n ) {\n return 'backward';\n }\n }\n\n return undefined;\n}\n\nfunction getPages(pageIndex: number, lastUsedPageIndex: number | undefined, currentPages: number[], direction: Direction) {\n if (currentPages.length && (pageIndex === lastUsedPageIndex || currentPages.includes(pageIndex))) {\n return currentPages;\n }\n\n if (direction === 'forward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(1) : currentPages;\n return nextPages.concat(pageIndex);\n }\n\n if (direction === 'backward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(0, -1) : currentPages;\n return [pageIndex].concat(nextPages);\n }\n\n return [pageIndex];\n}\n"],"names":["DEFAULT_PAGE_SIZE","index"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TableColumnFilter, TableColumnSort, TableFilterHandler, TableServerLoadPageHandler, TableServerLoadAllHandler, TableSortHandler, TableSearchHandler } from './types';
|
|
1
|
+
import { TableColumnFilter, TableColumnSort, TableFilterHandler, TableServerLoadPageHandler, TableServerLoadAllHandler, TableServerResetPaginationHandler, TableSortHandler, TableSearchHandler } from './types';
|
|
2
2
|
import { useTableDataLoaderOptions } from './useTableDataLoader';
|
|
3
3
|
export type useTableDataPageFetcher2<TType = unknown> = (pageIndex: number, pageSize: number, sorting: TableColumnSort[], filters: TableColumnFilter[], hiddenColumns: string[], search: string | undefined) => Promise<{
|
|
4
4
|
data: TType[];
|
|
@@ -18,6 +18,7 @@ export type useTableDataLoaderValues2<TType = unknown> = {
|
|
|
18
18
|
onChangeSort: TableSortHandler;
|
|
19
19
|
pageSize: number;
|
|
20
20
|
pages: number[];
|
|
21
|
+
resetPagination: TableServerResetPaginationHandler;
|
|
21
22
|
_experimentalDataLoader2: boolean;
|
|
22
23
|
};
|
|
23
24
|
export declare function useTableDataLoader2<TType = unknown>(fetchPage: useTableDataPageFetcher2<TType>, fetchAll: useTableDataAllFetcher2<TType>, options?: useTableDataLoaderOptions): [useTableDataLoaderValues2<TType>, () => Promise<void>];
|
|
@@ -66,7 +66,7 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: DEFAULT_
|
|
|
66
66
|
delete nextCache[unloadedPage];
|
|
67
67
|
}
|
|
68
68
|
} else if (direction === "backward" && currentData.rows.length >= DATASET_SIZE) {
|
|
69
|
-
const unloadedPage = currentData.pages
|
|
69
|
+
const unloadedPage = currentData.pages.at(-1);
|
|
70
70
|
if (unloadedPage !== void 0) {
|
|
71
71
|
delete nextCache[unloadedPage];
|
|
72
72
|
}
|
|
@@ -136,7 +136,7 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: DEFAULT_
|
|
|
136
136
|
cache: nextCache,
|
|
137
137
|
pages: nextPages,
|
|
138
138
|
rows,
|
|
139
|
-
lastFetchedPage: pageIndexes
|
|
139
|
+
lastFetchedPage: pageIndexes.at(-1)
|
|
140
140
|
});
|
|
141
141
|
requestAnimationFrame(() => {
|
|
142
142
|
_pendingPageRequests.current = {};
|
|
@@ -168,6 +168,38 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: DEFAULT_
|
|
|
168
168
|
const handleSearch = async (search, hiddenColumns) => {
|
|
169
169
|
return await loadPage(0, _lastUsedSorting.current, _lastUsedFilters.current, hiddenColumns, search);
|
|
170
170
|
};
|
|
171
|
+
const resetPagination = async () => {
|
|
172
|
+
const sorting = _lastUsedSorting.current;
|
|
173
|
+
const filters = _lastUsedFilters.current;
|
|
174
|
+
const hiddenColumns = _lastUsedHiddenColumns.current;
|
|
175
|
+
const search = _lastUsedSearch.current;
|
|
176
|
+
const dataKey = getDataKey(sorting, filters, hiddenColumns, search);
|
|
177
|
+
const pageIndexes = [0, 1];
|
|
178
|
+
_pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});
|
|
179
|
+
try {
|
|
180
|
+
const responses = await Promise.all(
|
|
181
|
+
pageIndexes.map((pageIndex) => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))
|
|
182
|
+
);
|
|
183
|
+
length.current = responses[0]?.length;
|
|
184
|
+
const pageCount = Math.ceil((responses[0]?.length ?? 0) / pageSize);
|
|
185
|
+
const nextPages = pageIndexes.filter((pageIndex) => pageIndex === 0 || pageIndex < pageCount);
|
|
186
|
+
const nextCache = nextPages.reduce(
|
|
187
|
+
(acc, pageIndex) => ({ ...acc, [pageIndex]: responses[pageIndex]?.data ?? [] }),
|
|
188
|
+
{}
|
|
189
|
+
);
|
|
190
|
+
const rows = Object.values(nextCache).flat();
|
|
191
|
+
setData({
|
|
192
|
+
cache: nextCache,
|
|
193
|
+
pages: nextPages,
|
|
194
|
+
rows,
|
|
195
|
+
lastFetchedPage: nextPages.at(-1)
|
|
196
|
+
});
|
|
197
|
+
requestAnimationFrame(() => {
|
|
198
|
+
_pendingPageRequests.current = {};
|
|
199
|
+
});
|
|
200
|
+
} catch {
|
|
201
|
+
}
|
|
202
|
+
};
|
|
171
203
|
return [
|
|
172
204
|
{
|
|
173
205
|
data: data.rows,
|
|
@@ -179,6 +211,7 @@ function useTableDataLoader2(fetchPage, fetchAll, options = { pageSize: DEFAULT_
|
|
|
179
211
|
onChangeSearch: handleSearch,
|
|
180
212
|
onChangeSort: handleSort,
|
|
181
213
|
pageSize,
|
|
214
|
+
resetPagination,
|
|
182
215
|
_experimentalDataLoader2: true
|
|
183
216
|
},
|
|
184
217
|
invalidate
|
|
@@ -193,7 +226,7 @@ function getCurrentPage(currentPages) {
|
|
|
193
226
|
}
|
|
194
227
|
function getDirection(pageIndex, currentPages) {
|
|
195
228
|
if (currentPages.length) {
|
|
196
|
-
const lastPageIndex = currentPages
|
|
229
|
+
const lastPageIndex = currentPages.at(-1);
|
|
197
230
|
if (lastPageIndex !== void 0 && pageIndex === lastPageIndex + 1) {
|
|
198
231
|
return "forward";
|
|
199
232
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableDataLoader2.js","sources":["../../../src/primitives/Table/useTableDataLoader2.ts"],"sourcesContent":["import React from 'react';\n\nimport type {\n TableColumnFilter,\n TableColumnSort,\n TableFilterHandler,\n TableServerLoadPageHandler,\n TableServerLoadAllHandler,\n TableSortHandler,\n TableSearchHandler,\n} from './types';\nimport type { useTableDataLoaderOptions } from './useTableDataLoader';\nimport { DEFAULT_PAGE_SIZE } from './useTableDataLoader';\n\nconst DATASET_SIZE_MULTIPLIER = 15;\n\nexport type useTableDataPageFetcher2<TType = unknown> = (\n pageIndex: number,\n pageSize: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataAllFetcher2<TType = unknown> = (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataLoaderValues2<TType = unknown> = {\n data: TType[];\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n onChangeFilter: TableFilterHandler;\n onChangeSearch: TableSearchHandler;\n onChangeSort: TableSortHandler;\n pageSize: number;\n pages: number[];\n _experimentalDataLoader2: boolean;\n};\n\ntype Data<TType = unknown> = {\n rows: TType[];\n pages: number[];\n cache: Record<number, TType[]>;\n lastFetchedPage: number | undefined;\n};\ntype Direction = 'forward' | 'backward' | undefined;\n\nfunction getDataKey(\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) {\n return [JSON.stringify(sorting), JSON.stringify(filters), JSON.stringify(hiddenColumns), JSON.stringify(search)].join('_');\n}\n\nexport function useTableDataLoader2<TType = unknown>(\n fetchPage: useTableDataPageFetcher2<TType>,\n fetchAll: useTableDataAllFetcher2<TType>,\n options: useTableDataLoaderOptions = { pageSize: DEFAULT_PAGE_SIZE }\n): [useTableDataLoaderValues2<TType>, () => Promise<void>] {\n const { pageSize } = options;\n const DATASET_SIZE = DATASET_SIZE_MULTIPLIER * pageSize;\n\n // track the data length, we don't know it until the first request\n const length = React.useRef<number>(undefined);\n // data will be filled after the first request\n const [data, setData] = React.useState<Data<TType>>({ rows: [], pages: [], cache: {}, lastFetchedPage: undefined });\n // track which pages have been loaded to dedupe requests\n const _pendingPageRequests = React.useRef<Record<number, string>>({});\n // store last used properties\n const _lastUsedSorting = React.useRef<TableColumnSort[]>([]);\n const _lastUsedFilters = React.useRef<TableColumnFilter[]>([]);\n const _lastUsedHiddenColumns = React.useRef<string[]>([]);\n const _lastUsedSearch = React.useRef<string | undefined>(undefined);\n\n async function loadPage(\n pageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const hasDataChanged =\n JSON.stringify(sorting) !== JSON.stringify(_lastUsedSorting.current) ||\n JSON.stringify(filters) !== JSON.stringify(_lastUsedFilters.current) ||\n JSON.stringify(hiddenColumns) !== JSON.stringify(_lastUsedHiddenColumns.current) ||\n search !== _lastUsedSearch.current;\n\n if (hasDataChanged) {\n // set values so we can use them for invalidate\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // ideally we would have requests to abort, but we don't perform the fetch\n _pendingPageRequests.current = {};\n\n // we don't reset cached data here because it would result in a flicker of no data for the user,\n // instead we reset it in setState below when we have the new data to replace with\n } else {\n // if a request is already pending for this page, skip the load\n if (_pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n // if the page is already loaded, abort\n if (data.cache[pageIndex] && data.cache[pageIndex][0]) {\n return;\n }\n }\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the page as loading, so that subsequent requests don't retrigger it\n _pendingPageRequests.current[pageIndex] = dataKey;\n\n try {\n // fetch the page\n const response = await fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search);\n\n // ensure the data hasn't changed since the fetch was initiated, exit if it has\n // ideally we would use an abort controller here to abort the request, but we don't perform the fetch\n if (dataKey !== _pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n length.current = response.length;\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData(currentData => {\n const direction = getDirection(pageIndex, currentData.pages);\n const nextPages = getPages(\n pageIndex,\n currentData.lastFetchedPage,\n hasDataChanged ? [] : currentData.pages,\n direction\n );\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n let nextCache: Record<number, TType[]>;\n\n if (hasDataChanged || !direction) {\n nextCache = nextPages.reduce(\n (acc, p) => ({ ...acc, [p]: Array.from({ length: pageSize }).fill(undefined) }),\n {}\n );\n } else {\n nextCache = { ...currentData.cache };\n }\n\n nextCache[pageIndex] = response.data;\n\n // cleanup \"unloaded\" pages\n if (direction === 'forward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages[0];\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n } else if (direction === 'backward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages[currentData.pages.length - 1];\n\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n }\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n return {\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndex,\n };\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n delete _pendingPageRequests.current[pageIndex];\n });\n } catch {\n //\n }\n }\n\n const loadAll = async (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) => {\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n try {\n const response = await fetchAll(sorting, filters, hiddenColumns, search);\n length.current = response.length;\n\n const pages: number[] = [];\n const cache: Record<number, TType[]> = {};\n const pageCount = Math.ceil(response.length / pageSize);\n\n Array.from(Array.from({ length: pageCount }).keys()).forEach((index: number) => {\n pages.push(index);\n const startIndex = index * pageSize;\n cache[index] = response.data.slice(startIndex, startIndex + pageSize);\n });\n\n setData({\n cache,\n pages,\n rows: response.data,\n lastFetchedPage: undefined,\n });\n } catch {\n //\n } finally {\n // reset pending requests\n _pendingPageRequests.current = {};\n }\n };\n\n async function reloadCurrentPages(\n currentPageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const index = data.pages.indexOf(currentPageIndex);\n const pageIndexes = [data.pages[index - 1], currentPageIndex, data.pages[index + 1]].filter(x => x !== undefined);\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the pages as loading, so that subsequent requests don't retrigger them\n _pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});\n\n try {\n // fetch the page\n const responses = await Promise.all(\n pageIndexes.map(pageIndex => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))\n );\n\n length.current = responses[0]?.length;\n\n const nextPages = pageIndexes;\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n const nextCache: Record<number, TType[]> = nextPages.reduce(\n (acc, p, index) => ({ ...acc, [p]: responses[index]?.data ?? [] }),\n {}\n );\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData({\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndexes[pageIndexes.length - 1],\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n _pendingPageRequests.current = {};\n });\n } catch {\n //\n }\n }\n\n const invalidate = async () => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n _lastUsedSorting.current,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n\n const handleSort = async (sorting: TableColumnSort[]) => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n sorting,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n const handleFilter = async (filters: TableColumnFilter[], hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, filters, hiddenColumns, _lastUsedSearch.current);\n };\n const handleSearch = async (search: string | undefined, hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, _lastUsedFilters.current, hiddenColumns, search);\n };\n\n return [\n {\n data: data.rows,\n pages: data.pages,\n length: length.current,\n loadAll,\n loadPage,\n onChangeFilter: handleFilter,\n onChangeSearch: handleSearch,\n onChangeSort: handleSort,\n pageSize,\n _experimentalDataLoader2: true,\n },\n invalidate,\n ];\n}\n\nfunction getCurrentPage(currentPages: number[]) {\n if (currentPages.length <= 2 && currentPages[0] !== undefined) {\n return currentPages[0];\n }\n\n // for even page lengths we can't know which is the current visible page - it could even be both\n // so we load one of them and rely on the \"load next/previous page\" functionality in row\n const middle = Math.floor(currentPages.length / 2);\n return currentPages[middle] as number;\n}\n\nfunction getDirection(pageIndex: number, currentPages: number[]): Direction {\n if (currentPages.length) {\n const lastPageIndex = currentPages[currentPages.length - 1];\n\n if (lastPageIndex !== undefined && pageIndex === lastPageIndex + 1) {\n return 'forward';\n }\n\n const firstPageIndex = currentPages[0];\n\n if (\n (firstPageIndex !== undefined && pageIndex === firstPageIndex - 1) ||\n (currentPages.length === 2 && currentPages[0] !== 0 && pageIndex === currentPages[0])\n ) {\n return 'backward';\n }\n }\n\n return undefined;\n}\n\nfunction getPages(pageIndex: number, lastUsedPageIndex: number | undefined, currentPages: number[], direction: Direction) {\n if (currentPages.length && (pageIndex === lastUsedPageIndex || currentPages.includes(pageIndex))) {\n return currentPages;\n }\n\n if (direction === 'forward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(1) : currentPages;\n return nextPages.concat(pageIndex);\n }\n\n if (direction === 'backward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(0, -1) : currentPages;\n return [pageIndex].concat(nextPages);\n }\n\n return [pageIndex];\n}\n"],"names":["React","index"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useTableDataLoader2.js","sources":["../../../src/primitives/Table/useTableDataLoader2.ts"],"sourcesContent":["import React from 'react';\n\nimport type {\n TableColumnFilter,\n TableColumnSort,\n TableFilterHandler,\n TableServerLoadPageHandler,\n TableServerLoadAllHandler,\n TableServerResetPaginationHandler,\n TableSortHandler,\n TableSearchHandler,\n} from './types';\nimport type { useTableDataLoaderOptions } from './useTableDataLoader';\nimport { DEFAULT_PAGE_SIZE } from './useTableDataLoader';\n\nconst DATASET_SIZE_MULTIPLIER = 15;\n\nexport type useTableDataPageFetcher2<TType = unknown> = (\n pageIndex: number,\n pageSize: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataAllFetcher2<TType = unknown> = (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) => Promise<{ data: TType[]; length: number }>;\n\nexport type useTableDataLoaderValues2<TType = unknown> = {\n data: TType[];\n length: number | undefined;\n loadAll: TableServerLoadAllHandler;\n loadPage: TableServerLoadPageHandler;\n onChangeFilter: TableFilterHandler;\n onChangeSearch: TableSearchHandler;\n onChangeSort: TableSortHandler;\n pageSize: number;\n pages: number[];\n resetPagination: TableServerResetPaginationHandler;\n _experimentalDataLoader2: boolean;\n};\n\ntype Data<TType = unknown> = {\n rows: TType[];\n pages: number[];\n cache: Record<number, TType[]>;\n lastFetchedPage: number | undefined;\n};\ntype Direction = 'forward' | 'backward' | undefined;\n\nfunction getDataKey(\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n) {\n return [JSON.stringify(sorting), JSON.stringify(filters), JSON.stringify(hiddenColumns), JSON.stringify(search)].join('_');\n}\n\nexport function useTableDataLoader2<TType = unknown>(\n fetchPage: useTableDataPageFetcher2<TType>,\n fetchAll: useTableDataAllFetcher2<TType>,\n options: useTableDataLoaderOptions = { pageSize: DEFAULT_PAGE_SIZE }\n): [useTableDataLoaderValues2<TType>, () => Promise<void>] {\n const { pageSize } = options;\n const DATASET_SIZE = DATASET_SIZE_MULTIPLIER * pageSize;\n\n // track the data length, we don't know it until the first request\n const length = React.useRef<number>(undefined);\n // data will be filled after the first request\n const [data, setData] = React.useState<Data<TType>>({ rows: [], pages: [], cache: {}, lastFetchedPage: undefined });\n // track which pages have been loaded to dedupe requests\n const _pendingPageRequests = React.useRef<Record<number, string>>({});\n // store last used properties\n const _lastUsedSorting = React.useRef<TableColumnSort[]>([]);\n const _lastUsedFilters = React.useRef<TableColumnFilter[]>([]);\n const _lastUsedHiddenColumns = React.useRef<string[]>([]);\n const _lastUsedSearch = React.useRef<string | undefined>(undefined);\n\n async function loadPage(\n pageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const hasDataChanged =\n JSON.stringify(sorting) !== JSON.stringify(_lastUsedSorting.current) ||\n JSON.stringify(filters) !== JSON.stringify(_lastUsedFilters.current) ||\n JSON.stringify(hiddenColumns) !== JSON.stringify(_lastUsedHiddenColumns.current) ||\n search !== _lastUsedSearch.current;\n\n if (hasDataChanged) {\n // set values so we can use them for invalidate\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // ideally we would have requests to abort, but we don't perform the fetch\n _pendingPageRequests.current = {};\n\n // we don't reset cached data here because it would result in a flicker of no data for the user,\n // instead we reset it in setState below when we have the new data to replace with\n } else {\n // if a request is already pending for this page, skip the load\n if (_pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n // if the page is already loaded, abort\n if (data.cache[pageIndex] && data.cache[pageIndex][0]) {\n return;\n }\n }\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the page as loading, so that subsequent requests don't retrigger it\n _pendingPageRequests.current[pageIndex] = dataKey;\n\n try {\n // fetch the page\n const response = await fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search);\n\n // ensure the data hasn't changed since the fetch was initiated, exit if it has\n // ideally we would use an abort controller here to abort the request, but we don't perform the fetch\n if (dataKey !== _pendingPageRequests.current[pageIndex]) {\n return;\n }\n\n length.current = response.length;\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData(currentData => {\n const direction = getDirection(pageIndex, currentData.pages);\n const nextPages = getPages(\n pageIndex,\n currentData.lastFetchedPage,\n hasDataChanged ? [] : currentData.pages,\n direction\n );\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n let nextCache: Record<number, TType[]>;\n\n if (hasDataChanged || !direction) {\n nextCache = nextPages.reduce(\n (acc, p) => ({ ...acc, [p]: Array.from({ length: pageSize }).fill(undefined) }),\n {}\n );\n } else {\n nextCache = { ...currentData.cache };\n }\n\n nextCache[pageIndex] = response.data;\n\n // cleanup \"unloaded\" pages\n if (direction === 'forward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages[0];\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n } else if (direction === 'backward' && currentData.rows.length >= DATASET_SIZE) {\n const unloadedPage = currentData.pages.at(-1);\n\n if (unloadedPage !== undefined) {\n delete nextCache[unloadedPage];\n }\n }\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n return {\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndex,\n };\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n delete _pendingPageRequests.current[pageIndex];\n });\n } catch {\n //\n }\n }\n\n const loadAll = async (\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) => {\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n try {\n const response = await fetchAll(sorting, filters, hiddenColumns, search);\n length.current = response.length;\n\n const pages: number[] = [];\n const cache: Record<number, TType[]> = {};\n const pageCount = Math.ceil(response.length / pageSize);\n\n Array.from(Array.from({ length: pageCount }).keys()).forEach((index: number) => {\n pages.push(index);\n const startIndex = index * pageSize;\n cache[index] = response.data.slice(startIndex, startIndex + pageSize);\n });\n\n setData({\n cache,\n pages,\n rows: response.data,\n lastFetchedPage: undefined,\n });\n } catch {\n //\n } finally {\n // reset pending requests\n _pendingPageRequests.current = {};\n }\n };\n\n async function reloadCurrentPages(\n currentPageIndex: number,\n sorting: TableColumnSort[],\n filters: TableColumnFilter[],\n hiddenColumns: string[],\n search: string | undefined\n ) {\n const index = data.pages.indexOf(currentPageIndex);\n const pageIndexes = [data.pages[index - 1], currentPageIndex, data.pages[index + 1]].filter(x => x !== undefined);\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n // if it has changed then we need to ignore all cached or pending requests and load again\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // set the pages as loading, so that subsequent requests don't retrigger them\n _pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});\n\n try {\n // fetch the page\n const responses = await Promise.all(\n pageIndexes.map(pageIndex => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))\n );\n\n length.current = responses[0]?.length;\n\n const nextPages = pageIndexes;\n\n // set values so we can track if they changed between loads\n _lastUsedSorting.current = sorting;\n _lastUsedFilters.current = filters;\n _lastUsedSearch.current = search;\n _lastUsedHiddenColumns.current = hiddenColumns;\n\n // cache data as an object to prevent any duplicates for pages\n const nextCache: Record<number, TType[]> = nextPages.reduce(\n (acc, p, index) => ({ ...acc, [p]: responses[index]?.data ?? [] }),\n {}\n );\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n // update state, here we do some \"magic\" to support \"load in place\"\n setData({\n cache: nextCache,\n pages: nextPages,\n rows: rows,\n lastFetchedPage: pageIndexes.at(-1),\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n _pendingPageRequests.current = {};\n });\n } catch {\n //\n }\n }\n\n const invalidate = async () => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n _lastUsedSorting.current,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n\n const handleSort = async (sorting: TableColumnSort[]) => {\n return await reloadCurrentPages(\n getCurrentPage(data.pages),\n sorting,\n _lastUsedFilters.current,\n _lastUsedHiddenColumns.current,\n _lastUsedSearch.current\n );\n };\n const handleFilter = async (filters: TableColumnFilter[], hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, filters, hiddenColumns, _lastUsedSearch.current);\n };\n const handleSearch = async (search: string | undefined, hiddenColumns: string[]) => {\n return await loadPage(0, _lastUsedSorting.current, _lastUsedFilters.current, hiddenColumns, search);\n };\n\n // discards the currently loaded pages and loads the first page(s) again, keeping the last used\n // sorting, filters, hidden columns and search. this is useful after mutations which change the\n // length of the data (e.g. a bulk delete), where the currently loaded pages may no longer exist\n const resetPagination = async () => {\n const sorting = _lastUsedSorting.current;\n const filters = _lastUsedFilters.current;\n const hiddenColumns = _lastUsedHiddenColumns.current;\n const search = _lastUsedSearch.current;\n\n // we use the dataKey to track whether the fetching data (sorting, filters etc) has changed\n const dataKey = getDataKey(sorting, filters, hiddenColumns, search);\n\n // ideally we would have requests to abort, but we don't perform the fetch. any in flight request\n // belongs to a page we are about to discard, so mark only the pages we are about to load as pending\n const pageIndexes = [0, 1];\n _pendingPageRequests.current = pageIndexes.reduce((accum, index) => ({ ...accum, [index]: dataKey }), {});\n\n try {\n const responses = await Promise.all(\n pageIndexes.map(pageIndex => fetchPage(pageIndex, pageSize, sorting, filters, hiddenColumns, search))\n );\n\n length.current = responses[0]?.length;\n\n const pageCount = Math.ceil((responses[0]?.length ?? 0) / pageSize);\n // always keep the first page, even when there is no data, so that the table can render an empty state\n const nextPages = pageIndexes.filter(pageIndex => pageIndex === 0 || pageIndex < pageCount);\n\n const nextCache: Record<number, TType[]> = nextPages.reduce(\n (acc, pageIndex) => ({ ...acc, [pageIndex]: responses[pageIndex]?.data ?? [] }),\n {}\n );\n\n // remap rows from the cached data - do it here and not in render to save some performance\n const rows = Object.values(nextCache).flat();\n\n setData({\n cache: nextCache,\n pages: nextPages,\n rows,\n lastFetchedPage: nextPages.at(-1),\n });\n\n // reset pending requests - after state has been set\n requestAnimationFrame(() => {\n _pendingPageRequests.current = {};\n });\n } catch {\n //\n }\n };\n\n return [\n {\n data: data.rows,\n pages: data.pages,\n length: length.current,\n loadAll,\n loadPage,\n onChangeFilter: handleFilter,\n onChangeSearch: handleSearch,\n onChangeSort: handleSort,\n pageSize,\n resetPagination,\n _experimentalDataLoader2: true,\n },\n invalidate,\n ];\n}\n\nfunction getCurrentPage(currentPages: number[]) {\n if (currentPages.length <= 2 && currentPages[0] !== undefined) {\n return currentPages[0];\n }\n\n // for even page lengths we can't know which is the current visible page - it could even be both\n // so we load one of them and rely on the \"load next/previous page\" functionality in row\n const middle = Math.floor(currentPages.length / 2);\n return currentPages[middle] as number;\n}\n\nfunction getDirection(pageIndex: number, currentPages: number[]): Direction {\n if (currentPages.length) {\n const lastPageIndex = currentPages.at(-1);\n\n if (lastPageIndex !== undefined && pageIndex === lastPageIndex + 1) {\n return 'forward';\n }\n\n const firstPageIndex = currentPages[0];\n\n if (\n (firstPageIndex !== undefined && pageIndex === firstPageIndex - 1) ||\n (currentPages.length === 2 && currentPages[0] !== 0 && pageIndex === currentPages[0])\n ) {\n return 'backward';\n }\n }\n\n return undefined;\n}\n\nfunction getPages(pageIndex: number, lastUsedPageIndex: number | undefined, currentPages: number[], direction: Direction) {\n if (currentPages.length && (pageIndex === lastUsedPageIndex || currentPages.includes(pageIndex))) {\n return currentPages;\n }\n\n if (direction === 'forward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(1) : currentPages;\n return nextPages.concat(pageIndex);\n }\n\n if (direction === 'backward') {\n const nextPages = currentPages.length === DATASET_SIZE_MULTIPLIER ? currentPages.slice(0, -1) : currentPages;\n return [pageIndex].concat(nextPages);\n }\n\n return [pageIndex];\n}\n"],"names":["React","index"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableRowActive.cjs","sources":["../../../../../src/primitives/Table/useTableManager/features/useTableRowActive.ts"],"sourcesContent":["import React from 'react';\n\nimport { useIsHoverStatePaused } from '@/hooks/useIsHoverStatePaused';\nimport { isElementInsideOrTriggeredFromContainer } from '@/utils/dom';\n\nimport { focusActiveRow } from '../../Core/listeners/useTableRowActiveListener';\nimport type { TableScrollToIndexHandler } from '../../types';\n\nexport function useTableRowActive(\n isEnabled = false,\n initialRowActiveIndex?: number,\n tableRef?: React.RefObject<HTMLTableElement>\n) {\n const [rowActiveIndex, setRowActiveIndex] = React.useState<number | undefined>(initialRowActiveIndex);\n const [rowHoverIndex, setRowHoverIndex] = React.useState<number | undefined>(undefined);\n const [isHoverStatePaused, setHoverStatePaused] = useIsHoverStatePaused();\n\n const move = (direction: -1 | 1, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n const nextIndex = rowActiveIndex === undefined ? 0 : getNextIndex(direction, rowActiveIndex, length);\n scrollToIndex(nextIndex);\n setTimeout(() => setRowActiveIndex(nextIndex), 50);\n };\n\n const onKeyDown = React.useCallback(\n (event: KeyboardEvent, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n if (!isEnabled || event.defaultPrevented) {\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n event.preventDefault();\n setHoverStatePaused(true);\n\n // Edge case: when only one row is visible, skip navigation since there's nowhere to move.\n // Explicit refocus is needed because document-level keyboard event handling causes the row to lose DOM focus\n // (removing :focus-within CSS styling). Since rowActiveIndex doesn't change (0→0), useEffect won't run to restore focus.\n if (length <= 1) {\n focusActiveRow(tableRef);\n return;\n }\n }\n\n if (event.key === 'ArrowUp') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = 0;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(-1, length, scrollToIndex);\n }\n\n return;\n }\n if (event.key === 'ArrowDown') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = length - 1;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(+1, length, scrollToIndex);\n }\n
|
|
1
|
+
{"version":3,"file":"useTableRowActive.cjs","sources":["../../../../../src/primitives/Table/useTableManager/features/useTableRowActive.ts"],"sourcesContent":["import React from 'react';\n\nimport { useIsHoverStatePaused } from '@/hooks/useIsHoverStatePaused';\nimport { isElementInsideOrTriggeredFromContainer } from '@/utils/dom';\n\nimport { focusActiveRow } from '../../Core/listeners/useTableRowActiveListener';\nimport type { TableScrollToIndexHandler } from '../../types';\n\nexport function useTableRowActive(\n isEnabled = false,\n initialRowActiveIndex?: number,\n tableRef?: React.RefObject<HTMLTableElement | null>\n) {\n const [rowActiveIndex, setRowActiveIndex] = React.useState<number | undefined>(initialRowActiveIndex);\n const [rowHoverIndex, setRowHoverIndex] = React.useState<number | undefined>(undefined);\n const [isHoverStatePaused, setHoverStatePaused] = useIsHoverStatePaused();\n\n const move = (direction: -1 | 1, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n const nextIndex = rowActiveIndex === undefined ? 0 : getNextIndex(direction, rowActiveIndex, length);\n scrollToIndex(nextIndex);\n setTimeout(() => setRowActiveIndex(nextIndex), 50);\n };\n\n const onKeyDown = React.useCallback(\n (event: KeyboardEvent, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n if (!isEnabled || event.defaultPrevented) {\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n event.preventDefault();\n setHoverStatePaused(true);\n\n // Edge case: when only one row is visible, skip navigation since there's nowhere to move.\n // Explicit refocus is needed because document-level keyboard event handling causes the row to lose DOM focus\n // (removing :focus-within CSS styling). Since rowActiveIndex doesn't change (0→0), useEffect won't run to restore focus.\n if (length <= 1) {\n focusActiveRow(tableRef);\n return;\n }\n }\n\n if (event.key === 'ArrowUp') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = 0;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(-1, length, scrollToIndex);\n }\n\n return;\n }\n if (event.key === 'ArrowDown') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = length - 1;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(+1, length, scrollToIndex);\n }\n }\n },\n [isEnabled, rowActiveIndex, tableRef]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n if (!isEnabled || event.isDefaultPrevented()) {\n return;\n }\n\n if (event.target.closest('tbody') || isElementInsideOrTriggeredFromContainer(event.target, event.currentTarget)) {\n return;\n }\n\n if (rowActiveIndex === undefined && length > 0) {\n setRowActiveIndex(index => {\n if (index === undefined) {\n scrollToIndex(0);\n return 0;\n }\n return index;\n });\n }\n },\n [rowActiveIndex, isEnabled]\n );\n\n return {\n isEnabled,\n rowActiveIndex,\n setRowActiveIndex: isEnabled ? setRowActiveIndex : () => undefined,\n rowHoverIndex,\n setRowHoverIndex,\n isHoverStatePaused,\n setHoverStatePaused: isEnabled ? setHoverStatePaused : () => undefined,\n handleFocus: isEnabled ? onFocus : () => undefined,\n handleKeyDown: isEnabled ? onKeyDown : () => undefined,\n };\n}\n\nfunction getNextIndex(direction: -1 | 1, currentIndex: number, length: number) {\n if (direction === -1) {\n return currentIndex - 1 > 0 ? currentIndex - 1 : 0;\n }\n\n return currentIndex + 1 < length ? currentIndex + 1 : currentIndex;\n}\n"],"names":["useIsHoverStatePaused","focusActiveRow","isElementInsideOrTriggeredFromContainer"],"mappings":";;;;;;AAQO,SAAS,kBACZ,YAAY,OACZ,uBACA,UACF;AACE,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,MAAM,SAA6B,qBAAqB;AACpG,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAA6B,MAAS;AACtF,QAAM,CAAC,oBAAoB,mBAAmB,IAAIA,4CAAA;AAElD,QAAM,OAAO,CAAC,WAAmB,QAAgB,kBAA6C;AAC1F,UAAM,YAAY,mBAAmB,SAAY,IAAI,aAAa,WAAW,gBAAgB,MAAM;AACnG,kBAAc,SAAS;AACvB,eAAW,MAAM,kBAAkB,SAAS,GAAG,EAAE;AAAA,EACrD;AAEA,QAAM,YAAY,MAAM;AAAA,IACpB,CAAC,OAAsB,QAAgB,kBAA6C;AAChF,UAAI,CAAC,aAAa,MAAM,kBAAkB;AACtC;AAAA,MACJ;AAEA,UAAI,MAAM,QAAQ,aAAa,MAAM,QAAQ,aAAa;AACtD,cAAM,eAAA;AACN,4BAAoB,IAAI;AAKxB,YAAI,UAAU,GAAG;AACbC,oCAAAA,eAAe,QAAQ;AACvB;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,MAAM,QAAQ,WAAW;AACzB,YAAI,MAAM,WAAW,MAAM,SAAS;AAChC,gBAAM,WAAW;AACjB,wBAAc,QAAQ;AACtB,4BAAkB,QAAQ;AAAA,QAC9B,OAAO;AACH,eAAK,IAAI,QAAQ,aAAa;AAAA,QAClC;AAEA;AAAA,MACJ;AACA,UAAI,MAAM,QAAQ,aAAa;AAC3B,YAAI,MAAM,WAAW,MAAM,SAAS;AAChC,gBAAM,WAAW,SAAS;AAC1B,wBAAc,QAAQ;AACtB,4BAAkB,QAAQ;AAAA,QAC9B,OAAO;AACH,eAAK,GAAI,QAAQ,aAAa;AAAA,QAClC;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,CAAC,WAAW,gBAAgB,QAAQ;AAAA,EAAA;AAGxC,QAAM,UAAU,MAAM;AAAA,IAClB,CAAC,OAAyB,QAAgB,kBAA6C;AACnF,UAAI,CAAC,aAAa,MAAM,sBAAsB;AAC1C;AAAA,MACJ;AAEA,UAAI,MAAM,OAAO,QAAQ,OAAO,KAAKC,4CAAwC,MAAM,QAAQ,MAAM,aAAa,GAAG;AAC7G;AAAA,MACJ;AAEA,UAAI,mBAAmB,UAAa,SAAS,GAAG;AAC5C,0BAAkB,CAAA,UAAS;AACvB,cAAI,UAAU,QAAW;AACrB,0BAAc,CAAC;AACf,mBAAO;AAAA,UACX;AACA,iBAAO;AAAA,QACX,CAAC;AAAA,MACL;AAAA,IACJ;AAAA,IACA,CAAC,gBAAgB,SAAS;AAAA,EAAA;AAG9B,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA,mBAAmB,YAAY,oBAAoB,MAAM;AAAA,IACzD;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,YAAY,sBAAsB,MAAM;AAAA,IAC7D,aAAa,YAAY,UAAU,MAAM;AAAA,IACzC,eAAe,YAAY,YAAY,MAAM;AAAA,EAAA;AAErD;AAEA,SAAS,aAAa,WAAmB,cAAsB,QAAgB;AAC3E,MAAI,cAAc,IAAI;AAClB,WAAO,eAAe,IAAI,IAAI,eAAe,IAAI;AAAA,EACrD;AAEA,SAAO,eAAe,IAAI,SAAS,eAAe,IAAI;AAC1D;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { TableScrollToIndexHandler } from '../../types';
|
|
3
|
-
export declare function useTableRowActive(isEnabled?: boolean, initialRowActiveIndex?: number, tableRef?: React.RefObject<HTMLTableElement>): {
|
|
3
|
+
export declare function useTableRowActive(isEnabled?: boolean, initialRowActiveIndex?: number, tableRef?: React.RefObject<HTMLTableElement | null>): {
|
|
4
4
|
isEnabled: boolean;
|
|
5
5
|
rowActiveIndex: number | undefined;
|
|
6
6
|
setRowActiveIndex: React.Dispatch<React.SetStateAction<number | undefined>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTableRowActive.js","sources":["../../../../../src/primitives/Table/useTableManager/features/useTableRowActive.ts"],"sourcesContent":["import React from 'react';\n\nimport { useIsHoverStatePaused } from '@/hooks/useIsHoverStatePaused';\nimport { isElementInsideOrTriggeredFromContainer } from '@/utils/dom';\n\nimport { focusActiveRow } from '../../Core/listeners/useTableRowActiveListener';\nimport type { TableScrollToIndexHandler } from '../../types';\n\nexport function useTableRowActive(\n isEnabled = false,\n initialRowActiveIndex?: number,\n tableRef?: React.RefObject<HTMLTableElement>\n) {\n const [rowActiveIndex, setRowActiveIndex] = React.useState<number | undefined>(initialRowActiveIndex);\n const [rowHoverIndex, setRowHoverIndex] = React.useState<number | undefined>(undefined);\n const [isHoverStatePaused, setHoverStatePaused] = useIsHoverStatePaused();\n\n const move = (direction: -1 | 1, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n const nextIndex = rowActiveIndex === undefined ? 0 : getNextIndex(direction, rowActiveIndex, length);\n scrollToIndex(nextIndex);\n setTimeout(() => setRowActiveIndex(nextIndex), 50);\n };\n\n const onKeyDown = React.useCallback(\n (event: KeyboardEvent, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n if (!isEnabled || event.defaultPrevented) {\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n event.preventDefault();\n setHoverStatePaused(true);\n\n // Edge case: when only one row is visible, skip navigation since there's nowhere to move.\n // Explicit refocus is needed because document-level keyboard event handling causes the row to lose DOM focus\n // (removing :focus-within CSS styling). Since rowActiveIndex doesn't change (0→0), useEffect won't run to restore focus.\n if (length <= 1) {\n focusActiveRow(tableRef);\n return;\n }\n }\n\n if (event.key === 'ArrowUp') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = 0;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(-1, length, scrollToIndex);\n }\n\n return;\n }\n if (event.key === 'ArrowDown') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = length - 1;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(+1, length, scrollToIndex);\n }\n
|
|
1
|
+
{"version":3,"file":"useTableRowActive.js","sources":["../../../../../src/primitives/Table/useTableManager/features/useTableRowActive.ts"],"sourcesContent":["import React from 'react';\n\nimport { useIsHoverStatePaused } from '@/hooks/useIsHoverStatePaused';\nimport { isElementInsideOrTriggeredFromContainer } from '@/utils/dom';\n\nimport { focusActiveRow } from '../../Core/listeners/useTableRowActiveListener';\nimport type { TableScrollToIndexHandler } from '../../types';\n\nexport function useTableRowActive(\n isEnabled = false,\n initialRowActiveIndex?: number,\n tableRef?: React.RefObject<HTMLTableElement | null>\n) {\n const [rowActiveIndex, setRowActiveIndex] = React.useState<number | undefined>(initialRowActiveIndex);\n const [rowHoverIndex, setRowHoverIndex] = React.useState<number | undefined>(undefined);\n const [isHoverStatePaused, setHoverStatePaused] = useIsHoverStatePaused();\n\n const move = (direction: -1 | 1, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n const nextIndex = rowActiveIndex === undefined ? 0 : getNextIndex(direction, rowActiveIndex, length);\n scrollToIndex(nextIndex);\n setTimeout(() => setRowActiveIndex(nextIndex), 50);\n };\n\n const onKeyDown = React.useCallback(\n (event: KeyboardEvent, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n if (!isEnabled || event.defaultPrevented) {\n return;\n }\n\n if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {\n event.preventDefault();\n setHoverStatePaused(true);\n\n // Edge case: when only one row is visible, skip navigation since there's nowhere to move.\n // Explicit refocus is needed because document-level keyboard event handling causes the row to lose DOM focus\n // (removing :focus-within CSS styling). Since rowActiveIndex doesn't change (0→0), useEffect won't run to restore focus.\n if (length <= 1) {\n focusActiveRow(tableRef);\n return;\n }\n }\n\n if (event.key === 'ArrowUp') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = 0;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(-1, length, scrollToIndex);\n }\n\n return;\n }\n if (event.key === 'ArrowDown') {\n if (event.ctrlKey || event.metaKey) {\n const newIndex = length - 1;\n scrollToIndex(newIndex);\n setRowActiveIndex(newIndex);\n } else {\n move(+1, length, scrollToIndex);\n }\n }\n },\n [isEnabled, rowActiveIndex, tableRef]\n );\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent, length: number, scrollToIndex: TableScrollToIndexHandler) => {\n if (!isEnabled || event.isDefaultPrevented()) {\n return;\n }\n\n if (event.target.closest('tbody') || isElementInsideOrTriggeredFromContainer(event.target, event.currentTarget)) {\n return;\n }\n\n if (rowActiveIndex === undefined && length > 0) {\n setRowActiveIndex(index => {\n if (index === undefined) {\n scrollToIndex(0);\n return 0;\n }\n return index;\n });\n }\n },\n [rowActiveIndex, isEnabled]\n );\n\n return {\n isEnabled,\n rowActiveIndex,\n setRowActiveIndex: isEnabled ? setRowActiveIndex : () => undefined,\n rowHoverIndex,\n setRowHoverIndex,\n isHoverStatePaused,\n setHoverStatePaused: isEnabled ? setHoverStatePaused : () => undefined,\n handleFocus: isEnabled ? onFocus : () => undefined,\n handleKeyDown: isEnabled ? onKeyDown : () => undefined,\n };\n}\n\nfunction getNextIndex(direction: -1 | 1, currentIndex: number, length: number) {\n if (direction === -1) {\n return currentIndex - 1 > 0 ? currentIndex - 1 : 0;\n }\n\n return currentIndex + 1 < length ? currentIndex + 1 : currentIndex;\n}\n"],"names":["React"],"mappings":";;;;AAQO,SAAS,kBACZ,YAAY,OACZ,uBACA,UACF;AACE,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,eAAM,SAA6B,qBAAqB;AACpG,QAAM,CAAC,eAAe,gBAAgB,IAAIA,eAAM,SAA6B,MAAS;AACtF,QAAM,CAAC,oBAAoB,mBAAmB,IAAI,sBAAA;AAElD,QAAM,OAAO,CAAC,WAAmB,QAAgB,kBAA6C;AAC1F,UAAM,YAAY,mBAAmB,SAAY,IAAI,aAAa,WAAW,gBAAgB,MAAM;AACnG,kBAAc,SAAS;AACvB,eAAW,MAAM,kBAAkB,SAAS,GAAG,EAAE;AAAA,EACrD;AAEA,QAAM,YAAYA,eAAM;AAAA,IACpB,CAAC,OAAsB,QAAgB,kBAA6C;AAChF,UAAI,CAAC,aAAa,MAAM,kBAAkB;AACtC;AAAA,MACJ;AAEA,UAAI,MAAM,QAAQ,aAAa,MAAM,QAAQ,aAAa;AACtD,cAAM,eAAA;AACN,4BAAoB,IAAI;AAKxB,YAAI,UAAU,GAAG;AACb,yBAAe,QAAQ;AACvB;AAAA,QACJ;AAAA,MACJ;AAEA,UAAI,MAAM,QAAQ,WAAW;AACzB,YAAI,MAAM,WAAW,MAAM,SAAS;AAChC,gBAAM,WAAW;AACjB,wBAAc,QAAQ;AACtB,4BAAkB,QAAQ;AAAA,QAC9B,OAAO;AACH,eAAK,IAAI,QAAQ,aAAa;AAAA,QAClC;AAEA;AAAA,MACJ;AACA,UAAI,MAAM,QAAQ,aAAa;AAC3B,YAAI,MAAM,WAAW,MAAM,SAAS;AAChC,gBAAM,WAAW,SAAS;AAC1B,wBAAc,QAAQ;AACtB,4BAAkB,QAAQ;AAAA,QAC9B,OAAO;AACH,eAAK,GAAI,QAAQ,aAAa;AAAA,QAClC;AAAA,MACJ;AAAA,IACJ;AAAA,IACA,CAAC,WAAW,gBAAgB,QAAQ;AAAA,EAAA;AAGxC,QAAM,UAAUA,eAAM;AAAA,IAClB,CAAC,OAAyB,QAAgB,kBAA6C;AACnF,UAAI,CAAC,aAAa,MAAM,sBAAsB;AAC1C;AAAA,MACJ;AAEA,UAAI,MAAM,OAAO,QAAQ,OAAO,KAAK,wCAAwC,MAAM,QAAQ,MAAM,aAAa,GAAG;AAC7G;AAAA,MACJ;AAEA,UAAI,mBAAmB,UAAa,SAAS,GAAG;AAC5C,0BAAkB,CAAA,UAAS;AACvB,cAAI,UAAU,QAAW;AACrB,0BAAc,CAAC;AACf,mBAAO;AAAA,UACX;AACA,iBAAO;AAAA,QACX,CAAC;AAAA,MACL;AAAA,IACJ;AAAA,IACA,CAAC,gBAAgB,SAAS;AAAA,EAAA;AAG9B,SAAO;AAAA,IACH;AAAA,IACA;AAAA,IACA,mBAAmB,YAAY,oBAAoB,MAAM;AAAA,IACzD;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,YAAY,sBAAsB,MAAM;AAAA,IAC7D,aAAa,YAAY,UAAU,MAAM;AAAA,IACzC,eAAe,YAAY,YAAY,MAAM;AAAA,EAAA;AAErD;AAEA,SAAS,aAAa,WAAmB,cAAsB,QAAgB;AAC3E,MAAI,cAAc,IAAI;AAClB,WAAO,eAAe,IAAI,IAAI,eAAe,IAAI;AAAA,EACrD;AAEA,SAAO,eAAe,IAAI,SAAS,eAAe,IAAI;AAC1D;"}
|
|
@@ -16,7 +16,6 @@ function useTableRowClick(isEnabled = false, onRowClick) {
|
|
|
16
16
|
if (rowData && event.key === "Enter") {
|
|
17
17
|
event.preventDefault();
|
|
18
18
|
onRowClick(rowData);
|
|
19
|
-
return;
|
|
20
19
|
}
|
|
21
20
|
},
|
|
22
21
|
[isEnabled, onRowClick]
|
|
@@ -28,7 +27,6 @@ function useTableRowClick(isEnabled = false, onRowClick) {
|
|
|
28
27
|
}
|
|
29
28
|
event.preventDefault();
|
|
30
29
|
onRowClick(rowData);
|
|
31
|
-
return;
|
|
32
30
|
},
|
|
33
31
|
[isEnabled, onRowClick]
|
|
34
32
|
);
|