mantinedev / mantine

A fully featured React components library
https://mantine.dev
MIT License
26.16k stars 1.85k forks source link

Export Pagination's DefaultItem #2703

Closed affanshahid closed 1 year ago

affanshahid commented 1 year ago

What package has an issue

@mantine/core

Describe the bug

I am using pagination and just want to wrap the default pagination controls in some anchor tags however I can't seem to import the DefaultItem from the pagination module, it isn't directly exported and I have to explicitly use the cjs path to import it. (Which lacks types so need to declare those manually as well).

What version of @mantine/hooks page do you have in package.json?

^5.5.4

If possible, please include a link to a codesandbox with the reproduced problem

No response

Do you know how to fix the issue

Yes

Are you willing to participate in fixing this issue and create a pull request with the fix

Yes

Possible fix

Export DefaultItem from https://github.com/mantinedev/mantine/blob/master/src/mantine-core/src/Pagination/index.ts

rtivital commented 1 year ago

You should set itemComponent instead:

function MyComponent({ page }) {
  return <div>{page}</div>
}

<Pagination itemComponent={MyComponent} />

DefaultItem is internal component, it will not be exported from the library.

shawnmclean commented 1 year ago

Is there an easier way to wrap the existing item component in a link?

rtivital commented 1 year ago

Use itemComponent prop as shown above

shawnmclean commented 1 year ago

Thanks, I'm doing that now, I'm making a new PaginationItem that can apply to other Pagination components, such as blog and podcasts.

function PaginationItem({ page, baseUrl }) {
  return (
    <Link href={`${baseUrl}/${page}`}>{page}</Link>
  );
}

How can I pass in the config to the component from here?

<Pagination
        total={totalPages}
        page={currentPage}
        itemComponent={PaginationItem}
      />
shawnmclean commented 1 year ago

For anyone else wanting to make this reusable:

<Pagination
  total={totalPages}
  page={currentPage}
  itemComponent={(props) => (
    <PaginationItem
      {...props}
      baseUrl={Config.blog.pageMeta.blogPage.slug}
    />
  )}
/>
function PaginationItem({
  page,
  baseUrl,
}: PaginationItemProps & { baseUrl: string }) {
  return <Link href={`${baseUrl}/${page}`}>{page}</Link>;
}

Full component:

import { createStyles } from '@mantine/core';
import { useMantineTheme } from '@mantine/styles';

import { IconDots, IconChevronRight, IconChevronLeft } from '@tabler/icons';
import Link from 'next/link';

const useStyles = createStyles((theme) => ({
  link: {
    textDecoration: 'none',
  },
}));

export interface LinkPaginationItemProps {
  page: number | 'dots' | 'prev' | 'next' | 'first' | 'last';
  currentPage: number;
  active?: boolean;
  basePageUrl: string;
  baseIndexUrl: string;
}

const icons = {
  dots: IconDots,
  next: IconChevronRight,
  prev: IconChevronLeft,
};

const rtlIcons = {
  dots: IconDots,
  prev: IconChevronRight,
  next: IconChevronLeft,
};

export default function LinkPaginationItem({
  page,
  currentPage,
  active,
  basePageUrl,
  baseIndexUrl,
  ...others
}: LinkPaginationItemProps) {
  const { classes } = useStyles();
  const theme = useMantineTheme();
  const Item = (theme.dir === 'rtl' ? rtlIcons : icons)[page];
  const children = Item ? <Item /> : page;

  let url = `${basePageUrl}/${page}`;
  switch (page) {
    case 'prev':
      url =
        currentPage === 2 ? baseIndexUrl : `${basePageUrl}/${currentPage - 1}`;
      break;
    case 'next':
      url = `${basePageUrl}/${currentPage + 1}`;
      break;
  }

  return (
    <Link href={url} className={classes.link}>
      <button type="button" {...others}>
        {children}
      </button>
    </Link>
  );
}
OrkhanAlikhanov commented 1 year ago

Seems like DefaultItem can be access from esm folder but typescript won't resolve types.

import {PaginationItemProps} from '@mantine/core'
import {
  DefaultItem as DefaultPaginationItem,
  // @ts-expect-error
} from '@mantine/core/esm/Pagination/DefaultItem/DefaultItem'

Note that since DefaultItem is an internal component it can be updated or removed without any need to be explained