Repository: h2oai/wave
File: ui/src/table.tsx (TypeScript)

Code before:
        }} />
        : null,
      onItemInvoked = (item: Fluent.IObjectWithKey & Dict<any>) => {
        wave.args[m.name] = [item.key as S]
        wave.push()
      },
      onRenderItemColumn = (item?: Fluent.IObjectWithKey & Dict<any>, _idx?: U, col?: WaveColumn) => {
        if (!item || !col) return <span />

        const TooltipWrapper = ({ children }: { children: S }) => {
          if (col.cellOverflow === 'tooltip') return (
            <Fluent.TooltipHost
              id={item.key as S}
              // HACK: prevent Safari from showing a default tooltip - https://github.com/microsoft/fluentui/issues/13868
              styles={{ root: { '::after': { content: '', display: 'block' } } }}
              content={children}
              overflowMode={Fluent.TooltipOverflowMode.Parent}
              title={children}
            >{children}</Fluent.TooltipHost>
          )
          return <>{children}</>
        }

        const AlignmentWrapper = ({ children }: { children: any }) => {
          const alignment = col.alignment ? col.alignment : 'left'
          return <div style={{ display: 'flex', justifyContent: alignment, textAlign: alignment }}>{children}</div>
        }

        let v = item[col.fieldName as S]
        if (col.cellType?.progress) return <AlignmentWrapper><XProgressTableCellType model={col.cellType.progress} progress={item[col.key]} /></AlignmentWrapper>
        if (col.cellType?.icon) return <AlignmentWrapper> <XIconTableCellType model={col.cellType.icon} icon={item[col.key]} /></AlignmentWrapper>
        if (col.cellType?.tag) return <AlignmentWrapper><XTagTableCellType model={col.cellType.tag} serializedTags={item[col.key]} /></AlignmentWrapper>
        if (col.cellType?.menu) return <AlignmentWrapper><XMenuTableCellType model={{ ...col.cellType.menu, rowId: String(item.key) }} /></AlignmentWrapper>
        if (col.cellType?.markdown) return <AlignmentWrapper><XMarkdownTableCellType model={{ ...col.cellType.markdown, content: item[col.key] }} /></AlignmentWrapper>
        if (col.dataType === 'time') {
          const epoch = Number(v)
          v = new Date(isNaN(epoch) ? v : epoch).toLocaleString()
        }

        const wrappedItem = <AlignmentWrapper><TooltipWrapper>{v}</TooltipWrapper></AlignmentWrapper>

        if (col.key === primaryColumnKey) {
          const onClick = () => {
            wave.args[m.name] = [item.key as S]
            wave.push()
          }
          return <AlignmentWrapper><Fluent.Link onClick={onClick}>{wrappedItem}</Fluent.Link></AlignmentWrapper>
        }

        return wrappedItem
      },

Review comment (suggestion):
```suggestion
          const alignment = col.alignment || 'left'
          return <div style={{ display: 'flex', justifyContent: alignment, textAlign: alignment }}>{children}</div>
```

Code after:
          if (col.cellOverflow === 'tooltip') return (
            <Fluent.TooltipHost
              id={item.key as S}
              // HACK: prevent Safari from showing a default tooltip - https://github.com/microsoft/fluentui/issues/13868
              styles={{ root: { '::after': { content: '', display: 'block' } } }}
              content={children}
              overflowMode={Fluent.TooltipOverflowMode.Parent}
            >{children}</Fluent.TooltipHost>
          )
          return <>{children}</>
        }

        let v = item[col.fieldName as S]
        if (col.cellType?.progress) return <XProgressTableCellType model={col.cellType.progress} progress={item[col.key]} />
        if (col.cellType?.icon) return <XIconTableCellType model={col.cellType.icon} icon={item[col.key]} />
        if (col.cellType?.tag) return <XTagTableCellType model={col.cellType.tag} serializedTags={item[col.key]} />
        if (col.cellType?.menu) return <XMenuTableCellType model={{ ...col.cellType.menu, rowId: String(item.key) }} />
        if (col.cellType?.markdown) return <XMarkdownTableCellType model={{ ...col.cellType.markdown, content: item[col.key] }} />
        if (col.dataType === 'time') {
          const epoch = Number(v)
          v = new Date(isNaN(epoch) ? v : epoch).toLocaleString()
        }

        if (col.key === primaryColumnKey) {
          const onClick = () => {
            wave.args[m.name] = [item.key as S]
            wave.push()
          }
          return <TooltipWrapper><Fluent.Link onClick={onClick} styles={{ root: { textAlign: col?.align || 'left' } }}>{v}</Fluent.Link></TooltipWrapper>
        }

        return <TooltipWrapper>{v}</TooltipWrapper>
      },
      onRenderItemColumn = (item?: Fluent.IObjectWithKey & Dict<any>, _idx?: U, col?: WaveColumn) => {
        const align = col?.align || 'left'
        return <div style={{ display: 'flex', justifyContent: align, textAlign: align }}>{getCellComponent(item, _idx, col)}</div>
      },
      // HACK: fixed jumping scrollbar issue when scrolling into the end of list with all groups expanded - https://github.com/microsoft/fluentui/pull/5204 
      getGroupHeight = (group: Fluent.IGroup) => {
        const
          rowHeight = m.columns.some(c => c.cell_type?.progress) ? 76 : 48,
          groupHeaderHeight = 48
        return groupHeaderHeight + (group.isCollapsed ? 0 : rowHeight * group.count)
      }

    // HACK: React stale closures - https://reactjs.org/docs/hooks-faq.html#why-am-i-seeing-stale-props-or-state-inside-my-function
    // TODO: Find a reasonable way of doing this.
    React.useEffect(() => { { selectedFiltersRef.current = selectedFilters } }, [selectedFilters])
    React.useImperativeHandle(ref, () => ({
      resetSortIcons: () => {
        setColumns(columns.map(col => {