Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support data prop for grouped mode #235

Open
petyosi opened this issue Dec 15, 2020 · 1 comment
Open

Support data prop for grouped mode #235

petyosi opened this issue Dec 15, 2020 · 1 comment
Labels
enhancement New feature or request sponsor-or-pr Contribute or sponsor the solution using GH sponsors

Comments

@petyosi
Copy link
Owner

petyosi commented Dec 15, 2020

Since the flat and the grouped component are the same, there should be a way to detect the grouped mode. Most intuitive would be an array of arrays. Partially reported in #232.

@Hideman85
Copy link

I think it would be better to revise the props of GroupedVirtuoso to something more intuitive like:

interface GroupedVirtuosoProps<T> extends Omit<VirtuosoProps<T>, 'totalCount' | 'itemContent'> {
  groups: {
    items: T[]
    RenderItem: React.FC<{ item: T, index: number }>
    RenderGroup: React.FC
  }[]
}

If people want a wrapper you could use this:

export interface CustomGroupedVirtuosoProps<T> extends Omit<VirtuosoProps<T>, 'totalCount' | 'itemContent'> {
  groups: {
    items: T[]
    RenderItem: React.FC<{ item: T, index: number }>
    RenderGroup: React.FC
  }[]
}

export const CustomGroupedVirtuoso = <T extends unknown>({ groups, ...props }: React.PropsWithChildren<CustomGroupedVirtuosoProps<T>>): React.ReactElement => {
  const virtuosoProps = useMemo<Pick<GroupedVirtuosoProps<T>, 'data' | 'itemContent' | 'groupContent' | 'groupCounts'>>(() => {
    const groupCounts: number[] = []
    let data: T[] = []
    const formattedGroups: (Pick<CustomGroupedVirtuosoProps<T>['groups'][0], 'RenderGroup' | 'RenderItem'> & { firstIndex: number })[] = []

    let size = 0
    groups.forEach(({ items, RenderGroup, RenderItem }) => {
      const prevSize = size
      size += items.length
      groupCounts.push(items.length)
      data = data.concat(items)

      formattedGroups.push({
        firstIndex: prevSize,
        RenderGroup: React.memo(RenderGroup),
        RenderItem: React.memo(RenderItem)
      })
    })

    const itemContent: GroupedVirtuosoProps<T>['itemContent'] = (globalIndex, groupIndex, item) => {
      const { RenderItem, firstIndex } = formattedGroups[groupIndex]
      const index = globalIndex - firstIndex

      return <RenderItem index={index} item={item} />
    }

    const groupContent: GroupedVirtuosoProps<T>['groupContent'] = groupIndex => {
      const { RenderGroup } = formattedGroups[groupIndex]

      return <RenderGroup />
    }

    return { data, itemContent, groupContent, groupCounts }
  }, [groups])

  return <GroupedVirtuoso {...props} {...virtuosoProps} />
}

@petyosi petyosi added the sponsor-or-pr Contribute or sponsor the solution using GH sponsors label Mar 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request sponsor-or-pr Contribute or sponsor the solution using GH sponsors
Projects
None yet
Development

No branches or pull requests

2 participants