@@ -36,7 +36,7 @@ export interface TableProps<K = string, T = string> {
3636 /** Height of cells in pixels. */
3737 cellHeight ?: number
3838 /** The state of the selected cell or cells in the table. */
39- activeRange : ActiveRange
39+ activeRange ? : ActiveRange
4040 /** Sets the state of the selected cell or cells in the table. */
4141 setActiveRange ?: ( range : ActiveRange ) => void
4242 /** Gets the value in a cell. */
@@ -89,11 +89,10 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
8989 // Row and column counts
9090 const numRows = ( ) => props . numRows
9191 const numCols = ( ) => props . columns . length
92- const minCell = ( ) => [ 0 , 0 ] as const
93- const maxCell = ( ) => [ numRows ( ) - 1 , numCols ( ) - 1 ] as const
9492
9593 // The active cell range
9694 const activeRange = createMemo ( ( ) => {
95+ if ( ! props . activeRange ) return undefined
9796 const { cell, range } = props . activeRange
9897 const maxRow = Math . max ( numRows ( ) - 1 , 0 )
9998 const maxCol = Math . max ( numCols ( ) - 1 , 0 )
@@ -114,13 +113,15 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
114113 } )
115114
116115 // The active cell, which may be within a range
117- const activeCell = ( ) => activeRange ( ) . cell
116+ const activeCell = ( ) => activeRange ( ) ? .cell
118117
119118 // Details about the active cell
120119 const activeCellData = createMemo ( ( ) => {
121- const [ rowIdx , colIdx ] = activeCell ( )
122- const column = props . columns [ colIdx ]
123- if ( rowIdx >= props . numRows || ! column ) return undefined
120+ const cell = activeCell ( )
121+ if ( ! cell ) return undefined
122+ const rowIdx = cell [ 0 ]
123+ const column = props . columns [ cell [ 1 ] ]
124+ if ( cell [ 0 ] >= props . numRows || ! column ) return undefined
124125 return { rowIdx, column }
125126 } )
126127
@@ -316,7 +317,7 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
316317
317318 // Moves focus to the given cell without modifying the selected range
318319 const moveWithinRange = ( [ i , j ] : CellIndex ) => {
319- const range = props . activeRange . range
320+ const range = props . activeRange ? .range
320321 const min = range ?. min ?? [ 0 , 0 ]
321322 const max = range ?. max ?? [ numRows ( ) - 1 , numCols ( ) - 1 ]
322323
@@ -334,6 +335,8 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
334335
335336 // Moves the cell range to the given cell
336337 const rangeToCell = ( i ?: number , j ?: number ) => {
338+ if ( ! props . activeRange ) return
339+
337340 if ( i != null ) i = Math . max ( Math . min ( i , numRows ( ) - 1 ) , 0 )
338341 if ( j != null ) j = Math . max ( Math . min ( j , numCols ( ) - 1 ) , 0 )
339342
@@ -350,12 +353,14 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
350353
351354 // Moves focus to the given cell, but only if it is outside the active range
352355 const moveToCellIfOutside = ( i : number , j : number ) => {
356+ const range = activeRange ( )
357+ if ( ! range ) return
358+
353359 i = Math . max ( Math . min ( i , numRows ( ) - 1 ) , 0 )
354360 j = Math . max ( Math . min ( j , numCols ( ) - 1 ) , 0 )
355361 const cell = [ i , j ] as const
356362
357- const { min, max } = activeRange ( )
358- if ( i < min [ 0 ] || i > max [ 0 ] || j < min [ 1 ] || j > max [ 1 ] ) {
363+ if ( i < range . min [ 0 ] || i > range . max [ 0 ] || j < range . min [ 1 ] || j > range . max [ 1 ] ) {
359364 props . setActiveRange ?.( { cell } )
360365 scrollToCell ( i , j )
361366 focus ( )
@@ -433,6 +438,8 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
433438 ev ?. preventDefault ( )
434439
435440 const range = activeRange ( )
441+ if ( ! range ) return
442+
436443 props . onCopy ?.( range . min , range . max )
437444 }
438445
@@ -441,13 +448,17 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
441448 if ( ! props . rowsEditable ) return
442449
443450 const range = activeRange ( )
451+ if ( ! range ) return
452+
444453 props . onPaste ?.( range . min , range . max )
445454 }
446455
447456 // Handle keyboard events
448457 const handleKeyDown = ( ev : KeyboardEvent ) => {
449- const { cell, shiftCell, min, max } = activeRange ( )
458+ const range = activeRange ( )
459+ if ( ! range ) return
450460
461+ const { cell, shiftCell, min, max } = range
451462 const delta = ev [ modifierKey ] ? Infinity : 1
452463
453464 if ( ev . key . startsWith ( 'Arrow' ) ) {
@@ -507,7 +518,8 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
507518 }
508519
509520 // Compute dimensions for active cell outline
510- const calcOutline = ( min : CellIndex , max : CellIndex ) => {
521+ const calcOutline = ( min ?: CellIndex , max ?: CellIndex ) => {
522+ if ( ! min || ! max ) return undefined
511523 const left = columnSize ( min [ 1 ] ) ?. left ?? 0
512524 const right = columnSize ( max [ 1 ] ) ?. right ?? 0
513525 const width = right - left + px ( )
@@ -517,16 +529,18 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
517529 return { left, right, top, bottom, width, height }
518530 }
519531 const activeCellOutline = createMemo ( ( ) => calcOutline ( activeCell ( ) , activeCell ( ) ) )
520- const activeRangeOutline = createMemo ( ( ) => calcOutline ( activeRange ( ) . min , activeRange ( ) . max ) )
532+ const activeRangeOutline = createMemo ( ( ) => calcOutline ( activeRange ( ) ? .min , activeRange ( ) ? .max ) )
521533
522534 // Monitor scroll position
523535 const cellIntersectsLeft = createMemo ( ( ) => {
524536 const outline = activeRangeOutline ( )
537+ if ( ! outline ) return false
525538 const x = viewport ( ) . left + rowHeaderWidth ( ) - outline . left
526539 return x >= 0 && x <= outline . width
527540 } )
528541 const cellIntersectsTop = createMemo ( ( ) => {
529542 const outline = activeRangeOutline ( )
543+ if ( ! outline ) return false
530544 const y = viewport ( ) . top + colHeaderHeight ( ) - outline . top
531545 return y >= 0 && y <= outline . height
532546 } )
@@ -543,8 +557,8 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
543557 if ( shouldRestoreScroll ) return
544558 props . onScrollPositionChange ?.( ev . currentTarget . scrollLeft , ev . currentTarget . scrollTop )
545559 } }
546- onMouseMove = { onCellMove }
547- onMouseUp = { onCellUp }
560+ onPointerMove = { onCellMove }
561+ onPointerUp = { onCellUp }
548562 tabIndex = { - 1 }
549563 >
550564 < div ref = { focusEl } class = "solid-tabular/focus-proxy" tabIndex = { - 1 } contentEditable />
@@ -626,7 +640,6 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
626640 rowIdx = { item . index }
627641 top = { item . start }
628642 height = { item . size }
629- isActive = { item . index >= activeRange ( ) . min [ 0 ] && item . index <= activeRange ( ) . max [ 0 ] }
630643 getCellValue = { props . getCellValue }
631644 setCellValue = { props . setCellValue }
632645 onPointerDown = { onCellDown }
@@ -641,7 +654,7 @@ export default function Table<K = string, T = unknown>(props: TableProps<K, T>)
641654 { ( { rowIdx, column } ) => (
642655 < CellInputContainer
643656 component = { column . component }
644- rect = { activeCellOutline ( ) }
657+ rect = { activeCellOutline ( ) ! }
645658 value = { props . getCellValue ( rowIdx , column ) }
646659 readonly = { ! props . cellsEditable || ! ! column . readonly }
647660 setValue = { value => props . setCellValue ?.( rowIdx , column . id , value ) }
0 commit comments