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

[Pagination] Add TypeScript types #19933

Merged
merged 22 commits into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/pages/api/pagination.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,24 @@ You can learn more about the difference by [reading this guide](/guides/minimizi
| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| <span class="prop-name">boundaryCount</span> | <span class="prop-type">number</span> | <span class="prop-default">1</span> | Number of always visible pages at the beginning and end. |
| <span class="prop-name">children</span> | <span class="prop-type">node</span> | | Pagination items. |
| <span class="prop-name">children</span> | <span class="prop-type">node</span> | | The content of the component. |
| <span class="prop-name">classes</span> | <span class="prop-type">object</span> | | Override or extend the styles applied to the component. See [CSS API](#css) below for more details. |
| <span class="prop-name">color</span> | <span class="prop-type">'default'<br>&#124;&nbsp;'primary'<br>&#124;&nbsp;'secondary'</span> | <span class="prop-default">'standard'</span> | The active color. |
| <span class="prop-name">count</span> | <span class="prop-type">number</span> | <span class="prop-default">1</span> | The total number of pages. |
| <span class="prop-name">defaultPage</span> | <span class="prop-type">number</span> | <span class="prop-default">1</span> | The page selected by default when the component is uncontrolled. |
| <span class="prop-name">disabled</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, all the pagination component will be disabled. |
| <span class="prop-name">disabled</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, all the pagination components will be disabled. |
| <span class="prop-name">getItemAriaLabel</span> | <span class="prop-type">func</span> | | Accepts a function which returns a string value that provides a user-friendly name for the current page.<br>For localization purposes, you can use the provided [translations](/guides/localization/).<br><br>**Signature:**<br>`function(type?: string, page: number, selected: bool) => string`<br>*type:* The link or button type to format ('page' | 'first' | 'last' | 'next' | 'previous').<br>*page:* The page number to format.<br>*selected:* If true, the current page is selected. |
| <span class="prop-name">hideNextButton</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, hide the next-page button. |
| <span class="prop-name">hidePrevButton</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, hide the previous-page button. |
| <span class="prop-name">onChange</span> | <span class="prop-type">func</span> | | Callback fired when the page is changed.<br><br>**Signature:**<br>`function(event: object, page: number) => void`<br>*event:* The event source of the callback.<br>*page:* The page selected. |
| <span class="prop-name">page</span> | <span class="prop-type">number</span> | | The current page. |
| <span class="prop-name">renderItem</span> | <span class="prop-type">func</span> | <span class="prop-default">item => &lt;PaginationItem {...item} /></span> | Render the item.<br><br>**Signature:**<br>`function(params: object) => ReactNode`<br>*params:* The props to spread on a PaginationItem. |
| <span class="prop-name">renderItem</span> | <span class="prop-type">func</span> | <span class="prop-default">item => &lt;PaginationItem {...item} /></span> | Renders the item.<br><br>**Signature:**<br>`function(params: object) => ReactNode`<br>*params:* The props to spread on a PaginationItem. |
| <span class="prop-name">shape</span> | <span class="prop-type">'round'<br>&#124;&nbsp;'rounded'</span> | <span class="prop-default">'round'</span> | The shape of the pagination items. |
| <span class="prop-name">showFirstButton</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, show the first-page button. |
| <span class="prop-name">showLastButton</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, show the last-page button. |
| <span class="prop-name">siblingCount</span> | <span class="prop-type">number</span> | <span class="prop-default">1</span> | Number of always visible pages before and after the current page. |
| <span class="prop-name">size</span> | <span class="prop-type">'small'<br>&#124;&nbsp;'medium'<br>&#124;&nbsp;'large'</span> | <span class="prop-default">'medium'</span> | The size of the pagination component. |
| <span class="prop-name">variant</span> | <span class="prop-type">'text'<br>&#124;&nbsp;'outlined'</span> | <span class="prop-default">'text'</span> | The variant to use. |
| <span class="prop-name">size</span> | <span class="prop-type">'large'<br>&#124;&nbsp;'medium'<br>&#124;&nbsp;'small'</span> | <span class="prop-default">'medium'</span> | The size of the pagination component. |
| <span class="prop-name">variant</span> | <span class="prop-type">'outlined'<br>&#124;&nbsp;'text'</span> | <span class="prop-default">'text'</span> | The variant to use. |

The `ref` is forwarded to the root element.

Expand Down
98 changes: 96 additions & 2 deletions packages/material-ui-lab/src/Pagination/Pagination.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,96 @@
declare const Pagination: any;
export default Pagination;
import * as React from 'react';
import { StandardProps } from '@material-ui/core';
import { UsePaginationItem } from './usePagination';

export interface PaginationProps
extends StandardProps<React.HTMLAttributes<HTMLElement>, PaginationClassKey, 'onChange'> {
/**
* Number of always visible pages at the beginning and end.
*/
boundaryCount?: number;
/**
* The active color.
*/
color?: 'default' | 'primary' | 'secondary';
/**
* The total number of pages.
*/
count?: number;
/**
* The page selected by default when the component is uncontrolled.
*/
defaultPage?: number;
/**
* If `true`, all the pagination components will be disabled.
pvdstel marked this conversation as resolved.
Show resolved Hide resolved
*/
disabled?: boolean;
/**
* Accepts a function which returns a string value that provides a user-friendly name for the current page.
*
* For localization purposes, you can use the provided [translations](/guides/localization/).
*
* @param {string} [type = page] The link or button type to format ('page' | 'first' | 'last' | 'next' | 'previous').
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove the types in the jsdoc? They duplicate the TS types and conflict in this case. It's also not clear when type can be undefined while also having a default value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I thought that syntax somehow implied an optional argument. Will fix it in a sec.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't remove the types from the jsdoc here. These docs are copied to the JS component by yarn proptypes --disable-cache, and then the yarn docs:api command will fail because there is no type annotation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into adding support for this upstream, the parsing of basic types is complete but I stopped after a limited search for a JSDoc -> AST -> JSDoc lib failed.

* @param {number} page The page number to format.
* @param {bool} selected If true, the current page is selected.
* @returns {string}
*/
getItemAriaLabel?: (
type: UsePaginationItem['type'] | undefined,
page: number,
selected: boolean,
) => string;
/**
* If `true`, hide the next-page button.
*/
hideNextButton?: boolean;
/**
* If `true`, hide the previous-page button.
*/
hidePrevButton?: boolean;
/**
* Callback fired when the page is changed.
*
* @param {object} event The event source of the callback.
* @param {number} page The page selected.
*/
onChange?: (event: React.ChangeEvent<{}>, page: number) => void;
pvdstel marked this conversation as resolved.
Show resolved Hide resolved
/**
* The current page.
*/
page?: number;
/**
* Renders the item.
pvdstel marked this conversation as resolved.
Show resolved Hide resolved
*
* @param {object} params The props to spread on a PaginationItem.
pvdstel marked this conversation as resolved.
Show resolved Hide resolved
* @returns {ReactNode}
*/
renderItem?: (params: object) => React.ReactNode;
/**
* The shape of the pagination items.
*/
shape?: 'round' | 'rounded';
/**
* If `true`, show the first-page button.
*/
showFirstButton?: boolean;
/**
* If `true`, show the last-page button.
*/
showLastButton?: boolean;
/**
* Number of always visible pages before and after the current page.
*/
siblingCount?: number;
/**
* The size of the pagination component.
*/
size?: 'small' | 'medium' | 'large';
/**
* The variant to use.
*/
variant?: 'text' | 'outlined';
}

export type PaginationClassKey = 'root' | 'ul';

export default function Pagination(props: PaginationProps): JSX.Element;
20 changes: 14 additions & 6 deletions packages/material-ui-lab/src/Pagination/Pagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ const Pagination = React.forwardRef(function Pagination(props, ref) {
getItemAriaLabel: getAriaLabel = defaultGetAriaLabel,
hideNextButton = false,
hidePrevButton = false,
onChange,
page,
renderItem = item => <PaginationItem {...item} />,
shape = 'round',
showFirstButton = false,
Expand Down Expand Up @@ -68,6 +70,8 @@ const Pagination = React.forwardRef(function Pagination(props, ref) {
...item,
color,
'aria-label': getAriaLabel(item.type, item.page, item.selected),
page,
onChange,
shape,
size,
variant,
Expand All @@ -80,19 +84,23 @@ const Pagination = React.forwardRef(function Pagination(props, ref) {
});

Pagination.propTypes = {
// ----------------------------- Warning --------------------------------
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the d.ts file and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* Number of always visible pages at the beginning and end.
*/
boundaryCount: PropTypes.number,
/**
* Pagination items.
* The content of the component.
*/
children: PropTypes.node,
mbrookes marked this conversation as resolved.
Show resolved Hide resolved
/**
* Override or extend the styles applied to the component.
* See [CSS API](#css) below for more details.
*/
classes: PropTypes.object.isRequired,
classes: PropTypes.object,
/**
* @ignore
*/
Expand All @@ -110,7 +118,7 @@ Pagination.propTypes = {
*/
defaultPage: PropTypes.number,
/**
* If `true`, all the pagination component will be disabled.
* If `true`, all the pagination components will be disabled.
*/
disabled: PropTypes.bool,
/**
Expand Down Expand Up @@ -144,7 +152,7 @@ Pagination.propTypes = {
*/
page: PropTypes.number,
/**
* Render the item.
* Renders the item.
*
* @param {object} params The props to spread on a PaginationItem.
* @returns {ReactNode}
Expand All @@ -169,11 +177,11 @@ Pagination.propTypes = {
/**
* The size of the pagination component.
*/
size: PropTypes.oneOf(['small', 'medium', 'large']),
size: PropTypes.oneOf(['large', 'medium', 'small']),
/**
* The variant to use.
*/
variant: PropTypes.oneOf(['text', 'outlined']),
variant: PropTypes.oneOf(['outlined', 'text']),
};

export default withStyles(styles, { name: 'MuiPagination' })(Pagination);
28 changes: 26 additions & 2 deletions packages/material-ui-lab/src/Pagination/usePagination.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,26 @@
declare const usePagination: any;
export default usePagination;
import * as React from 'react';

export interface UsePaginationProps {
merceyz marked this conversation as resolved.
Show resolved Hide resolved
boundaryCount?: number;
componentName?: string;
count?: number;
defaultPage?: number;
disabled?: boolean;
hideNextButton?: boolean;
hidePrevButton?: boolean;
onChange?: (event: React.ChangeEvent<{}>, page: number) => void;
page?: number;
showFirstButton?: boolean;
showLastButton?: boolean;
siblingCount?: number;
}

export interface UsePaginationItem {
onClick: React.ReactEventHandler;
type: 'page' | 'first' | 'last' | 'next' | 'previous' | 'start-ellipsis' | 'end-ellipsis';
page: number;
selected: boolean;
disabled: boolean;
}

export default function usePagination(props: UsePaginationProps): UsePaginationItem[];
68 changes: 67 additions & 1 deletion packages/material-ui-lab/src/PaginationItem/PaginationItem.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,68 @@
declare const PaginationItem: any;
import * as React from 'react';
import { OverridableComponent, OverrideProps } from '@material-ui/core/OverridableComponent';
import { UsePaginationItem } from '../Pagination/usePagination';

export interface PaginationItemTypeMap<P = {}, D extends React.ElementType = 'div'> {
props: P & {
/**
* The active color.
*/
color?: 'standard' | 'primary' | 'secondary';
/**
* If `true`, the item will be disabled.
*/
disabled?: boolean;
/**
* The current page number.
*/
page?: number;
/**
* If `true` the pagination item is selected.
*/
selected?: boolean;
/**
* The shape of the pagination item.
*/
shape?: 'round' | 'rounded';
/**
* The size of the pagination item.
*/
size?: 'small' | 'medium' | 'large';
/**
* The type of pagination item.
*/
type?: UsePaginationItem['type'];
/**
* The pagination item variant.
*/
variant?: 'text' | 'outlined';
};
defaultComponent: D;
classKey: PaginationItemClassKey;
}

declare const PaginationItem: OverridableComponent<PaginationItemTypeMap>;

export type PaginationItemClassKey =
| 'root'
| 'page'
| 'sizeSmall'
| 'sizeLarge'
| 'textPrimary'
| 'textSecondary'
| 'outlined'
| 'outlinedPrimary'
| 'outlinedSecondary'
| 'rounded'
| 'ellipsis'
| 'focusVisible'
| 'disabled'
| 'selected'
| 'icon';

export type PaginationItemProps<
D extends React.ElementType = PaginationItemTypeMap['defaultComponent'],
P = {}
> = OverrideProps<PaginationItemTypeMap<P, D>, D>;

export default PaginationItem;