@westpac/ui 0.43.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/component-type.json +1 -1
  3. package/dist/components/accordion/components/accordion-item/accordion-item.component.js +3 -1
  4. package/dist/components/accordion/components/accordion-item/accordion-item.styles.d.ts +3 -0
  5. package/dist/components/accordion/components/accordion-item/accordion-item.styles.js +2 -1
  6. package/dist/components/pagination/components/pagination-item/pagination-item.component.js +5 -1
  7. package/dist/components/pagination/components/pagination-item/pagination-item.styles.d.ts +2 -2
  8. package/dist/components/pagination/components/pagination-item/pagination-item.styles.js +1 -1
  9. package/dist/components/pagination/components/pagination-pages/pagination-pages.component.d.ts +2 -0
  10. package/dist/components/pagination/components/pagination-pages/pagination-pages.component.js +185 -0
  11. package/dist/components/pagination/components/pagination-pages/pagination-pages.types.d.ts +36 -0
  12. package/dist/components/pagination/components/pagination-pages/pagination-pages.types.js +1 -0
  13. package/dist/components/pagination/components/pagination-presentational/pagination-presentational.component.d.ts +2 -0
  14. package/dist/components/pagination/components/pagination-presentational/pagination-presentational.component.js +44 -0
  15. package/dist/components/pagination/{pagination.styles.d.ts → components/pagination-presentational/pagination-presentational.styles.d.ts} +3 -0
  16. package/dist/components/pagination/{pagination.styles.js → components/pagination-presentational/pagination-presentational.styles.js} +2 -1
  17. package/dist/components/pagination/components/pagination-presentational/pagination-presentational.types.d.ts +41 -0
  18. package/dist/components/pagination/components/pagination-presentational/pagination-presentational.types.js +1 -0
  19. package/dist/components/pagination/components/pagination-total-pages/pagination-total-pages.component.d.ts +2 -0
  20. package/dist/components/pagination/components/pagination-total-pages/pagination-total-pages.component.js +188 -0
  21. package/dist/components/pagination/components/pagination-total-pages/pagination-total-pages.types.d.ts +40 -0
  22. package/dist/components/pagination/components/pagination-total-pages/pagination-total-pages.types.js +1 -0
  23. package/dist/components/pagination/pagination.component.d.ts +1 -1
  24. package/dist/components/pagination/pagination.component.js +26 -121
  25. package/dist/components/pagination/pagination.types.d.ts +33 -29
  26. package/dist/components/pagination/pagination.utils.d.ts +2 -0
  27. package/dist/components/pagination/pagination.utils.js +12 -0
  28. package/dist/components/progress-indicator/progress-indicator.component.js +1 -1
  29. package/dist/css/westpac-ui.css +3 -0
  30. package/dist/css/westpac-ui.min.css +3 -0
  31. package/dist/hook/breakpoints.hook.d.ts +1 -0
  32. package/dist/hook/breakpoints.hook.js +21 -0
  33. package/package.json +3 -3
  34. package/src/components/accordion/components/accordion-item/accordion-item.component.tsx +1 -1
  35. package/src/components/accordion/components/accordion-item/accordion-item.styles.ts +2 -1
  36. package/src/components/pagination/components/pagination-item/pagination-item.component.tsx +2 -0
  37. package/src/components/pagination/components/pagination-item/pagination-item.styles.ts +1 -1
  38. package/src/components/pagination/components/pagination-pages/pagination-pages.component.tsx +212 -0
  39. package/src/components/pagination/components/pagination-pages/pagination-pages.types.ts +47 -0
  40. package/src/components/pagination/components/pagination-presentational/pagination-presentational.component.tsx +81 -0
  41. package/src/components/pagination/{pagination.styles.ts → components/pagination-presentational/pagination-presentational.styles.ts} +2 -0
  42. package/src/components/pagination/components/pagination-presentational/pagination-presentational.types.ts +48 -0
  43. package/src/components/pagination/components/pagination-total-pages/pagination-total-pages.component.tsx +234 -0
  44. package/src/components/pagination/components/pagination-total-pages/pagination-total-pages.types.ts +48 -0
  45. package/src/components/pagination/pagination.component.tsx +34 -142
  46. package/src/components/pagination/pagination.types.ts +34 -31
  47. package/src/components/pagination/pagination.utils.ts +11 -0
  48. package/src/components/progress-indicator/progress-indicator.component.tsx +1 -1
  49. package/src/hook/breakpoints.hook.ts +29 -0
