@charcoal-ui/react 5.5.0-beta.0 → 5.5.0-beta.2
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.
- package/dist/components/Pagination/PaginationContext.d.ts +20 -0
- package/dist/components/Pagination/PaginationContext.d.ts.map +1 -0
- package/dist/components/Pagination/helper.d.ts +2 -1
- package/dist/components/Pagination/helper.d.ts.map +1 -1
- package/dist/components/Pagination/index.d.ts +32 -8
- package/dist/components/Pagination/index.d.ts.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +126 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/layered.css +126 -0
- package/dist/layered.css.map +1 -1
- package/package.json +6 -6
- package/src/components/Modal/index.tsx +1 -1
- package/src/components/Pagination/Pagination.story.tsx +68 -12
- package/src/components/Pagination/PaginationContext.ts +35 -0
- package/src/components/Pagination/helper.test.ts +58 -0
- package/src/components/Pagination/helper.ts +17 -16
- package/src/components/Pagination/index.css +83 -25
- package/src/components/Pagination/index.tsx +159 -131
- package/src/index.ts +4 -0
|
@@ -1,158 +1,186 @@
|
|
|
1
1
|
import './index.css'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { usePagerWindow } from './helper'
|
|
3
|
+
import { usePaginationWindow } from './helper'
|
|
5
4
|
import { useClassNames } from '../../_lib/useClassNames'
|
|
6
5
|
import IconButton from '../IconButton'
|
|
6
|
+
import {
|
|
7
|
+
PaginationContext,
|
|
8
|
+
usePaginationContext,
|
|
9
|
+
type LinkComponentProps,
|
|
10
|
+
type PageRangeDisplayed,
|
|
11
|
+
type Size,
|
|
12
|
+
} from './PaginationContext'
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
interface CommonProps {
|
|
11
|
-
page: number
|
|
12
|
-
pageCount: number
|
|
13
|
-
pageRangeDisplayed?: number
|
|
14
|
+
type NavButtonProps = {
|
|
15
|
+
direction: 'prev' | 'next'
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}: PaginationProps & Omit<React.ComponentPropsWithoutRef<'nav'>, 'onChange'>) {
|
|
28
|
-
const window = usePagerWindow(page, pageCount, pageRangeDisplayed)
|
|
29
|
-
const makeClickHandler = useCallback(
|
|
30
|
-
(value: number) => () => {
|
|
31
|
-
onChange(value)
|
|
32
|
-
},
|
|
33
|
-
[onChange],
|
|
34
|
-
)
|
|
18
|
+
function NavButton({ direction }: NavButtonProps) {
|
|
19
|
+
'use memo'
|
|
20
|
+
const {
|
|
21
|
+
page,
|
|
22
|
+
pageCount,
|
|
23
|
+
size,
|
|
24
|
+
isLinkMode,
|
|
25
|
+
makeUrl,
|
|
26
|
+
LinkComponent,
|
|
27
|
+
makeClickHandler,
|
|
28
|
+
} = usePaginationContext()
|
|
35
29
|
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
30
|
+
const isPrev = direction === 'prev'
|
|
31
|
+
const targetPage = isPrev
|
|
32
|
+
? Math.max(1, page - 1)
|
|
33
|
+
: Math.min(pageCount, page + 1)
|
|
34
|
+
const disabled = isPrev ? page <= 1 : page >= pageCount
|
|
39
35
|
|
|
40
36
|
return (
|
|
41
|
-
<
|
|
37
|
+
<IconButton
|
|
38
|
+
icon={isPrev ? '24/Prev' : '24/Next'}
|
|
39
|
+
size={size}
|
|
40
|
+
hidden={disabled}
|
|
41
|
+
className="charcoal-pagination-nav-button"
|
|
42
|
+
{...(isLinkMode && makeUrl
|
|
43
|
+
? {
|
|
44
|
+
component: LinkComponent as 'a',
|
|
45
|
+
href: makeUrl(targetPage),
|
|
46
|
+
'aria-disabled': disabled,
|
|
47
|
+
}
|
|
48
|
+
: {
|
|
49
|
+
disabled,
|
|
50
|
+
onClick: makeClickHandler(targetPage),
|
|
51
|
+
})}
|
|
52
|
+
/>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function PageItem({ value }: { value: number | string }) {
|
|
57
|
+
'use memo'
|
|
58
|
+
const { page, size, isLinkMode, makeUrl, LinkComponent, makeClickHandler } =
|
|
59
|
+
usePaginationContext()
|
|
60
|
+
// 省略記号
|
|
61
|
+
if (value === '...') {
|
|
62
|
+
return (
|
|
42
63
|
<IconButton
|
|
43
|
-
icon="24/
|
|
44
|
-
size=
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
hidden
|
|
48
|
-
disabled={!hasPrev}
|
|
49
|
-
onClick={makeClickHandler(Math.max(1, page - 1))}
|
|
64
|
+
icon="24/Dot"
|
|
65
|
+
size={size}
|
|
66
|
+
disabled
|
|
67
|
+
className="charcoal-pagination-spacer"
|
|
68
|
+
aria-hidden
|
|
50
69
|
/>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
className="charcoal-pagination-button"
|
|
68
|
-
aria-current
|
|
69
|
-
>
|
|
70
|
-
<Text>{p}</Text>
|
|
71
|
-
</button>
|
|
72
|
-
) : (
|
|
73
|
-
<button
|
|
74
|
-
key={p}
|
|
75
|
-
type="button"
|
|
76
|
-
className="charcoal-pagination-button"
|
|
77
|
-
onClick={makeClickHandler(p)}
|
|
78
|
-
>
|
|
79
|
-
<Text>{p}</Text>
|
|
80
|
-
</button>
|
|
81
|
-
),
|
|
82
|
-
)}
|
|
83
|
-
<IconButton
|
|
84
|
-
icon="24/Next"
|
|
85
|
-
size="M"
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
// 現在ページ(クリック不可)
|
|
73
|
+
if (value === page) {
|
|
74
|
+
return (
|
|
75
|
+
<span className="charcoal-pagination-button" aria-current="page">
|
|
76
|
+
{value}
|
|
77
|
+
</span>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
if (typeof value !== 'number') return null
|
|
81
|
+
// リンクモード: ページへのリンク
|
|
82
|
+
if (isLinkMode && makeUrl) {
|
|
83
|
+
return (
|
|
84
|
+
<LinkComponent
|
|
85
|
+
href={makeUrl(value)}
|
|
86
86
|
className="charcoal-pagination-button"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
>
|
|
88
|
+
{value}
|
|
89
|
+
</LinkComponent>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
// ボタンモード: クリックでページ遷移
|
|
93
|
+
return (
|
|
94
|
+
<button
|
|
95
|
+
type="button"
|
|
96
|
+
className="charcoal-pagination-button"
|
|
97
|
+
onClick={makeClickHandler(value)}
|
|
98
|
+
>
|
|
99
|
+
{value}
|
|
100
|
+
</button>
|
|
93
101
|
)
|
|
94
|
-
}
|
|
102
|
+
}
|
|
95
103
|
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
interface CommonProps {
|
|
105
|
+
page: number
|
|
106
|
+
pageCount: number
|
|
107
|
+
pageRangeDisplayed?: PageRangeDisplayed
|
|
108
|
+
size?: Size
|
|
98
109
|
}
|
|
99
110
|
|
|
100
|
-
|
|
111
|
+
type NavProps = Omit<React.ComponentPropsWithoutRef<'nav'>, 'onChange'>
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Pagination component. Use either `onChange` (button mode) or `makeUrl` (link mode).
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* // Button mode - for client-side state
|
|
118
|
+
* <Pagination page={1} pageCount={10} onChange={setPage} />
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* // Link mode - for server routing / static pages
|
|
122
|
+
* <Pagination page={1} pageCount={10} makeUrl={(p) => `?page=${p}`} />
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* // Link mode with custom component (e.g. Next.js Link)
|
|
126
|
+
* <Pagination page={1} pageCount={10} makeUrl={(p) => `?page=${p}`} component={Link} />
|
|
127
|
+
*/
|
|
128
|
+
export type PaginationProps = CommonProps &
|
|
129
|
+
NavProps &
|
|
130
|
+
(
|
|
131
|
+
| { onChange(newPage: number): void; makeUrl?: never; component?: never }
|
|
132
|
+
| {
|
|
133
|
+
makeUrl(page: number): string
|
|
134
|
+
onChange?: never
|
|
135
|
+
/**
|
|
136
|
+
* The component used for link elements. Receives `href`, `className`, and `children`.
|
|
137
|
+
* @default 'a'
|
|
138
|
+
*/
|
|
139
|
+
component?: React.ElementType<LinkComponentProps>
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
export default function Pagination({
|
|
101
144
|
page,
|
|
102
145
|
pageCount,
|
|
103
146
|
pageRangeDisplayed,
|
|
147
|
+
size = 'M',
|
|
148
|
+
onChange,
|
|
104
149
|
makeUrl,
|
|
150
|
+
component: LinkComponent = 'a',
|
|
105
151
|
className,
|
|
106
|
-
...
|
|
107
|
-
}:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
const
|
|
152
|
+
...navProps
|
|
153
|
+
}: PaginationProps) {
|
|
154
|
+
'use memo'
|
|
155
|
+
const window = usePaginationWindow(page, pageCount, pageRangeDisplayed)
|
|
156
|
+
const isLinkMode = makeUrl !== undefined
|
|
157
|
+
const makeClickHandler = (value: number) => () => onChange?.(value)
|
|
112
158
|
const classNames = useClassNames('charcoal-pagination', className)
|
|
113
159
|
|
|
160
|
+
const contextValue = {
|
|
161
|
+
page,
|
|
162
|
+
pageCount,
|
|
163
|
+
size,
|
|
164
|
+
isLinkMode,
|
|
165
|
+
makeUrl,
|
|
166
|
+
LinkComponent,
|
|
167
|
+
makeClickHandler,
|
|
168
|
+
}
|
|
169
|
+
|
|
114
170
|
return (
|
|
115
|
-
<
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
size=
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
key={p}
|
|
130
|
-
icon="24/Dot"
|
|
131
|
-
size="M"
|
|
132
|
-
disabled
|
|
133
|
-
className="charcoal-pagination-button charcoal-pagination-spacer"
|
|
134
|
-
aria-hidden
|
|
135
|
-
/>
|
|
136
|
-
) : p === page ? (
|
|
137
|
-
<span key={p} className="charcoal-pagination-button" aria-current>
|
|
138
|
-
<Text>{p}</Text>
|
|
139
|
-
</span>
|
|
140
|
-
) : (
|
|
141
|
-
<a key={p} href={makeUrl(p)} className="charcoal-pagination-button">
|
|
142
|
-
<Text>{p}</Text>
|
|
143
|
-
</a>
|
|
144
|
-
),
|
|
145
|
-
)}
|
|
146
|
-
<IconButton
|
|
147
|
-
icon="24/Next"
|
|
148
|
-
size="M"
|
|
149
|
-
component="a"
|
|
150
|
-
href={makeUrl(Math.min(pageCount, page + 1))}
|
|
151
|
-
className="charcoal-pagination-button"
|
|
152
|
-
data-no-background
|
|
153
|
-
hidden={!hasNext}
|
|
154
|
-
aria-disabled={!hasNext}
|
|
155
|
-
/>
|
|
156
|
-
</nav>
|
|
171
|
+
<PaginationContext.Provider value={contextValue}>
|
|
172
|
+
<nav
|
|
173
|
+
className={classNames}
|
|
174
|
+
data-size={size}
|
|
175
|
+
aria-label="Pagination"
|
|
176
|
+
{...navProps}
|
|
177
|
+
>
|
|
178
|
+
<NavButton direction="prev" />
|
|
179
|
+
{window.map((p) => (
|
|
180
|
+
<PageItem key={p} value={p} />
|
|
181
|
+
))}
|
|
182
|
+
<NavButton direction="next" />
|
|
183
|
+
</nav>
|
|
184
|
+
</PaginationContext.Provider>
|
|
157
185
|
)
|
|
158
186
|
}
|