⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export default defineConfig([
'@typescript-eslint/prefer-promise-reject-errors': 'off',
'@typescript-eslint/require-await': 'error',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/switch-exhaustiveness-check': ['error', { allowDefaultCaseForExhaustiveSwitch: false }],
'@typescript-eslint/use-unknown-in-catch-callback-variable': 'off',
},
settings: { react: { version: 'detect' } },
Expand Down
2 changes: 1 addition & 1 deletion src/components/ColumnHeader/ColumnHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export default function ColumnHeader({ columnIndex, columnName, columnConfig, ca
const { getHideColumn, showAllColumns } = useContext(ColumnVisibilityStatesContext)

const refCallback = useCallback((node: HTMLTableCellElement | null) => {
focusCellIfNeeded(node)
// set the current ref, it will be used to position the menu in handleMenuClick
ref.current = node
focusCellIfNeeded(node)
}, [focusCellIfNeeded])

const handleClick = useCallback(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ColumnMenu/ColumnMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function getSortDirection(direction?: Direction) {
return 'Ascending'
case 'descending':
return 'Descending'
default:
case undefined:
return 'No sort'
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/HighTable/HighTable.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ function createFilteredData(): DataFrame {
}

function createLargeData(): DataFrame {
const numRows = 777_000_000
// 1 peta rows (1 million billion, 10^15)
const numRows = 1_000_000_000_000_000
const columnDescriptors = ['ID1', 'LongString1', 'Value1', 'ID2', 'LongString2', 'Value2', 'ID3', 'LongString3', 'Value3', 'ID4', 'LongString4', 'Value4'].map(name => ({ name }))
function getCell({ row, column }: { row: number, column: string }): ResolvedValue | undefined {
return {
Expand Down
4 changes: 3 additions & 1 deletion src/components/HighTable/Slice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,10 @@ export default function Slice({
event.preventDefault()
if (newRowIndex !== undefined) {
setRowIndex(newRowIndex)
scrollRowIntoView?.({ rowIndex: newRowIndex }) // ensure the cell is visible
}
// ensure the cell is visible (even if only horizontal scrolling is needed)
// TODO(SL): improve the name of scrollRowIntoView, because it can also (indirectly) scroll columns into view
scrollRowIntoView?.({ rowIndex: newRowIndex ?? rowIndex })
setShouldFocus(true)
}, [rowIndex, colCount, rowCount, setColIndex, setRowIndex, setShouldFocus, scrollRowIntoView])

Expand Down
3 changes: 2 additions & 1 deletion src/contexts/ScrollModeContext.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createContext } from 'react'

export interface ScrollModeContextType {
scrollMode?: 'native' | 'virtual'
scrollMode?: 'native' | 'virtual' // it's only informative for now
canvasHeight?: number // total scrollable height
isScrolling?: boolean
sliceTop?: number // offset of the top of the slice from the top of the canvas
visibleRowsStart?: number // index of the first row visible in the viewport (inclusive). Indexes refer to the virtual table domain.
visibleRowsEnd?: number // index of the last row visible in the viewport (exclusive).
Expand Down
11 changes: 9 additions & 2 deletions src/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,12 @@ export const ariaOffset = 2 // 1-based index, +1 for the header

// reference: https://meyerweb.com/eric/thoughts/2025/08/07/infinite-pixels/
// it seems to be 17,895,700 in Firefox, 33,554,400 in Chrome and 33,554,428 in Safari
// Disabled for now
export const maxElementHeight = Infinity
export const maxElementHeight = 8_000_000 // a safe maximum height for an element in the DOM

// 16,500px is ~0.2% of the canvas height for 8M px, it corresponds to 500 rows at 33px height.
// -> when scrolling with the mouse wheel, the change is local (< 16,500px)
// -> when scrolling with the scrollbar (drag/drop), or with the mouse wheel for a long time (> 500 rows), the change is global (> 0.2% of the scrollbar height)
// -> on mobile, swapping will also produce big jumps.
// TODO(SL): should we detect touch events and adapt the thresholds on mobile?
// TODO(SL): decrease/increase the threshold? make it configurable? or dependent on the number of rows, ie: a % of the scroll bar height?
export const largeScrollPx = 500 * rowHeight // px threshold to consider a scroll as "large"
Loading