-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create GridTrackTable - to replace TrackTables in the future
- Loading branch information
Showing
8 changed files
with
391 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
packages/ui/lib/components/GridTrackTable/Cells/TextCell.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
|
||
import React from 'react'; | ||
import { CellProps } from 'react-table'; | ||
import cx from 'classnames'; | ||
|
||
import { Track } from '@nuclear/core'; | ||
|
||
import styles from '../styles.scss'; | ||
|
||
|
||
export const TextCell: React.FC<CellProps<Track>> = ({ | ||
cell, | ||
value | ||
}) => <div | ||
{...cell.getCellProps()} | ||
className={cx(styles.track_table_cell)} | ||
> | ||
{value} | ||
</div>; |
16 changes: 16 additions & 0 deletions
16
packages/ui/lib/components/GridTrackTable/Cells/ThumbnailCell.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from 'react'; | ||
import { CellProps } from 'react-table'; | ||
import cx from 'classnames'; | ||
|
||
import { Track } from '../../../types'; | ||
import styles from '../styles.scss'; | ||
|
||
export const ThumbnailCell: React.FC<CellProps<Track>> = ({ | ||
cell, | ||
value | ||
}) => <div | ||
className={cx(styles.track_table_cell, styles.thumbnail_cell)} | ||
{...cell.getCellProps()} | ||
> | ||
<img className={styles.thumbnail_cell_thumbnail} src={value} /> | ||
</div>; |
30 changes: 30 additions & 0 deletions
30
packages/ui/lib/components/GridTrackTable/Headers/TextHeader.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { ColumnInstance, UseSortByColumnProps } from 'react-table'; | ||
import { Track } from '../../../types'; | ||
import React from 'react'; | ||
import { Icon } from 'semantic-ui-react'; | ||
|
||
type TextHeaderProps = { | ||
column: ColumnInstance<Track> & UseSortByColumnProps<Track>; | ||
header: string | React.ReactNode; | ||
'data-testid'?: string; | ||
}; | ||
|
||
export const TextHeader: React.FC<TextHeaderProps> = ({ | ||
column, | ||
header, | ||
'data-testid': dataTestId | ||
}) => { | ||
const { isSorted, isSortedDesc } = column; | ||
const name = isSortedDesc | ||
? 'sort content descending' : 'sort content ascending'; | ||
|
||
return ( | ||
<div data-testid={dataTestId}> | ||
{header} | ||
{ | ||
isSorted && | ||
<Icon name={name} /> | ||
} | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
import { Row, TableInstance, TableState, UseSortByInstanceProps, UseSortByState, useSortBy, useTable } from 'react-table'; | ||
import React, { useMemo, memo } from 'react'; | ||
import { DragDropContext, DragDropContextProps, Draggable, Droppable } from 'react-beautiful-dnd'; | ||
import cx from 'classnames'; | ||
import { FixedSizeList, FixedSizeList as List } from 'react-window'; | ||
import AutoSizer from 'react-virtualized-auto-sizer'; | ||
|
||
import { TrackTableColumn, TrackTableHeaders, TrackTableSettings } from '../TrackTable/types'; | ||
import { TextHeader } from './Headers/TextHeader'; | ||
import { TextCell } from './Cells/TextCell'; | ||
import { Track } from '../../types'; | ||
import { getTrackThumbnail } from '../TrackRow'; | ||
|
||
import styles from './styles.scss'; | ||
import artPlaceholder from '../../../resources/media/art_placeholder.png'; | ||
import { ThumbnailCell } from './Cells/ThumbnailCell'; | ||
|
||
type GridTrackTableRowProps<T extends Track> = { | ||
data: { | ||
rows: TableInstance<T>['rows']; | ||
prepareRow: TableInstance<T>['prepareRow']; | ||
extraProps: TrackTableSettings; | ||
}; | ||
index: number; | ||
style: React.CSSProperties; | ||
} | ||
|
||
const GridTrackTableRow = memo(<T extends Track>({ index, style, data }: GridTrackTableRowProps<T>) => { | ||
const row = data.rows[index]; | ||
data.prepareRow(row); | ||
return <Draggable | ||
key={row.id} | ||
draggableId={row.id} | ||
index={row.index} | ||
isDragDisabled={false} | ||
> | ||
{ | ||
(draggableProvided, draggableSnapshot) => ( | ||
<div | ||
data-test-id='track-table-row' | ||
className={cx( | ||
styles.track_table_row, | ||
{ [styles.is_dragging]: draggableSnapshot.isDragging } | ||
)} | ||
ref={draggableProvided.innerRef} | ||
{...row.getRowProps()} | ||
{...draggableProvided.draggableProps} | ||
{...draggableProvided.dragHandleProps} | ||
style={style ? { | ||
...draggableProvided.draggableProps.style, | ||
...style | ||
} : draggableProvided.draggableProps.style} | ||
> | ||
{row.cells.map((cell, i) => cell.render( | ||
'Cell', | ||
{ ...data.extraProps, key: i } | ||
))} | ||
</div> | ||
)} | ||
</Draggable>; | ||
}); | ||
|
||
export type GridTrackTableProps<T extends Track> = { | ||
tracks: T[]; | ||
onDragEnd?: DragDropContextProps['onDragEnd']; | ||
} & TrackTableHeaders & TrackTableSettings; | ||
|
||
export const GridTrackTable = <T extends Track>({ | ||
tracks, | ||
|
||
titleHeader, | ||
thumbnailHeader, | ||
|
||
displayArtist=true, | ||
displayThumbnail=true, | ||
|
||
...extraProps | ||
}: GridTrackTableProps<T>) => { | ||
const columns = useMemo(() => [ | ||
displayThumbnail && { | ||
id: TrackTableColumn.Thumbnail, | ||
Header: () => <span className={styles.center_aligned}>{thumbnailHeader}</span>, | ||
accessor: (track) => getTrackThumbnail(track) || artPlaceholder, | ||
Cell: ThumbnailCell | ||
}, | ||
{ | ||
id: TrackTableColumn.Title, | ||
Header: ({ column }) => <TextHeader column={column} header={titleHeader} />, | ||
accessor: (track) => track.title ?? track.name, | ||
Cell: TextCell, | ||
enableSorting: true | ||
} | ||
], [displayArtist, displayThumbnail]); | ||
|
||
const data = useMemo(() => tracks, [tracks]); | ||
|
||
const initialState: Partial<TableState<T> & UseSortByState<T>> = { | ||
sortBy: [{ id: TrackTableColumn.Title, desc: false }] | ||
}; | ||
const table = useTable<T>({ columns, data, initialState }, useSortBy) as (TableInstance<T> & UseSortByInstanceProps<T>); | ||
|
||
const {getTableProps, getTableBodyProps, headerGroups, rows, prepareRow} = table; | ||
|
||
return <div className={styles.track_table_wrapper}> | ||
<div | ||
className={styles.track_table} | ||
{...getTableProps()} | ||
> | ||
<div className={styles.track_table_head}> | ||
{headerGroups.map(headerGroup => ( | ||
<div | ||
key={headerGroup.id} | ||
className={styles.track_table_header_row} | ||
{...headerGroup.getHeaderGroupProps()} | ||
> | ||
{ | ||
headerGroup.headers.map(column => ( | ||
<div | ||
key={column.id} | ||
className={styles.track_table_header_cell} | ||
{...column.getHeaderProps()} | ||
> | ||
{column.render('Header')} | ||
</div>)) | ||
} | ||
</div> | ||
))} | ||
</div> | ||
<DragDropContext onDragEnd={() => {}}> | ||
<Droppable droppableId='track_table'> | ||
{(droppableProvided) => ( | ||
<div | ||
data-testid='track-table-body' | ||
className={styles.track_table_body} | ||
ref={droppableProvided.innerRef} | ||
{...getTableBodyProps()} | ||
{...droppableProvided.droppableProps} | ||
> | ||
<AutoSizer> | ||
{({ height, width }) => | ||
<> | ||
<FixedSizeList | ||
height={829} | ||
width={width} | ||
itemSize={42} | ||
itemCount={rows.length} | ||
overscanCount={2} | ||
itemData={{ | ||
rows: rows as Row<Track>[], | ||
prepareRow: prepareRow as (row: Row<Track>) => void, | ||
extraProps | ||
}} | ||
outerRef={droppableProvided.innerRef} | ||
> | ||
{GridTrackTableRow} | ||
</FixedSizeList> | ||
{droppableProvided.placeholder} | ||
</> | ||
} | ||
</AutoSizer> | ||
</div> | ||
)} | ||
</Droppable> | ||
</DragDropContext> | ||
</div> | ||
</div>; | ||
}; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
@import "../../common.scss"; | ||
|
||
.track_table_wrapper { | ||
position: relative; | ||
display: flex; | ||
flex-flow: column; | ||
overflow: hidden; | ||
height: 100%; | ||
} | ||
|
||
.track_table { | ||
position: relative; | ||
display: flex; | ||
flex-flow: column; | ||
width: 100%; | ||
flex: 1 1 auto; | ||
|
||
.track_table_head { | ||
display: grid; | ||
background: $bgdefault; | ||
color: $white; | ||
grid-template-columns: 1fr; | ||
flex: 0 0 auto; | ||
} | ||
|
||
.track_table_header_row { | ||
display: grid; | ||
grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); | ||
width: 100%; | ||
} | ||
|
||
.track_table_header_cell { | ||
display: table-cell; | ||
padding: 1em; | ||
text-align: left; | ||
} | ||
|
||
.track_table_body { | ||
display: block; | ||
gap: 0.25em; | ||
overflow: auto; | ||
flex: 1 1 auto; | ||
|
||
&.body_dragged_over { | ||
background: $bgdark; | ||
} | ||
} | ||
|
||
.track_table_row { | ||
display: grid; | ||
grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); | ||
gap: 1em; | ||
|
||
color: $white; | ||
|
||
&:hover { | ||
background: rgba($bgdefault, 0.25); | ||
} | ||
} | ||
|
||
.track_table_cell { | ||
display: flex; | ||
align-items: center; | ||
} | ||
} | ||
|
||
.thumbnail_cell { | ||
height: 3em; | ||
.thumbnail_cell_thumbnail { | ||
display: block; | ||
width: 3em; | ||
height: 3em; | ||
object-fit: contain; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.