@charcoal-ui/react 5.5.0-beta.2 → 5.5.0-beta.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@charcoal-ui/react",
3
- "version": "5.5.0-beta.2",
3
+ "version": "5.5.0-beta.3",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -54,10 +54,10 @@
54
54
  "react-compiler-runtime": "1.0.0",
55
55
  "react-stately": "^3.26.0",
56
56
  "warning": "^4.0.3",
57
- "@charcoal-ui/foundation": "5.5.0-beta.2",
58
- "@charcoal-ui/theme": "5.5.0-beta.2",
59
- "@charcoal-ui/utils": "5.5.0-beta.2",
60
- "@charcoal-ui/icons": "5.5.0-beta.2"
57
+ "@charcoal-ui/foundation": "5.5.0-beta.3",
58
+ "@charcoal-ui/icons": "5.5.0-beta.3",
59
+ "@charcoal-ui/theme": "5.5.0-beta.3",
60
+ "@charcoal-ui/utils": "5.5.0-beta.3"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "react": ">=17.0.0"
@@ -7,6 +7,9 @@ type PaginationStoryArgs = Pick<
7
7
  'page' | 'pageCount' | 'pageRangeDisplayed' | 'size'
8
8
  >
9
9
 
10
+ type LinkPaginationStoryArgs = PaginationStoryArgs &
11
+ Pick<PaginationProps, 'linkProps'>
12
+
10
13
  function PaginationWithState(args: PaginationStoryArgs) {
11
14
  const [page, setPage] = useState(args.page)
12
15
  return (
@@ -25,7 +28,7 @@ function parsePageFromHash(fallback: number): number {
25
28
  return match ? parseInt(match[1], 10) : fallback
26
29
  }
27
30
 
28
- function LinkPaginationWithState(args: PaginationStoryArgs) {
31
+ function LinkPaginationWithState(args: LinkPaginationStoryArgs) {
29
32
  const [page, setPage] = useState(() => parsePageFromHash(args.page))
30
33
 
31
34
  useEffect(() => {
@@ -45,6 +48,7 @@ function LinkPaginationWithState(args: PaginationStoryArgs) {
45
48
  pageRangeDisplayed={args.pageRangeDisplayed}
46
49
  size={args.size}
47
50
  makeUrl={(p) => `#page-${p}`}
51
+ linkProps={args.linkProps}
48
52
  />
49
53
  </div>
50
54
  )
@@ -111,3 +115,19 @@ export const LinkPaginationStory: StoryObj<typeof Pagination> = {
111
115
  },
112
116
  render: (args) => <LinkPaginationWithState {...args} />,
113
117
  }
118
+
119
+ export const LinkPaginationWithLinkProps: StoryObj<typeof Pagination> = {
120
+ args: {
121
+ page: 5,
122
+ pageCount: 10,
123
+ linkProps: { scroll: 'marker' },
124
+ },
125
+ render: (args) => (
126
+ <div>
127
+ <p style={{ marginBottom: 8, fontSize: 14, color: '#666' }}>
128
+ linkProps を渡した例(scroll: &apos;marker&apos; は Next.js Link 用)
129
+ </p>
130
+ <LinkPaginationWithState {...args} />
131
+ </div>
132
+ ),
133
+ }
@@ -10,26 +10,29 @@ export type LinkComponentProps = {
10
10
  children?: React.ReactNode
11
11
  }
12
12
 
13
- type PaginationContextValue = {
13
+ export type PaginationContextValue<T extends React.ElementType = 'a'> = {
14
14
  page: number
15
15
  pageCount: number
16
16
  size: Size
17
17
  isLinkMode: boolean
18
18
  makeUrl?: (page: number) => string
19
- LinkComponent: React.ElementType<LinkComponentProps>
19
+ LinkComponent: T
20
20
  makeClickHandler: (value: number) => () => void
21
+ linkProps?: Omit<React.ComponentPropsWithoutRef<T>, 'href' | 'children'>
21
22
  }
22
23
 
23
- export const PaginationContext = createContext<PaginationContextValue | null>(
24
- null,
25
- )
24
+ export const PaginationContext = createContext<PaginationContextValue<
25
+ React.ElementType<LinkComponentProps>
26
+ > | null>(null)
26
27
 
27
- export function usePaginationContext(): PaginationContextValue {
28
+ export function usePaginationContext<
29
+ T extends React.ElementType = 'a',
30
+ >(): PaginationContextValue<T> {
28
31
  const context = useContext(PaginationContext)
29
32
  if (context == null) {
30
33
  throw new Error(
31
34
  'Pagination components must be used within a Pagination component',
32
35
  )
33
36
  }
34
- return context
37
+ return context as PaginationContextValue<T>
35
38
  }
@@ -7,6 +7,7 @@ import {
7
7
  PaginationContext,
8
8
  usePaginationContext,
9
9
  type LinkComponentProps,
10
+ type PaginationContextValue,
10
11
  type PageRangeDisplayed,
11
12
  type Size,
12
13
  } from './PaginationContext'
@@ -25,6 +26,7 @@ function NavButton({ direction }: NavButtonProps) {
25
26
  makeUrl,
26
27
  LinkComponent,
27
28
  makeClickHandler,
29
+ linkProps,
28
30
  } = usePaginationContext()
29
31
 
30
32
  const isPrev = direction === 'prev'
@@ -32,22 +34,28 @@ function NavButton({ direction }: NavButtonProps) {
32
34
  ? Math.max(1, page - 1)
33
35
  : Math.min(pageCount, page + 1)
34
36
  const disabled = isPrev ? page <= 1 : page >= pageCount
37
+ const navButtonClassName = useClassNames(
38
+ 'charcoal-pagination-nav-button',
39
+ linkProps?.className,
40
+ )
35
41
 
36
42
  return (
37
43
  <IconButton
38
44
  icon={isPrev ? '24/Prev' : '24/Next'}
39
45
  size={size}
40
46
  hidden={disabled}
41
- className="charcoal-pagination-nav-button"
42
47
  {...(isLinkMode && makeUrl
43
48
  ? {
44
49
  component: LinkComponent as 'a',
45
50
  href: makeUrl(targetPage),
46
51
  'aria-disabled': disabled,
52
+ ...linkProps,
53
+ className: navButtonClassName,
47
54
  }
48
55
  : {
49
56
  disabled,
50
57
  onClick: makeClickHandler(targetPage),
58
+ className: navButtonClassName,
51
59
  })}
52
60
  />
53
61
  )
@@ -55,8 +63,20 @@ function NavButton({ direction }: NavButtonProps) {
55
63
 
56
64
  function PageItem({ value }: { value: number | string }) {
57
65
  'use memo'
58
- const { page, size, isLinkMode, makeUrl, LinkComponent, makeClickHandler } =
59
- usePaginationContext()
66
+ const {
67
+ page,
68
+ size,
69
+ isLinkMode,
70
+ makeUrl,
71
+ LinkComponent,
72
+ makeClickHandler,
73
+ linkProps,
74
+ } = usePaginationContext()
75
+ const pageItemClassName = useClassNames(
76
+ 'charcoal-pagination-button',
77
+ linkProps?.className,
78
+ )
79
+
60
80
  // 省略記号
61
81
  if (value === '...') {
62
82
  return (
@@ -83,7 +103,8 @@ function PageItem({ value }: { value: number | string }) {
83
103
  return (
84
104
  <LinkComponent
85
105
  href={makeUrl(value)}
86
- className="charcoal-pagination-button"
106
+ {...linkProps}
107
+ className={pageItemClassName}
87
108
  >
88
109
  {value}
89
110
  </LinkComponent>
@@ -124,11 +145,20 @@ type NavProps = Omit<React.ComponentPropsWithoutRef<'nav'>, 'onChange'>
124
145
  * @example
125
146
  * // Link mode with custom component (e.g. Next.js Link)
126
147
  * <Pagination page={1} pageCount={10} makeUrl={(p) => `?page=${p}`} component={Link} />
148
+ *
149
+ * @example
150
+ * // Link mode with linkProps (e.g. Next.js scroll)
151
+ * <Pagination page={1} pageCount={10} makeUrl={(p) => `?page=${p}`} component={Link} linkProps={{ scroll: 'marker' }} />
127
152
  */
128
- export type PaginationProps = CommonProps &
153
+ export type PaginationProps<T extends React.ElementType = 'a'> = CommonProps &
129
154
  NavProps &
130
155
  (
131
- | { onChange(newPage: number): void; makeUrl?: never; component?: never }
156
+ | {
157
+ onChange(newPage: number): void
158
+ makeUrl?: never
159
+ component?: never
160
+ linkProps?: undefined
161
+ }
132
162
  | {
133
163
  makeUrl(page: number): string
134
164
  onChange?: never
@@ -136,21 +166,26 @@ export type PaginationProps = CommonProps &
136
166
  * The component used for link elements. Receives `href`, `className`, and `children`.
137
167
  * @default 'a'
138
168
  */
139
- component?: React.ElementType<LinkComponentProps>
169
+ component?: T
170
+ /**
171
+ * Additional props passed to all link elements (e.g. Next.js Link's scroll, prefetch).
172
+ */
173
+ linkProps?: Omit<React.ComponentPropsWithoutRef<T>, 'href' | 'children'>
140
174
  }
141
175
  )
142
176
 
143
- export default function Pagination({
177
+ export default function Pagination<T extends React.ElementType = 'a'>({
144
178
  page,
145
179
  pageCount,
146
180
  pageRangeDisplayed,
147
181
  size = 'M',
148
182
  onChange,
149
183
  makeUrl,
150
- component: LinkComponent = 'a',
184
+ component: LinkComponent = 'a' as T,
185
+ linkProps,
151
186
  className,
152
187
  ...navProps
153
- }: PaginationProps) {
188
+ }: PaginationProps<T>) {
154
189
  'use memo'
155
190
  const window = usePaginationWindow(page, pageCount, pageRangeDisplayed)
156
191
  const isLinkMode = makeUrl !== undefined
@@ -165,15 +200,22 @@ export default function Pagination({
165
200
  makeUrl,
166
201
  LinkComponent,
167
202
  makeClickHandler,
203
+ linkProps,
168
204
  }
169
205
 
170
206
  return (
171
- <PaginationContext.Provider value={contextValue}>
207
+ <PaginationContext.Provider
208
+ value={
209
+ contextValue as PaginationContextValue<
210
+ React.ElementType<LinkComponentProps>
211
+ >
212
+ }
213
+ >
172
214
  <nav
173
- className={classNames}
174
215
  data-size={size}
175
216
  aria-label="Pagination"
176
217
  {...navProps}
218
+ className={classNames}
177
219
  >
178
220
  <NavButton direction="prev" />
179
221
  {window.map((p) => (