@@ -2690,62 +2690,40 @@ export function Table({
26902690 < TableBodySkeleton colCount = { displayColCount } />
26912691 ) : (
26922692 < >
2693- { rows . map ( ( row , index ) => {
2694- const prevPosition = index > 0 ? rows [ index - 1 ] . position : - 1
2695- const gapCount =
2696- queryOptions . filter || queryOptions . sort
2697- ? 0
2698- : row . position - prevPosition - 1
2699- return (
2700- < React . Fragment key = { row . id } >
2701- { gapCount > 0 && (
2702- < PositionGapRows
2703- count = { gapCount }
2704- startPosition = { prevPosition + 1 }
2705- columns = { displayColumns }
2706- normalizedSelection = { normalizedSelection }
2707- checkedRows = { checkedRows }
2708- firstRowUnderHeader = { prevPosition === - 1 }
2709- onCellMouseDown = { handleCellMouseDown }
2710- onCellMouseEnter = { handleCellMouseEnter }
2711- onRowToggle = { handleRowToggle }
2712- />
2713- ) }
2714- < DataRow
2715- row = { row }
2716- columns = { displayColumns }
2717- rowIndex = { row . position }
2718- isFirstRow = { row . position === 0 }
2719- editingColumnName = {
2720- editingCell ?. rowId === row . id ? editingCell . columnName : null
2721- }
2722- initialCharacter = {
2723- editingCell ?. rowId === row . id ? initialCharacter : null
2724- }
2725- pendingCellValue = {
2726- pendingUpdate && pendingUpdate . rowId === row . id
2727- ? pendingUpdate . data
2728- : null
2729- }
2730- normalizedSelection = { normalizedSelection }
2731- onClick = { handleCellClick }
2732- onDoubleClick = { handleCellDoubleClick }
2733- onSave = { handleInlineSave }
2734- onCancel = { handleInlineCancel }
2735- onContextMenu = { handleRowContextMenu }
2736- onCellMouseDown = { handleCellMouseDown }
2737- onCellMouseEnter = { handleCellMouseEnter }
2738- isRowChecked = { checkedRows . has ( row . position ) }
2739- onRowToggle = { handleRowToggle }
2740- runningCount = { runningByRowId . get ( row . id ) ?? 0 }
2741- hasWorkflowColumns = { hasWorkflowColumns }
2742- onStopRow = { handleStopRow }
2743- onRunRow = { handleRunRow }
2744- workflowNameById = { workflowNameById }
2745- />
2746- </ React . Fragment >
2747- )
2748- } ) }
2693+ { rows . map ( ( row , index ) => (
2694+ < DataRow
2695+ key = { row . id }
2696+ row = { row }
2697+ columns = { displayColumns }
2698+ rowIndex = { row . position }
2699+ arrayIndex = { index }
2700+ isFirstRow = { row . position === 0 }
2701+ editingColumnName = {
2702+ editingCell ?. rowId === row . id ? editingCell . columnName : null
2703+ }
2704+ initialCharacter = { editingCell ?. rowId === row . id ? initialCharacter : null }
2705+ pendingCellValue = {
2706+ pendingUpdate && pendingUpdate . rowId === row . id
2707+ ? pendingUpdate . data
2708+ : null
2709+ }
2710+ normalizedSelection = { normalizedSelection }
2711+ onClick = { handleCellClick }
2712+ onDoubleClick = { handleCellDoubleClick }
2713+ onSave = { handleInlineSave }
2714+ onCancel = { handleInlineCancel }
2715+ onContextMenu = { handleRowContextMenu }
2716+ onCellMouseDown = { handleCellMouseDown }
2717+ onCellMouseEnter = { handleCellMouseEnter }
2718+ isRowChecked = { checkedRows . has ( row . position ) }
2719+ onRowToggle = { handleRowToggle }
2720+ runningCount = { runningByRowId . get ( row . id ) ?? 0 }
2721+ hasWorkflowColumns = { hasWorkflowColumns }
2722+ onStopRow = { handleStopRow }
2723+ onRunRow = { handleRunRow }
2724+ workflowNameById = { workflowNameById }
2725+ />
2726+ ) ) }
27492727 </ >
27502728 ) }
27512729 </ tbody >
@@ -2947,157 +2925,6 @@ export function Table({
29472925 )
29482926}
29492927
2950- const GAP_ROW_LIMIT = 200
2951- const GAP_CHECKBOX_CLASS = cn ( CELL_CHECKBOX , 'cursor-pointer' )
2952-
2953- interface PositionGapRowsProps {
2954- count : number
2955- startPosition : number
2956- columns : DisplayColumn [ ]
2957- normalizedSelection : NormalizedSelection | null
2958- checkedRows : Set < number >
2959- firstRowUnderHeader ?: boolean
2960- onCellMouseDown : ( rowIndex : number , colIndex : number , shiftKey : boolean ) => void
2961- onCellMouseEnter : ( rowIndex : number , colIndex : number ) => void
2962- onRowToggle : ( rowIndex : number , shiftKey : boolean ) => void
2963- }
2964-
2965- const PositionGapRows = React . memo (
2966- function PositionGapRows ( {
2967- count,
2968- startPosition,
2969- columns,
2970- normalizedSelection,
2971- checkedRows,
2972- firstRowUnderHeader = false ,
2973- onCellMouseDown,
2974- onCellMouseEnter,
2975- onRowToggle,
2976- } : PositionGapRowsProps ) {
2977- const capped = Math . min ( count , GAP_ROW_LIMIT )
2978- const sel = normalizedSelection
2979- const isMultiCell = sel !== null && ( sel . startRow !== sel . endRow || sel . startCol !== sel . endCol )
2980-
2981- return (
2982- < >
2983- { Array . from ( { length : capped } ) . map ( ( _ , i ) => {
2984- const position = startPosition + i
2985- const isGapChecked = checkedRows . has ( position )
2986- return (
2987- < tr key = { `gap-${ position } ` } >
2988- < td className = { GAP_CHECKBOX_CLASS } >
2989- < div className = 'flex items-center justify-center gap-1' >
2990- < div
2991- className = 'group/checkbox flex h-[20px] w-[24px] shrink-0 items-center justify-center'
2992- onMouseDown = { ( e ) => {
2993- if ( e . button !== 0 ) return
2994- onRowToggle ( position , e . shiftKey )
2995- } }
2996- >
2997- < span
2998- className = { cn (
2999- 'text-[var(--text-tertiary)] text-xs tabular-nums' ,
3000- isGapChecked ? 'hidden' : 'block group-hover/checkbox:hidden'
3001- ) }
3002- >
3003- { position + 1 }
3004- </ span >
3005- < div
3006- className = { cn (
3007- 'items-center justify-center' ,
3008- isGapChecked ? 'flex' : 'hidden group-hover/checkbox:flex'
3009- ) }
3010- >
3011- < Checkbox size = 'sm' checked = { isGapChecked } className = 'pointer-events-none' />
3012- </ div >
3013- </ div >
3014- </ div >
3015- </ td >
3016- { columns . map ( ( col , colIndex ) => {
3017- const inRange =
3018- sel !== null &&
3019- position >= sel . startRow &&
3020- position <= sel . endRow &&
3021- colIndex >= sel . startCol &&
3022- colIndex <= sel . endCol
3023- const isAnchor =
3024- sel !== null && position === sel . anchorRow && colIndex === sel . anchorCol
3025- const isHighlighted = inRange || isGapChecked
3026-
3027- const isTopEdge = inRange ? position === sel ! . startRow : isGapChecked
3028- const isBottomEdge = inRange ? position === sel ! . endRow : isGapChecked
3029- const isLeftEdge = inRange ? colIndex === sel ! . startCol : colIndex === 0
3030- const isRightEdge = inRange
3031- ? colIndex === sel ! . endCol
3032- : colIndex === columns . length - 1
3033- const belowHeader = firstRowUnderHeader && i === 0
3034-
3035- return (
3036- < td
3037- key = { col . key }
3038- data-row = { position }
3039- data-col = { colIndex }
3040- className = { cn ( CELL , ( isHighlighted || isAnchor ) && 'relative' ) }
3041- onMouseDown = { ( e ) => {
3042- if ( e . button !== 0 ) return
3043- onCellMouseDown ( position , colIndex , e . shiftKey )
3044- } }
3045- onMouseEnter = { ( ) => onCellMouseEnter ( position , colIndex ) }
3046- >
3047- { isHighlighted && ( isMultiCell || isGapChecked ) && (
3048- < div
3049- className = { cn (
3050- '-top-px -right-px -bottom-px -left-px pointer-events-none absolute z-[4]' ,
3051- SELECTION_TINT_BG ,
3052- belowHeader && isTopEdge && 'top-0' ,
3053- isTopEdge && 'border-t border-t-[var(--selection)]' ,
3054- isBottomEdge && 'border-b border-b-[var(--selection)]' ,
3055- isLeftEdge && 'border-l border-l-[var(--selection)]' ,
3056- isRightEdge && 'border-r border-r-[var(--selection)]'
3057- ) }
3058- />
3059- ) }
3060- { isAnchor && < div className = { cn ( SELECTION_OVERLAY , belowHeader && 'top-0' ) } /> }
3061- < div className = 'min-h-[20px]' />
3062- </ td >
3063- )
3064- } ) }
3065- </ tr >
3066- )
3067- } ) }
3068- { count > GAP_ROW_LIMIT && (
3069- < tr >
3070- < td
3071- colSpan = { columns . length + 2 }
3072- className = 'border-[var(--border)] border-r border-b p-0'
3073- style = { { height : `${ ( count - GAP_ROW_LIMIT ) * ROW_HEIGHT_ESTIMATE } px` } }
3074- />
3075- </ tr >
3076- ) }
3077- </ >
3078- )
3079- } ,
3080- ( prev , next ) => {
3081- if (
3082- prev . count !== next . count ||
3083- prev . startPosition !== next . startPosition ||
3084- prev . columns !== next . columns ||
3085- prev . normalizedSelection !== next . normalizedSelection ||
3086- prev . firstRowUnderHeader !== next . firstRowUnderHeader ||
3087- prev . onCellMouseDown !== next . onCellMouseDown ||
3088- prev . onCellMouseEnter !== next . onCellMouseEnter ||
3089- prev . onRowToggle !== next . onRowToggle
3090- ) {
3091- return false
3092- }
3093- const end = prev . startPosition + Math . min ( prev . count , GAP_ROW_LIMIT )
3094- for ( let p = prev . startPosition ; p < end ; p ++ ) {
3095- if ( prev . checkedRows . has ( p ) !== next . checkedRows . has ( p ) ) return false
3096- }
3097- return true
3098- }
3099- )
3100-
31012928const TableColGroup = React . memo ( function TableColGroup ( {
31022929 columns,
31032930 columnWidths,
@@ -3120,6 +2947,7 @@ interface DataRowProps {
31202947 row : TableRowType
31212948 columns : DisplayColumn [ ]
31222949 rowIndex : number
2950+ arrayIndex : number
31232951 isFirstRow : boolean
31242952 editingColumnName : string | null
31252953 initialCharacter : string | null
@@ -3180,6 +3008,7 @@ function dataRowPropsAreEqual(prev: DataRowProps, next: DataRowProps): boolean {
31803008 prev . row !== next . row ||
31813009 prev . columns !== next . columns ||
31823010 prev . rowIndex !== next . rowIndex ||
3011+ prev . arrayIndex !== next . arrayIndex ||
31833012 prev . isFirstRow !== next . isFirstRow ||
31843013 prev . editingColumnName !== next . editingColumnName ||
31853014 prev . pendingCellValue !== next . pendingCellValue ||
@@ -3219,6 +3048,7 @@ const DataRow = React.memo(function DataRow({
32193048 row,
32203049 columns,
32213050 rowIndex,
3051+ arrayIndex,
32223052 isFirstRow,
32233053 editingColumnName,
32243054 initialCharacter,
@@ -3266,7 +3096,7 @@ const DataRow = React.memo(function DataRow({
32663096 isRowSelected ? 'hidden' : 'block group-hover/checkbox:hidden'
32673097 ) }
32683098 >
3269- { row . position + 1 }
3099+ { arrayIndex + 1 }
32703100 </ span >
32713101 < div
32723102 className = { cn (
0 commit comments