@@ -30,7 +30,9 @@ export function AccordionItem({ className, tag: Tag = 'div', look = 'soft', ...p
30
30
  ...mergeProps(buttonProps, hoverProps, focusProps),
31
31
  ref: ref,
32
32
  className: styles.itemHeader()
33
- }, React.createElement("span", null, item.props.title), direction === 'ltr' ? React.createElement(ArrowRightIcon, {
33
+ }, React.createElement("span", {
34
+ className: styles.headerTitleWrapper()
35
+ }, item.props.title), direction === 'ltr' ? React.createElement(ArrowRightIcon, {
34
36
  "aria-hidden": "true",
35
37
  className: styles.indicator()
36
38
  }) : React.createElement(ArrowLeftIcon, {
@@ -31,6 +31,7 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
31
31
  }, {
32
32
  base: string;
33
33
  itemHeader: string;
34
+ headerTitleWrapper: string;
34
35
  indicator: string;
35
36
  content: string;
36
37
  }, undefined, {
@@ -68,6 +69,7 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
68
69
  }, {
69
70
  base: string;
70
71
  itemHeader: string;
72
+ headerTitleWrapper: string;
71
73
  indicator: string;
72
74
  content: string;
73
75
  }, import("tailwind-variants").TVReturnType<{
@@ -103,6 +105,7 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
103
105
  }, {
104
106
  base: string;
105
107
  itemHeader: string;
108
+ headerTitleWrapper: string;
106
109
  indicator: string;
107
110
  content: string;
108
111
  }, undefined, {
@@ -2,7 +2,8 @@ import { tv } from 'tailwind-variants';
2
2
  export const styles = tv({
3
3
  slots: {
4
4
  base: 'relative',
5
- itemHeader: 'typography-body-9 flex w-full items-center justify-between px-3 py-2',
5
+ itemHeader: 'typography-body-9 flex w-full flex-1 items-center justify-between px-3 py-2',
6
+ headerTitleWrapper: 'flex-1 pr-2 text-left',
6
7
  indicator: 'size-3 rotate-90',
7
8
  content: 'hidden'
8
9
  },
@@ -11,6 +11,10 @@ export function PaginationItem({ className, firstItem = false, lastItem = false,
11
11
  }),
12
12
  ...props,
13
13
  disabled: disabled,
14
- "aria-current": active ? 'page' : undefined
14
+ "aria-disabled": disabled ? 'true' : 'false',
15
+ "aria-current": active ? 'page' : undefined,
16
+ ...Tag === 'button' && {
17
+ type: 'button'
18
+ }
15
19
  }, children);
16
20
  }
@@ -15,7 +15,7 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
15
15
  true: string;
16
16
  false: string;
17
17
  };
18
- }, undefined, "typography-body-10 relative block border border-border px-2 py-1.5 text-center text-text transition-colors", {
18
+ }, undefined, "typography-body-10 relative block min-w-7 border border-border px-2 py-1.5 text-center text-text", {
19
19
  responsiveVariants: string[];
20
20
  }, {
21
21
  firstItem: {
@@ -51,6 +51,6 @@ export declare const styles: import("tailwind-variants").TVReturnType<{
51
51
  true: string;
52
52
  false: string;
53
53
  };
54
- }, undefined, "typography-body-10 relative block border border-border px-2 py-1.5 text-center text-text transition-colors", {
54
+ }, undefined, "typography-body-10 relative block min-w-7 border border-border px-2 py-1.5 text-center text-text", {
55
55
  responsiveVariants: string[];
56
56
  }, unknown, unknown, undefined>>;
@@ -1,6 +1,6 @@
1
1
  import { tv } from 'tailwind-variants';
2
2
  export const styles = tv({
3
- base: 'typography-body-10 relative block border border-border px-2 py-1.5 text-center text-text transition-colors',
3
+ base: 'typography-body-10 relative block min-w-7 border border-border px-2 py-1.5 text-center text-text',
4
4
  variants: {
5
5
  firstItem: {
6
6
  true: 'rounded-l',
@@ -0,0 +1,2 @@
1
+ import { type PaginationPageProps } from './pagination-pages.types.js';
2
+ export declare function PaginationPage({ className, pages, tag, role, current, linkComponent, infinite, onChange, backLabel, nextLabel, nextAriaLabel, backAriaLabel, siblingCount, boundaryCount, ...props }: PaginationPageProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,185 @@
1
+ 'use client';
2
+ import React, { useCallback, useMemo } from 'react';
3
+ import { useBreakpoint } from '../../../../hook/breakpoints.hook.js';
4
+ import { getSiblingOrBoundaryCount } from '../../pagination.utils.js';
5
+ import { PaginationPresentational } from '../pagination-presentational/pagination-presentational.component.js';
6
+ export function PaginationPage({ className, pages, tag = 'nav', role = 'navigation', current = 1, linkComponent, infinite = false, onChange, backLabel = 'Back', nextLabel = 'Next', nextAriaLabel = 'Next', backAriaLabel = 'Back', siblingCount = 2, boundaryCount = 1, ...props }) {
7
+ const breakpoint = useBreakpoint();
8
+ const finalSiblingCount = useMemo(()=>{
9
+ if (typeof siblingCount === 'number') {
10
+ return siblingCount;
11
+ }
12
+ return getSiblingOrBoundaryCount(siblingCount, breakpoint);
13
+ }, [
14
+ breakpoint,
15
+ siblingCount
16
+ ]);
17
+ const finalBoundaryCount = useMemo(()=>{
18
+ if (typeof boundaryCount === 'number') {
19
+ return boundaryCount;
20
+ }
21
+ return getSiblingOrBoundaryCount(boundaryCount, breakpoint);
22
+ }, [
23
+ boundaryCount,
24
+ breakpoint
25
+ ]);
26
+ const generateHandleOnClickBackwards = useCallback((current, infinite, forwardOnly, onChange, pages)=>()=>{
27
+ if (infinite && forwardOnly) {
28
+ return onChange(pages.length);
29
+ }
30
+ if (!forwardOnly) {
31
+ return onChange(current - 1);
32
+ }
33
+ }, []);
34
+ const paginationBackProps = useMemo(()=>{
35
+ var _pages_;
36
+ const fowardOnly = (current || 1) <= 1;
37
+ const defaultBackProps = {
38
+ disabled: !infinite && fowardOnly,
39
+ firstItem: true,
40
+ 'aria-label': backAriaLabel
41
+ };
42
+ if (defaultBackProps.disabled) {
43
+ return {
44
+ ...defaultBackProps,
45
+ tag: 'button'
46
+ };
47
+ }
48
+ if (onChange) {
49
+ return {
50
+ ...defaultBackProps,
51
+ tag: linkComponent || 'button',
52
+ ...current && {
53
+ onClick: generateHandleOnClickBackwards(current, infinite, fowardOnly, onChange, pages)
54
+ }
55
+ };
56
+ }
57
+ return {
58
+ ...defaultBackProps,
59
+ tag: linkComponent || 'a',
60
+ href: fowardOnly ? pages[pages.length - 1].href : (_pages_ = pages[(current || 0) - 2]) === null || _pages_ === void 0 ? void 0 : _pages_.href
61
+ };
62
+ }, [
63
+ current,
64
+ infinite,
65
+ backAriaLabel,
66
+ onChange,
67
+ linkComponent,
68
+ pages,
69
+ generateHandleOnClickBackwards
70
+ ]);
71
+ const generateHandleOnClickForward = useCallback((current, infinite, backwardsOnly, onChange)=>()=>{
72
+ if (infinite && backwardsOnly) {
73
+ return onChange(1);
74
+ }
75
+ if (backwardsOnly) {
76
+ return;
77
+ }
78
+ return onChange(current + 1);
79
+ }, []);
80
+ const paginationNextProps = useMemo(()=>{
81
+ var _pages_;
82
+ const backwardsOnly = (current || 1) >= pages.length;
83
+ const defaultNextProps = {
84
+ disabled: !infinite && backwardsOnly,
85
+ tag: linkComponent,
86
+ lastItem: true,
87
+ 'aria-label': nextAriaLabel
88
+ };
89
+ if (defaultNextProps.disabled) {
90
+ return {
91
+ ...defaultNextProps,
92
+ tag: 'button'
93
+ };
94
+ }
95
+ if (onChange) {
96
+ return {
97
+ ...defaultNextProps,
98
+ tag: linkComponent || 'button',
99
+ ...current && {
100
+ onClick: generateHandleOnClickForward(current, infinite, backwardsOnly, onChange)
101
+ }
102
+ };
103
+ }
104
+ return {
105
+ ...defaultNextProps,
106
+ tag: linkComponent || 'a',
107
+ href: backwardsOnly ? pages[0].href : (_pages_ = pages[current || 0]) === null || _pages_ === void 0 ? void 0 : _pages_.href
108
+ };
109
+ }, [
110
+ current,
111
+ pages,
112
+ infinite,
113
+ linkComponent,
114
+ nextAriaLabel,
115
+ onChange,
116
+ generateHandleOnClickForward
117
+ ]);
118
+ const numberedPages = useMemo(()=>pages.map((page, index)=>({
119
+ ...page,
120
+ page: index + 1
121
+ })), [
122
+ pages
123
+ ]);
124
+ const pagesToRender = useMemo(()=>{
125
+ const minEdgePagesVisible = Math.min(finalSiblingCount * 2 + finalBoundaryCount + 2, pages.length);
126
+ let leftCorner = numberedPages.slice(0, finalBoundaryCount);
127
+ let rightCorner = finalBoundaryCount > 0 ? numberedPages.slice(-finalBoundaryCount).filter((page)=>!leftCorner.some((leftItem)=>leftItem.page === page.page)) : [];
128
+ let middle = [];
129
+ if (current) {
130
+ var _middle_, _leftCorner_at, _rightCorner_;
131
+ const nearStart = current < minEdgePagesVisible - finalSiblingCount;
132
+ const nearEnd = current > numberedPages.length - minEdgePagesVisible + finalSiblingCount;
133
+ if (nearStart) {
134
+ leftCorner = numberedPages.slice(0, minEdgePagesVisible);
135
+ }
136
+ if (nearEnd) {
137
+ rightCorner = numberedPages.slice(-minEdgePagesVisible);
138
+ }
139
+ rightCorner = rightCorner.filter((page)=>!leftCorner.some((leftItem)=>leftItem.page === page.page));
140
+ const currentIndex = current - 1;
141
+ const leftEdge = currentIndex - finalSiblingCount;
142
+ middle = numberedPages.slice(Math.max(0, leftEdge), leftEdge + (finalSiblingCount * 2 + 1)).filter((middleItem)=>{
143
+ return !(leftCorner.some((left)=>left.page === middleItem.page) || rightCorner.some((right)=>right.page === middleItem.page));
144
+ });
145
+ const lastItemMiddle = middle.at(-1);
146
+ const hasLeftDots = ((_middle_ = middle[0]) === null || _middle_ === void 0 ? void 0 : _middle_.page) && middle[0].page - 1 !== ((_leftCorner_at = leftCorner.at(-1)) === null || _leftCorner_at === void 0 ? void 0 : _leftCorner_at.page);
147
+ const hasRightDots = (lastItemMiddle === null || lastItemMiddle === void 0 ? void 0 : lastItemMiddle.page) && lastItemMiddle.page + 1 !== ((_rightCorner_ = rightCorner[0]) === null || _rightCorner_ === void 0 ? void 0 : _rightCorner_.page);
148
+ if (middle.length === 0 && leftCorner.length + rightCorner.length !== numberedPages.length) {
149
+ middle = [
150
+ null
151
+ ];
152
+ } else {
153
+ if (hasLeftDots) middle.unshift(null);
154
+ if (hasRightDots) middle.push(null);
155
+ }
156
+ }
157
+ return [
158
+ ...leftCorner,
159
+ ...middle,
160
+ ...rightCorner
161
+ ];
162
+ }, [
163
+ finalBoundaryCount,
164
+ current,
165
+ numberedPages,
166
+ finalSiblingCount,
167
+ pages.length
168
+ ]);
169
+ if (!pages.length) {
170
+ return React.createElement(React.Fragment, null);
171
+ }
172
+ return React.createElement(PaginationPresentational, {
173
+ className: className,
174
+ current: current,
175
+ paginationBackProps: paginationBackProps,
176
+ paginationNextProps: paginationNextProps,
177
+ pagesToRender: pagesToRender,
178
+ tag: tag,
179
+ role: role,
180
+ backLabel: backLabel,
181
+ nextLabel: nextLabel,
182
+ onChange: onChange,
183
+ ...props
184
+ });
185
+ }
@@ -0,0 +1,36 @@
1
+ import { HTMLAttributes, ReactNode } from 'react';
2
+ import { PaginationBase } from '../../pagination.types.js';
3
+ export type PageProps = {
4
+ 'aria-label'?: string;
5
+ href: string;
6
+ text: ReactNode;
7
+ };
8
+ export type PaginationAsLinkProps = {
9
+ /**
10
+ * on page change
11
+ */
12
+ onChange?: never;
13
+ /**
14
+ * Pages items
15
+ */
16
+ pages: PageProps[];
17
+ };
18
+ export type PaginationAsButtonProps = {
19
+ /**
20
+ * on page change
21
+ */
22
+ onChange: (page: number) => unknown;
23
+ /**
24
+ * Pages items
25
+ */
26
+ pages: Omit<PageProps, 'href'>[];
27
+ };
28
+ export type PaginationPageProps = PaginationBase & (PaginationAsLinkProps | PaginationAsButtonProps) & Omit<HTMLAttributes<Element>, 'onChange'>;
29
+ export type PageToRender = {
30
+ href: string;
31
+ page: number;
32
+ text: React.ReactNode;
33
+ } | {
34
+ page: number;
35
+ text: React.ReactNode;
36
+ } | null;
@@ -0,0 +1,2 @@
1
+ import { type PaginationPresentationalProps } from './pagination-presentational.types.js';
2
+ export declare function PaginationPresentational({ className, tag: Tag, role, paginationBackProps, backLabel, pagesToRender, current, linkComponent, onChange, paginationNextProps, nextLabel, ...props }: PaginationPresentationalProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import React from 'react';
3
+ import { PaginationItem } from '../../components/index.js';
4
+ import { styles as paginationStyles } from './pagination-presentational.styles.js';
5
+ export function PaginationPresentational({ className, tag: Tag = 'nav', role = 'navigation', paginationBackProps, backLabel, pagesToRender, current, linkComponent, onChange, paginationNextProps, nextLabel, ...props }) {
6
+ const styles = paginationStyles({});
7
+ return React.createElement(Tag, {
8
+ className: styles.base({
9
+ className
10
+ }),
11
+ role: role,
12
+ "aria-label": "Page number",
13
+ ...props
14
+ }, React.createElement("ul", {
15
+ className: styles.ul({})
16
+ }, React.createElement("li", null, React.createElement(PaginationItem, paginationBackProps, backLabel)), pagesToRender.map((page, index)=>{
17
+ if (page === null) {
18
+ return React.createElement("li", {
19
+ className: styles.emptyItem(),
20
+ key: `index-${index}`
21
+ }, "…");
22
+ }
23
+ const commonProps = {
24
+ active: (current || 0) === page.page,
25
+ 'aria-label': page['aria-label'] || `Go to page ${page.page}`
26
+ };
27
+ return React.createElement("li", {
28
+ key: page.page
29
+ }, 'href' in page ? React.createElement(PaginationItem, {
30
+ ...commonProps,
31
+ tag: linkComponent || 'a',
32
+ href: page.href
33
+ }, page.text) : React.createElement(PaginationItem, {
34
+ ...commonProps,
35
+ tag: linkComponent || 'button',
36
+ onClick: onChange && (()=>{
37
+ onChange(page.page);
38
+ })
39
+ }, page.text));
40
+ }), React.createElement("li", null, React.createElement(PaginationItem, paginationNextProps, nextLabel))), current && React.createElement("span", {
41
+ className: "sr-only",
42
+ role: "status"
43
+ }, "Page ", current));
44
+ }
@@ -1,14 +1,17 @@
1
1
  export declare const styles: import("tailwind-variants").TVReturnType<{}, {
2
2
  base: string;
3
3
  ul: string;
4
+ emptyItem: string;
4
5
  }, undefined, {
5
6
  responsiveVariants: string[];
6
7
  }, {}, {
7
8
  base: string;
8
9
  ul: string;
10
+ emptyItem: string;
9
11
  }, import("tailwind-variants").TVReturnType<{}, {
10
12
  base: string;
11
13
  ul: string;
14
+ emptyItem: string;
12
15
  }, undefined, {
13
16
  responsiveVariants: string[];
14
17
  }, unknown, unknown, undefined>>;
@@ -2,7 +2,8 @@ import { tv } from 'tailwind-variants';
2
2
  export const styles = tv({
3
3
  slots: {
4
4
  base: 'flex flex-col items-center',
5
- ul: 'flex overflow-hidden'
5
+ ul: 'flex overflow-hidden',
6
+ emptyItem: 'typography-body-10 relative block min-w-7 cursor-default border-y border-border px-2 py-1.5 text-center text-text'
6
7
  },
7
8
  variants: {}
8
9
  }, {
@@ -0,0 +1,41 @@
1
+ import { HTMLAttributes } from 'react';
2
+ import { type PaginationItemProps } from '../../components/index.js';
3
+ import { PaginationBase } from '../../pagination.types.js';
4
+ export type PageToRender = {
5
+ 'aria-label'?: string;
6
+ href: string;
7
+ page: number;
8
+ text: React.ReactNode;
9
+ } | {
10
+ 'aria-label'?: string;
11
+ page: number;
12
+ text: React.ReactNode;
13
+ } | null;
14
+ export type PaginationPresentationalProps = PaginationBase & {
15
+ /**
16
+ * on page change
17
+ */
18
+ onChange?: (page: number) => unknown;
19
+ /**
20
+ * Pages to render where the null value is rendered as [...]
21
+ */
22
+ pagesToRender: PageToRender[];
23
+ /**
24
+ * Props to back button
25
+ */
26
+ paginationBackProps?: PaginationItemProps;
27
+ /**
28
+ * Props to back button
29
+ */
30
+ paginationNextProps?: PaginationItemProps;
31
+ /**
32
+ * siblingCount
33
+ * @default 1
34
+ */
35
+ siblingCount?: number;
36
+ /**
37
+ * Tag to render
38
+ * @default nav
39
+ */
40
+ tag?: keyof JSX.IntrinsicElements;
41
+ } & Omit<HTMLAttributes<Element>, 'onChange'>;
@@ -0,0 +1,2 @@
1
+ import { type PaginationTotalPagesProps } from './pagination-total-pages.types.js';
2
+ export declare function PaginationTotalPages({ className, totalPages, tag, role, current, linkComponent, infinite, onChange, backLabel, backAriaLabel, nextLabel, nextAriaLabel, siblingCount, boundaryCount, onPageItemProps, ...props }: PaginationTotalPagesProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,188 @@
1
+ 'use client';
2
+ import React, { useCallback, useMemo } from 'react';
3
+ import { useBreakpoint } from '../../../../hook/breakpoints.hook.js';
4
+ import { getSiblingOrBoundaryCount } from '../../pagination.utils.js';
5
+ import { PaginationPresentational } from '../pagination-presentational/pagination-presentational.component.js';
6
+ function generateArray(from, to) {
7
+ return Array.from({
8
+ length: to - from + 1
9
+ }, (_, i)=>i + from);
10
+ }
11
+ export function PaginationTotalPages({ className, totalPages, tag = 'nav', role = 'navigation', current = 1, linkComponent, infinite = false, onChange, backLabel = 'Back', backAriaLabel = 'Back', nextLabel = 'Next', nextAriaLabel = 'Next', siblingCount = 2, boundaryCount = 1, onPageItemProps, ...props }) {
12
+ const breakpoint = useBreakpoint();
13
+ const finalSiblingCount = useMemo(()=>{
14
+ if (typeof siblingCount === 'number') {
15
+ return siblingCount;
16
+ }
17
+ return getSiblingOrBoundaryCount(siblingCount, breakpoint);
18
+ }, [
19
+ breakpoint,
20
+ siblingCount
21
+ ]);
22
+ const finalBoundaryCount = useMemo(()=>{
23
+ if (typeof boundaryCount === 'number') {
24
+ return boundaryCount;
25
+ }
26
+ return getSiblingOrBoundaryCount(boundaryCount, breakpoint);
27
+ }, [
28
+ boundaryCount,
29
+ breakpoint
30
+ ]);
31
+ const generateHandleOnClickBackwards = useCallback((current, infinite, forwardOnly, onChange, totalPages)=>()=>{
32
+ if (infinite && forwardOnly) {
33
+ return onChange(totalPages);
34
+ }
35
+ if (!forwardOnly) {
36
+ return onChange(current - 1);
37
+ }
38
+ }, []);
39
+ const paginationBackProps = useMemo(()=>{
40
+ var _onPageItemProps;
41
+ const fowardOnly = (current || 1) <= 1;
42
+ const defaultBackProps = {
43
+ disabled: !infinite && fowardOnly,
44
+ firstItem: true,
45
+ 'aria-label': backAriaLabel
46
+ };
47
+ if (defaultBackProps.disabled) {
48
+ return {
49
+ ...defaultBackProps,
50
+ tag: 'button'
51
+ };
52
+ }
53
+ if (onChange) {
54
+ return {
55
+ ...defaultBackProps,
56
+ tag: linkComponent || 'button',
57
+ ...current && {
58
+ onClick: generateHandleOnClickBackwards(current, infinite, fowardOnly, onChange, totalPages)
59
+ }
60
+ };
61
+ }
62
+ return {
63
+ ...defaultBackProps,
64
+ tag: linkComponent || 'a',
65
+ href: fowardOnly ? onPageItemProps(totalPages).href : (_onPageItemProps = onPageItemProps(current - 1)) === null || _onPageItemProps === void 0 ? void 0 : _onPageItemProps.href
66
+ };
67
+ }, [
68
+ current,
69
+ infinite,
70
+ backAriaLabel,
71
+ onChange,
72
+ linkComponent,
73
+ onPageItemProps,
74
+ totalPages,
75
+ generateHandleOnClickBackwards
76
+ ]);
77
+ const generateHandleOnClickForward = useCallback((current, infinite, backwardsOnly, onChange)=>()=>{
78
+ if (infinite && backwardsOnly) {
79
+ return onChange(1);
80
+ }
81
+ if (backwardsOnly) {
82
+ return;
83
+ }
84
+ return onChange(current + 1);
85
+ }, []);
86
+ const paginationNextProps = useMemo(()=>{
87
+ var _onPageItemProps, _onPageItemProps1;
88
+ const backwardsOnly = (current || 1) >= totalPages;
89
+ const defaultNextProps = {
90
+ disabled: !infinite && backwardsOnly,
91
+ tag: linkComponent,
92
+ lastItem: true,
93
+ 'aria-label': nextAriaLabel
94
+ };
95
+ if (defaultNextProps.disabled) {
96
+ return {
97
+ ...defaultNextProps,
98
+ tag: 'button'
99
+ };
100
+ }
101
+ if (onChange) {
102
+ return {
103
+ ...defaultNextProps,
104
+ tag: linkComponent || 'button',
105
+ ...current && {
106
+ onClick: generateHandleOnClickForward(current, infinite, backwardsOnly, onChange)
107
+ }
108
+ };
109
+ }
110
+ return {
111
+ ...defaultNextProps,
112
+ tag: linkComponent || 'a',
113
+ href: backwardsOnly ? (_onPageItemProps = onPageItemProps(1)) === null || _onPageItemProps === void 0 ? void 0 : _onPageItemProps.href : (_onPageItemProps1 = onPageItemProps(current || 0)) === null || _onPageItemProps1 === void 0 ? void 0 : _onPageItemProps1.href
114
+ };
115
+ }, [
116
+ current,
117
+ totalPages,
118
+ infinite,
119
+ linkComponent,
120
+ nextAriaLabel,
121
+ onChange,
122
+ onPageItemProps,
123
+ generateHandleOnClickForward
124
+ ]);
125
+ const pagesToRender = useMemo(()=>{
126
+ const minEdgePagesVisible = Math.min(finalSiblingCount * 2 + finalBoundaryCount + 2, totalPages);
127
+ let leftCorner = generateArray(1, Math.min(finalBoundaryCount, totalPages));
128
+ let rightCorner = finalBoundaryCount > 0 ? generateArray(totalPages + 1 - finalBoundaryCount, totalPages).filter((page)=>!leftCorner.some((leftItem)=>leftItem === page)) : [];
129
+ let middle = [];
130
+ if (current) {
131
+ const nearStart = current < minEdgePagesVisible - finalSiblingCount;
132
+ const nearEnd = current > totalPages - minEdgePagesVisible + finalSiblingCount;
133
+ if (nearStart) {
134
+ leftCorner = generateArray(1, minEdgePagesVisible);
135
+ }
136
+ if (nearEnd) {
137
+ rightCorner = generateArray(totalPages - minEdgePagesVisible + 1, totalPages);
138
+ }
139
+ rightCorner = rightCorner.filter((page)=>!leftCorner.some((leftItem)=>leftItem === page));
140
+ const leftEdge = current - finalSiblingCount;
141
+ middle = generateArray(Math.max(1, leftEdge), Math.min(leftEdge + finalSiblingCount * 2, totalPages)).filter((middleItem)=>{
142
+ return !(leftCorner.some((left)=>left === middleItem) || rightCorner.some((right)=>right === middleItem));
143
+ });
144
+ const lastItemMiddle = middle.at(-1);
145
+ const hasLeftDots = middle[0] && middle[0] - 1 !== leftCorner.at(-1);
146
+ const hasRightDots = lastItemMiddle && lastItemMiddle + 1 !== rightCorner[0];
147
+ if (middle.length === 0 && leftCorner.length + rightCorner.length !== totalPages) {
148
+ middle = [
149
+ null
150
+ ];
151
+ } else {
152
+ if (hasLeftDots) middle.unshift(null);
153
+ if (hasRightDots) middle.push(null);
154
+ }
155
+ }
156
+ return [
157
+ ...leftCorner,
158
+ ...middle,
159
+ ...rightCorner
160
+ ].map((page)=>page ? {
161
+ page,
162
+ text: page,
163
+ ...onPageItemProps === null || onPageItemProps === void 0 ? void 0 : onPageItemProps(page)
164
+ } : null);
165
+ }, [
166
+ finalBoundaryCount,
167
+ current,
168
+ onPageItemProps,
169
+ finalSiblingCount,
170
+ totalPages
171
+ ]);
172
+ if (totalPages <= 0) {
173
+ return React.createElement(React.Fragment, null);
174
+ }
175
+ return React.createElement(PaginationPresentational, {
176
+ className: className,
177
+ current: current,
178
+ paginationBackProps: paginationBackProps,
179
+ paginationNextProps: paginationNextProps,
180
+ pagesToRender: pagesToRender,
181
+ tag: tag,
182
+ role: role,
183
+ backLabel: backLabel,
184
+ nextLabel: nextLabel,
185
+ onChange: onChange,
186
+ ...props
187
+ });
188
+ }
@@ -0,0 +1,40 @@
1
+ import { HTMLAttributes, ReactNode } from 'react';
2
+ import { PaginationBase } from '../../pagination.types.js';
3
+ export type PageProps = {
4
+ href: string;
5
+ text: ReactNode;
6
+ };
7
+ export type PaginationAsLinkProps = {
8
+ /**
9
+ * on page change
10
+ */
11
+ onChange?: never;
12
+ /**
13
+ * Pages items
14
+ */
15
+ onPageItemProps: (page: number) => Omit<PageToRenderHref, 'page'>;
16
+ };
17
+ export type PaginationAsButtonProps = {
18
+ /**
19
+ * on page change
20
+ */
21
+ onChange: (page: number) => unknown;
22
+ /**
23
+ * Pages items
24
+ */
25
+ onPageItemProps?: (page: number) => Omit<PageToRenderBase, 'page'>;
26
+ };
27
+ export type PaginationTotalPagesProps = {
28
+ /**
29
+ * total of pages
30
+ */
31
+ totalPages: number;
32
+ } & PaginationBase & (PaginationAsLinkProps | PaginationAsButtonProps) & Omit<HTMLAttributes<Element>, 'onChange'>;
33
+ export type PageToRenderBase = {
34
+ 'aria-label'?: string;
35
+ page: number;
36
+ text: React.ReactNode;
37
+ };
38
+ export type PageToRenderHref = PageToRenderBase & {
39
+ href: string;
40
+ };