@blakesteve/roster 5.5.0 → 5.6.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.
- package/README.md +77 -1
- package/dist/components/molecules/Pagination/Pagination.cjs +1 -0
- package/dist/components/molecules/Pagination/Pagination.d.ts +116 -0
- package/dist/components/molecules/Pagination/Pagination.js +247 -0
- package/dist/components/molecules/Pagination/page-items.cjs +1 -0
- package/dist/components/molecules/Pagination/page-items.d.ts +13 -0
- package/dist/components/molecules/Pagination/page-items.js +11 -0
- package/dist/components/organisms/DataTable/DataTable.cjs +1 -1
- package/dist/components/organisms/DataTable/DataTable.d.ts +8 -1
- package/dist/components/organisms/DataTable/DataTable.js +61 -98
- package/dist/index.d.ts +1 -0
- package/dist/meta.json +3 -3
- package/dist/node_modules/@fortawesome/free-solid-svg-icons/index.cjs +1 -1
- package/dist/node_modules/@fortawesome/free-solid-svg-icons/index.js +30 -50
- package/dist/roster.cjs +1 -1
- package/dist/roster.css +1 -1
- package/dist/roster.js +69 -67
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1381,6 +1381,81 @@ submit button from sending its form twice. It no longer dims, since
|
|
|
1381
1381
|
the spinner says it's busy. `loadingLabel` names the spinner ("loading" by
|
|
1382
1382
|
default). `disabled` is unchanged and wins over `isLoading`.
|
|
1383
1383
|
|
|
1384
|
+
### Pagination
|
|
1385
|
+
|
|
1386
|
+
Moves through pages of a list, built for a long list browsed on a phone.
|
|
1387
|
+
Controlled: you hold `page` and `pageCount`.
|
|
1388
|
+
|
|
1389
|
+
```tsx
|
|
1390
|
+
import { Pagination } from "@blakesteve/roster";
|
|
1391
|
+
|
|
1392
|
+
// Pages in your own state: every control is a button.
|
|
1393
|
+
<Pagination page={page} pageCount={79} onPageChange={setPage} />
|
|
1394
|
+
|
|
1395
|
+
// Pages that are URLs: every control is a real link.
|
|
1396
|
+
<Pagination
|
|
1397
|
+
page={page}
|
|
1398
|
+
pageCount={79}
|
|
1399
|
+
getPageHref={(p) => `/catalog?page=${p}`}
|
|
1400
|
+
linkComponent={NextLink} // from a "use client" wrapper
|
|
1401
|
+
navigate={router.push} // for the compact form's page picker
|
|
1402
|
+
/>
|
|
1403
|
+
```
|
|
1404
|
+
|
|
1405
|
+
**Buttons or links.** Without `getPageHref`, controls are buttons and
|
|
1406
|
+
`onPageChange(page)` is the only thing that changes the page. With it, every
|
|
1407
|
+
control is an `<a href>` (crawlable, shareable, openable in a new tab) rendered
|
|
1408
|
+
through `linkComponent` (a plain `<a>` by default; it gets `href` and `to`, so
|
|
1409
|
+
`next/link` and React Router's `Link` both work). `onPageChange` is then called
|
|
1410
|
+
on a plain click before the link is followed. The compact form's page picker
|
|
1411
|
+
has no link to follow, so it calls `navigate(href)`, or loads the page.
|
|
1412
|
+
|
|
1413
|
+
**Two forms, chosen by the pager's own width** (a container query, so it's
|
|
1414
|
+
right in a sidebar and needs no measuring):
|
|
1415
|
+
|
|
1416
|
+
- **448px and up:** previous, the first page, the current page with a
|
|
1417
|
+
neighbor each side, the last page, gaps between, and next. That's always
|
|
1418
|
+
seven equal slots, so the buttons don't shift under the pointer as you page.
|
|
1419
|
+
The words "Previous" and "Next" join the arrows from 576px.
|
|
1420
|
+
- **Under 448px:** previous, a page picker ("Page 40 of 79"), and next, with
|
|
1421
|
+
the first and last pages joining from 384px. Any page is two taps away, and
|
|
1422
|
+
on a phone the picker is the system's own list.
|
|
1423
|
+
|
|
1424
|
+
`layout` picks one form (`"pages"`, `"compact"`), or `"arrows"` for first,
|
|
1425
|
+
previous, next and last beside a count the app shows itself, which is what
|
|
1426
|
+
DataTable uses.
|
|
1427
|
+
|
|
1428
|
+
What it promises:
|
|
1429
|
+
|
|
1430
|
+
- **Every control is a 44px target,** at every width.
|
|
1431
|
+
- **The current page is `aria-current="page"`,** the pager is a `nav` named by
|
|
1432
|
+
`labels.nav`, and every control's name says the page it goes to ("Next page
|
|
1433
|
+
(41)"). A new page is said in a polite live region ("Page 41 of 79").
|
|
1434
|
+
- **Focus stays on the control that was pressed.** A page number is the same
|
|
1435
|
+
element afterwards, and an arrow that reaches the end stays focusable,
|
|
1436
|
+
`aria-disabled` rather than `disabled`. To take a reader to the top of the
|
|
1437
|
+
new page, focus your list's heading in `onPageChange`.
|
|
1438
|
+
- **Every word is a `labels` entry,** page numbers included (`labels.number`).
|
|
1439
|
+
- **No Font Awesome:** the chevrons are inline SVG.
|
|
1440
|
+
- **The picker waits for the keyboard.** A pick from its list goes at once.
|
|
1441
|
+
Arrow keys on the closed picker (which step it on Windows and Linux) hold the
|
|
1442
|
+
choice until Enter or leaving it; Escape puts it back.
|
|
1443
|
+
|
|
1444
|
+
Things to know:
|
|
1445
|
+
|
|
1446
|
+
- **Give the pager a width.** It sizes its form by the width it's given, so in
|
|
1447
|
+
a slot that sizes to its content (an `ml-auto` box beside a heading, an `auto`
|
|
1448
|
+
grid column) it falls back to 18rem, the compact form. For numbers there,
|
|
1449
|
+
give the slot a width (`flex-1`, a `1fr` column) or pass `layout="pages"`.
|
|
1450
|
+
- **`siblings` above 1** needs more room than the 448px switch allows for;
|
|
1451
|
+
force `layout` if you widen it.
|
|
1452
|
+
- **When you move focus yourself,** pass `announce={false}`: the heading you
|
|
1453
|
+
focus says the new page, and the live region would say it again.
|
|
1454
|
+
- **In jsdom tests,** where no CSS applies, `layout="auto"` renders both forms;
|
|
1455
|
+
pass a `layout`, or query inside `[data-pagination-layout="pages"]`.
|
|
1456
|
+
- **Wire it fully.** With neither `onPageChange` nor `getPageHref` nothing
|
|
1457
|
+
pages, and in link mode without `navigate` the picker does a full page load.
|
|
1458
|
+
|
|
1384
1459
|
### Carousel
|
|
1385
1460
|
|
|
1386
1461
|
A sideways row: a row of cards, a selection strip, or a gallery of one per
|
|
@@ -1524,6 +1599,7 @@ function App() {
|
|
|
1524
1599
|
| `MatchupCard` | Head-to-head comparison card |
|
|
1525
1600
|
| `MediaPreview` | Thumbnail that falls back to "Preview unavailable, open original" when it can't render |
|
|
1526
1601
|
| `FileUpload` | Picks files and uploads each through the app's `upload`, with per-file progress, retry and rules |
|
|
1602
|
+
| `Pagination` | Page numbers with gaps, or a compact page picker on narrow screens; buttons or real links, 44px targets |
|
|
1527
1603
|
| `Pullquote` | A line lifted out of prose, as `<figure>` + `<blockquote>` + `<figcaption>` |
|
|
1528
1604
|
| `RadioGroup` | Radio set reporting one `string`; descriptions, error, 44px targets |
|
|
1529
1605
|
| `Toast` | Transient floating notice; `Toaster` + the imperative `toast` handle |
|
|
@@ -1534,7 +1610,7 @@ function App() {
|
|
|
1534
1610
|
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
1535
1611
|
| `ActionBar` | Sticky bottom action strip |
|
|
1536
1612
|
| `Countdown` | Live countdown timer |
|
|
1537
|
-
| `DataTable` | Full-featured table with sorting and pagination via TanStack Table v9
|
|
1613
|
+
| `DataTable` | Full-featured table with sorting and pagination via TanStack Table v9; its pager is `Pagination`'s arrows, worded through `paginationLabels`. Imported from `@blakesteve/roster/data-table` (see [DataTable columns](#datatable-columns)) |
|
|
1538
1614
|
| `Dialog` | Modal dialog; `onAfterClose` runs once it has finished closing |
|
|
1539
1615
|
| `Footer` | Site footer |
|
|
1540
1616
|
| `ModerationQueue` | Items waiting for a decision: busy per action, confirm, reason and edit steps, focus after an item leaves, a live region. Never fetches (see [ModerationQueue](#moderationqueue)) |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),w=require("react"),v=require("../../../lib/utils.cjs"),ee=require("../../atoms/Button/Button.cjs"),te=require("../../atoms/Button/button-variants.cjs"),se=require("../../atoms/Select/select-variants.cjs"),Q=require("./page-items.cjs"),re={nav:"Pagination",page:t=>`Page ${t}`,number:t=>String(t),previous:"Previous",next:"Next",previousPage:t=>t===null?"Previous page":`Previous page (${t})`,nextPage:t=>t===null?"Next page":`Next page (${t})`,firstPage:t=>t===null?"First page":`First page (${t})`,lastPage:t=>t===null?"Last page":`Last page (${t})`,gap:"…",picker:"Page",of:t=>`of ${t}`,status:(t,i)=>`Page ${t} of ${i}`};function ae({href:t,className:i,children:c,onClick:o,...d}){return e.jsx("a",{href:t,className:i,onClick:o,"aria-label":d["aria-label"],"aria-current":d["aria-current"],"aria-disabled":d["aria-disabled"],children:c})}const ne="rst:h-11 rst:min-w-11 rst:px-2",ie="rst:cursor-not-allowed rst:opacity-50",le="rst:forced-colors:border-2 rst:forced-colors:underline rst:forced-colors:decoration-2 rst:forced-colors:underline-offset-4",X={width:18,height:18,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":!0},F=({dir:t,double:i=!1})=>e.jsx("svg",{...X,className:"rst:shrink-0",children:t==="left"?i?e.jsx("path",{d:"m11 17-5-5 5-5M18 17l-5-5 5-5"}):e.jsx("path",{d:"m15 18-6-6 6-6"}):i?e.jsx("path",{d:"m13 17 5-5-5-5M6 17l5-5-5-5"}):e.jsx("path",{d:"m9 18 6-6-6-6"})});function oe({id:t,describedBy:i,page:c,pageCount:o,number:d,onCommit:k}){const[u,j]=w.useState(null),p=w.useRef(!1),x=u&&u.page===c?u.value:null,b=l=>{j(null),l!==c&&k(l)},P=w.useMemo(()=>Array.from({length:o},(l,f)=>e.jsx("option",{value:f+1,children:d(f+1)},f+1)),[o,d]);return e.jsx("select",{id:t,value:x??c,"aria-describedby":i,disabled:o<1,onKeyDown:l=>{if(l.key==="Enter"){x!==null&&(l.preventDefault(),b(x));return}if(l.key==="Escape"){j(null);return}p.current=!0,setTimeout(()=>{p.current=!1},0)},onChange:l=>{const f=Number(l.currentTarget.value);p.current?j({page:c,value:f}):b(f)},onBlur:()=>{x!==null&&b(x)},className:v.cn(se.selectTriggerVariants({variant:"outline"}),"rst:h-11 rst:w-auto rst:min-w-16 rst:appearance-none rst:pl-3 rst:pr-8 rst:text-base rst:tabular-nums"),"data-pagination-picker":"",children:P})}function ce({page:t,pageCount:i,onPageChange:c,getPageHref:o,linkComponent:d,navigate:k,layout:u="auto",siblings:j=1,edges:p=!0,align:x="center",variant:b="ghost",announce:P=!0,labels:l,className:f}){const a={...re,...l},m=Number.isFinite(i)?Math.max(0,Math.floor(i)):0,n=Q.clampPage(t,m),C=w.useId(),Y=d??ae,[E,Z]=w.useState({page:n,text:""});E.page!==n&&Z({page:n,text:P?a.status(n,m):""});const L=s=>{s!==Math.floor(t)&&c?.(s)},y=(s,r,N,A)=>{const h=s==="page"&&r===n,$=r===null,U=v.cn(ne,$&&ie,h&&le,A.className),W=s==="page"?`page-${r}`:s;if(o){const J=o(r??n);return e.jsx(Y,{href:J,to:J,className:v.cn(te.buttonVariants({variant:h?"solid":b,colorScheme:h?"primary":"neutral"}),U),"aria-label":A.label,"aria-current":h?"page":void 0,"aria-disabled":$?!0:void 0,onClick:g=>{if($){g.preventDefault();return}!g.defaultPrevented&&g.button===0&&!g.metaKey&&!g.ctrlKey&&!g.shiftKey&&!g.altKey&&r!==null&&L(r)},children:N},W)}return e.jsx(ee.Button,{type:"button",variant:h?"solid":b,colorScheme:h?"primary":"neutral",className:U,"aria-label":A.label,"aria-current":h?"page":void 0,"aria-disabled":$||void 0,onClick:()=>{r!==null&&L(r)},children:N},W)},I=n>1?n-1:null,R=n<m?n+1:null,T=n>1?1:null,B=n<m?m:null,M=s=>y("previous",I,e.jsxs(e.Fragment,{children:[e.jsx(F,{dir:"left"}),s&&e.jsx("span",{className:"rst:hidden rst:pr-1 rst:@[36rem]:inline",children:a.previous})]}),{label:a.previousPage(I)}),S=s=>y("next",R,e.jsxs(e.Fragment,{children:[s&&e.jsx("span",{className:"rst:hidden rst:pl-1 rst:@[36rem]:inline",children:a.next}),e.jsx(F,{dir:"right"})]}),{label:a.nextPage(R)}),K=s=>y("first",T,e.jsx(F,{dir:"left",double:!0}),{label:a.firstPage(T),className:s?"rst:hidden rst:@[24rem]:inline-flex":void 0}),V=s=>y("last",B,e.jsx(F,{dir:"right",double:!0}),{label:a.lastPage(B),className:s?"rst:hidden rst:@[24rem]:inline-flex":void 0}),D="rst:flex rst:flex-wrap rst:items-center rst:gap-1",q={start:"rst:justify-start",center:"rst:justify-center",end:"rst:justify-end"}[x],O=s=>e.jsxs("div",{className:v.cn(D,q,s),"data-pagination-layout":"pages",children:[M(!0),Q.pageItems(n,m,j).map(r=>typeof r=="number"?y("page",r,a.number(r),{label:a.page(r)}):e.jsx("span",{"aria-hidden":"true",className:"rst:inline-flex rst:h-11 rst:w-11 rst:items-center rst:justify-center rst:text-sm rst:text-gray-500 rst:dark:text-gray-400",children:a.gap},r)),S(!0)]}),_=`${C}-picker`,z=`${C}-of`,G=s=>e.jsxs("div",{className:v.cn(D,q,s),"data-pagination-layout":"compact",children:[p&&K(!0),M(!1),e.jsxs("div",{className:"rst:flex rst:items-center rst:gap-2 rst:px-1 rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]",children:[e.jsx("label",{htmlFor:_,children:a.picker}),e.jsxs("span",{className:"rst:relative rst:inline-flex",children:[e.jsx(oe,{id:_,describedBy:z,page:n,pageCount:m,number:a.number,onCommit:r=>{if(o){c?.(r);const N=o(r);k?k(N):window.location.assign(N)}else L(r)}}),e.jsx("svg",{...X,width:16,height:16,className:"rst:pointer-events-none rst:absolute rst:right-2.5 rst:top-1/2 rst:-translate-y-1/2 rst:text-gray-500 rst:dark:text-gray-400",children:e.jsx("path",{d:"m6 9 6 6 6-6"})})]}),e.jsx("span",{id:z,className:"rst:tabular-nums",children:a.of(m)})]}),S(!1),p&&V(!0)]}),H=e.jsxs("div",{className:v.cn(D,q),"data-pagination-layout":"arrows",children:[p&&K(!1),M(!1),S(!1),p&&V(!1)]});return e.jsxs("nav",{"aria-label":a.nav,className:v.cn("rst:font-ui",u==="arrows"?"rst:w-fit":"rst:@container rst:w-full rst:[contain-intrinsic-inline-size:18rem]",f),"data-pagination":"",children:[u==="pages"&&O(),u==="compact"&&G(),u==="arrows"&&H,u==="auto"&&e.jsxs(e.Fragment,{children:[O("rst:hidden rst:@[28rem]:flex"),G("rst:@[28rem]:hidden")]}),P&&e.jsx("div",{role:"status","aria-live":"polite","aria-atomic":"true",className:"rst:sr-only","data-pagination-live":"",children:E.text})]})}exports.Pagination=ce;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { ComponentType, MouseEvent, ReactNode } from 'react';
|
|
2
|
+
/** Every word Pagination shows or says. Pass any of them in `labels` to replace it. */
|
|
3
|
+
export interface PaginationLabels {
|
|
4
|
+
/** The landmark's name. A page with two pagers needs each named. */
|
|
5
|
+
nav: string;
|
|
6
|
+
/** A page number's accessible name: "Page 40". */
|
|
7
|
+
page: (page: number) => string;
|
|
8
|
+
/** A page number as shown. */
|
|
9
|
+
number: (page: number) => string;
|
|
10
|
+
/** Shown beside the arrows where there's room. */
|
|
11
|
+
previous: string;
|
|
12
|
+
next: string;
|
|
13
|
+
/** Each arrow's accessible name, given the page it goes to, or `null` at the end it can't pass. */
|
|
14
|
+
previousPage: (target: number | null) => string;
|
|
15
|
+
nextPage: (target: number | null) => string;
|
|
16
|
+
firstPage: (target: number | null) => string;
|
|
17
|
+
lastPage: (target: number | null) => string;
|
|
18
|
+
/** Where pages are skipped. Hidden from screen readers, which hear the numbers either side. */
|
|
19
|
+
gap: string;
|
|
20
|
+
/** The page picker's label in the compact form: "Page". */
|
|
21
|
+
picker: string;
|
|
22
|
+
/** After the picker: "of 79". */
|
|
23
|
+
of: (pageCount: number) => string;
|
|
24
|
+
/** Said politely when the page changes: "Page 41 of 79". */
|
|
25
|
+
status: (page: number, pageCount: number) => string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The props every link is rendered with, in link mode.
|
|
29
|
+
*
|
|
30
|
+
* `href` and `to` carry the same value, so `next/link`, React Router's `Link`
|
|
31
|
+
* and a plain `<a>` all work without a wrapper.
|
|
32
|
+
*/
|
|
33
|
+
export interface PaginationLinkProps {
|
|
34
|
+
href: string;
|
|
35
|
+
to: string;
|
|
36
|
+
className: string;
|
|
37
|
+
children: ReactNode;
|
|
38
|
+
"aria-label": string;
|
|
39
|
+
"aria-current"?: "page";
|
|
40
|
+
"aria-disabled"?: true;
|
|
41
|
+
onClick: (event: MouseEvent<HTMLAnchorElement>) => void;
|
|
42
|
+
}
|
|
43
|
+
export interface PaginationProps {
|
|
44
|
+
/** The current page, from 1. */
|
|
45
|
+
page: number;
|
|
46
|
+
/** How many pages there are. */
|
|
47
|
+
pageCount: number;
|
|
48
|
+
/**
|
|
49
|
+
* Called with the page a control goes to.
|
|
50
|
+
*
|
|
51
|
+
* Without `getPageHref`, every control is a button and this is the only
|
|
52
|
+
* thing that changes the page: page in your own state.
|
|
53
|
+
*
|
|
54
|
+
* With `getPageHref`, the controls are links and navigate themselves; this
|
|
55
|
+
* is called first, on a plain left click (not one that opens a new tab),
|
|
56
|
+
* for an app that wants to do something as it goes.
|
|
57
|
+
*/
|
|
58
|
+
onPageChange?: (page: number) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Makes every control a real link to `getPageHref(page)`: crawlable,
|
|
61
|
+
* shareable, and openable in a new tab. Use it when your pages are URLs.
|
|
62
|
+
*/
|
|
63
|
+
getPageHref?: (page: number) => string;
|
|
64
|
+
/**
|
|
65
|
+
* Renders each link in link mode. Defaults to a plain `<a>`, which is right
|
|
66
|
+
* for a static site and wrong inside a router, where every hop becomes a
|
|
67
|
+
* full page load.
|
|
68
|
+
*
|
|
69
|
+
* **Pass it from a client component.** Functions can not cross the React
|
|
70
|
+
* Server Component boundary. Bind it in a small `"use client"` wrapper.
|
|
71
|
+
*/
|
|
72
|
+
linkComponent?: ComponentType<PaginationLinkProps>;
|
|
73
|
+
/**
|
|
74
|
+
* How the compact form's page picker goes to a page in link mode, where
|
|
75
|
+
* there's no link to follow. Defaults to a full page load
|
|
76
|
+
* (`location.assign`); pass your router's push to stay client-side.
|
|
77
|
+
*/
|
|
78
|
+
navigate?: (href: string) => void;
|
|
79
|
+
/**
|
|
80
|
+
* - `"pages"`: previous, page numbers with gaps, next.
|
|
81
|
+
* - `"compact"`: previous, a page picker ("Page 40 of 79"), next, and the
|
|
82
|
+
* first and last pages where there's room. Any page is two taps away.
|
|
83
|
+
* - `"arrows"`: first, previous, next, last, for a pager that shows its
|
|
84
|
+
* own position.
|
|
85
|
+
* - `"auto"` (the default): `"pages"` where the pager has room, `"compact"`
|
|
86
|
+
* where it doesn't. Decided by the pager's own width, not the screen's.
|
|
87
|
+
*/
|
|
88
|
+
layout?: "auto" | "pages" | "compact" | "arrows";
|
|
89
|
+
/** Page numbers shown either side of the current one. */
|
|
90
|
+
siblings?: number;
|
|
91
|
+
/** Whether the compact and arrow forms offer the first and last pages. */
|
|
92
|
+
edges?: boolean;
|
|
93
|
+
/** Where the controls sit in the pager's width. */
|
|
94
|
+
align?: "start" | "center" | "end";
|
|
95
|
+
/** How the controls other than the current page are drawn. */
|
|
96
|
+
variant?: "ghost" | "outline";
|
|
97
|
+
/** Say the new page in a polite live region when it changes. */
|
|
98
|
+
announce?: boolean;
|
|
99
|
+
labels?: Partial<PaginationLabels>;
|
|
100
|
+
className?: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Moves through pages of a list.
|
|
104
|
+
*
|
|
105
|
+
* Controlled: you hold `page`, and the pager says which page a control goes
|
|
106
|
+
* to. Its controls are buttons that call `onPageChange`, or, with
|
|
107
|
+
* `getPageHref`, real links.
|
|
108
|
+
*
|
|
109
|
+
* **Focus.** A control keeps focus after the page changes: the number you
|
|
110
|
+
* pressed is the same element afterwards, and an arrow that reaches the end
|
|
111
|
+
* stays focusable, `aria-disabled`. Nothing moves focus for you. To take a
|
|
112
|
+
* reader to the top of the new page, focus your list's heading in
|
|
113
|
+
* `onPageChange`.
|
|
114
|
+
*/
|
|
115
|
+
declare function Pagination({ page: rawPage, pageCount: rawCount, onPageChange, getPageHref, linkComponent, navigate, layout, siblings, edges, align, variant, announce, labels: overrides, className, }: PaginationProps): import("react/jsx-runtime").JSX.Element;
|
|
116
|
+
export { Pagination };
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as u, Fragment as I, jsx as e } from "react/jsx-runtime";
|
|
3
|
+
import { useId as et, useState as X, useRef as rt, useMemo as st } from "react";
|
|
4
|
+
import { cn as x } from "../../../lib/utils.js";
|
|
5
|
+
import { Button as at } from "../../atoms/Button/Button.js";
|
|
6
|
+
import { buttonVariants as nt } from "../../atoms/Button/button-variants.js";
|
|
7
|
+
import { selectTriggerVariants as it } from "../../atoms/Select/select-variants.js";
|
|
8
|
+
import { clampPage as lt, pageItems as ot } from "./page-items.js";
|
|
9
|
+
const ct = {
|
|
10
|
+
nav: "Pagination",
|
|
11
|
+
page: (t) => `Page ${t}`,
|
|
12
|
+
number: (t) => String(t),
|
|
13
|
+
previous: "Previous",
|
|
14
|
+
next: "Next",
|
|
15
|
+
previousPage: (t) => t === null ? "Previous page" : `Previous page (${t})`,
|
|
16
|
+
nextPage: (t) => t === null ? "Next page" : `Next page (${t})`,
|
|
17
|
+
firstPage: (t) => t === null ? "First page" : `First page (${t})`,
|
|
18
|
+
lastPage: (t) => t === null ? "Last page" : `Last page (${t})`,
|
|
19
|
+
gap: "…",
|
|
20
|
+
picker: "Page",
|
|
21
|
+
of: (t) => `of ${t}`,
|
|
22
|
+
status: (t, i) => `Page ${t} of ${i}`
|
|
23
|
+
};
|
|
24
|
+
function dt({ href: t, className: i, children: c, onClick: o, ...p }) {
|
|
25
|
+
return /* @__PURE__ */ e(
|
|
26
|
+
"a",
|
|
27
|
+
{
|
|
28
|
+
href: t,
|
|
29
|
+
className: i,
|
|
30
|
+
onClick: o,
|
|
31
|
+
"aria-label": p["aria-label"],
|
|
32
|
+
"aria-current": p["aria-current"],
|
|
33
|
+
"aria-disabled": p["aria-disabled"],
|
|
34
|
+
children: c
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const ut = "rst:h-11 rst:min-w-11 rst:px-2", pt = "rst:cursor-not-allowed rst:opacity-50", ft = "rst:forced-colors:border-2 rst:forced-colors:underline rst:forced-colors:decoration-2 rst:forced-colors:underline-offset-4", Y = { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": !0 }, j = ({ dir: t, double: i = !1 }) => /* @__PURE__ */ e("svg", { ...Y, className: "rst:shrink-0", children: t === "left" ? i ? /* @__PURE__ */ e("path", { d: "m11 17-5-5 5-5M18 17l-5-5 5-5" }) : /* @__PURE__ */ e("path", { d: "m15 18-6-6 6-6" }) : i ? /* @__PURE__ */ e("path", { d: "m13 17 5-5-5-5M6 17l5-5-5-5" }) : /* @__PURE__ */ e("path", { d: "m9 18 6-6-6-6" }) });
|
|
39
|
+
function mt({
|
|
40
|
+
id: t,
|
|
41
|
+
describedBy: i,
|
|
42
|
+
page: c,
|
|
43
|
+
pageCount: o,
|
|
44
|
+
number: p,
|
|
45
|
+
onCommit: P
|
|
46
|
+
}) {
|
|
47
|
+
const [d, N] = X(null), f = rt(!1), v = d && d.page === c ? d.value : null, y = (l) => {
|
|
48
|
+
N(null), l !== c && P(l);
|
|
49
|
+
}, $ = st(
|
|
50
|
+
() => Array.from({ length: o }, (l, m) => /* @__PURE__ */ e("option", { value: m + 1, children: p(m + 1) }, m + 1)),
|
|
51
|
+
[o, p]
|
|
52
|
+
);
|
|
53
|
+
return /* @__PURE__ */ e(
|
|
54
|
+
"select",
|
|
55
|
+
{
|
|
56
|
+
id: t,
|
|
57
|
+
value: v ?? c,
|
|
58
|
+
"aria-describedby": i,
|
|
59
|
+
disabled: o < 1,
|
|
60
|
+
onKeyDown: (l) => {
|
|
61
|
+
if (l.key === "Enter") {
|
|
62
|
+
v !== null && (l.preventDefault(), y(v));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (l.key === "Escape") {
|
|
66
|
+
N(null);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
f.current = !0, setTimeout(() => {
|
|
70
|
+
f.current = !1;
|
|
71
|
+
}, 0);
|
|
72
|
+
},
|
|
73
|
+
onChange: (l) => {
|
|
74
|
+
const m = Number(l.currentTarget.value);
|
|
75
|
+
f.current ? N({ page: c, value: m }) : y(m);
|
|
76
|
+
},
|
|
77
|
+
onBlur: () => {
|
|
78
|
+
v !== null && y(v);
|
|
79
|
+
},
|
|
80
|
+
className: x(
|
|
81
|
+
it({ variant: "outline" }),
|
|
82
|
+
/* 16px: iOS zooms the page into a select whose text is smaller. */
|
|
83
|
+
"rst:h-11 rst:w-auto rst:min-w-16 rst:appearance-none rst:pl-3 rst:pr-8 rst:text-base rst:tabular-nums"
|
|
84
|
+
),
|
|
85
|
+
"data-pagination-picker": "",
|
|
86
|
+
children: $
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
function kt({
|
|
91
|
+
page: t,
|
|
92
|
+
pageCount: i,
|
|
93
|
+
onPageChange: c,
|
|
94
|
+
getPageHref: o,
|
|
95
|
+
linkComponent: p,
|
|
96
|
+
navigate: P,
|
|
97
|
+
layout: d = "auto",
|
|
98
|
+
siblings: N = 1,
|
|
99
|
+
edges: f = !0,
|
|
100
|
+
align: v = "center",
|
|
101
|
+
variant: y = "ghost",
|
|
102
|
+
announce: $ = !0,
|
|
103
|
+
labels: l,
|
|
104
|
+
className: m
|
|
105
|
+
}) {
|
|
106
|
+
const a = { ...ct, ...l }, h = Number.isFinite(i) ? Math.max(0, Math.floor(i)) : 0, n = lt(t, h), S = et(), Z = p ?? dt, [T, H] = X({ page: n, text: "" });
|
|
107
|
+
T.page !== n && H({ page: n, text: $ ? a.status(n, h) : "" });
|
|
108
|
+
const D = (r) => {
|
|
109
|
+
r !== Math.floor(t) && c?.(r);
|
|
110
|
+
}, w = (r, s, k, F) => {
|
|
111
|
+
const g = r === "page" && s === n, L = s === null, q = x(ut, L && pt, g && ft, F.className), J = r === "page" ? `page-${s}` : r;
|
|
112
|
+
if (o) {
|
|
113
|
+
const Q = o(s ?? n);
|
|
114
|
+
return /* @__PURE__ */ e(
|
|
115
|
+
Z,
|
|
116
|
+
{
|
|
117
|
+
href: Q,
|
|
118
|
+
to: Q,
|
|
119
|
+
className: x(nt({ variant: g ? "solid" : y, colorScheme: g ? "primary" : "neutral" }), q),
|
|
120
|
+
"aria-label": F.label,
|
|
121
|
+
"aria-current": g ? "page" : void 0,
|
|
122
|
+
"aria-disabled": L ? !0 : void 0,
|
|
123
|
+
onClick: (b) => {
|
|
124
|
+
if (L) {
|
|
125
|
+
b.preventDefault();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
!b.defaultPrevented && b.button === 0 && !b.metaKey && !b.ctrlKey && !b.shiftKey && !b.altKey && s !== null && D(s);
|
|
129
|
+
},
|
|
130
|
+
children: k
|
|
131
|
+
},
|
|
132
|
+
J
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
return /* @__PURE__ */ e(
|
|
136
|
+
at,
|
|
137
|
+
{
|
|
138
|
+
type: "button",
|
|
139
|
+
variant: g ? "solid" : y,
|
|
140
|
+
colorScheme: g ? "primary" : "neutral",
|
|
141
|
+
className: q,
|
|
142
|
+
"aria-label": F.label,
|
|
143
|
+
"aria-current": g ? "page" : void 0,
|
|
144
|
+
"aria-disabled": L || void 0,
|
|
145
|
+
onClick: () => {
|
|
146
|
+
s !== null && D(s);
|
|
147
|
+
},
|
|
148
|
+
children: k
|
|
149
|
+
},
|
|
150
|
+
J
|
|
151
|
+
);
|
|
152
|
+
}, B = n > 1 ? n - 1 : null, K = n < h ? n + 1 : null, R = n > 1 ? 1 : null, O = n < h ? h : null, M = (r) => w(
|
|
153
|
+
"previous",
|
|
154
|
+
B,
|
|
155
|
+
/* @__PURE__ */ u(I, { children: [
|
|
156
|
+
/* @__PURE__ */ e(j, { dir: "left" }),
|
|
157
|
+
r && /* @__PURE__ */ e("span", { className: "rst:hidden rst:pr-1 rst:@[36rem]:inline", children: a.previous })
|
|
158
|
+
] }),
|
|
159
|
+
{ label: a.previousPage(B) }
|
|
160
|
+
), A = (r) => w(
|
|
161
|
+
"next",
|
|
162
|
+
K,
|
|
163
|
+
/* @__PURE__ */ u(I, { children: [
|
|
164
|
+
r && /* @__PURE__ */ e("span", { className: "rst:hidden rst:pl-1 rst:@[36rem]:inline", children: a.next }),
|
|
165
|
+
/* @__PURE__ */ e(j, { dir: "right" })
|
|
166
|
+
] }),
|
|
167
|
+
{ label: a.nextPage(K) }
|
|
168
|
+
), V = (r) => w("first", R, /* @__PURE__ */ e(j, { dir: "left", double: !0 }), {
|
|
169
|
+
label: a.firstPage(R),
|
|
170
|
+
className: r ? "rst:hidden rst:@[24rem]:inline-flex" : void 0
|
|
171
|
+
}), _ = (r) => w("last", O, /* @__PURE__ */ e(j, { dir: "right", double: !0 }), {
|
|
172
|
+
label: a.lastPage(O),
|
|
173
|
+
className: r ? "rst:hidden rst:@[24rem]:inline-flex" : void 0
|
|
174
|
+
}), C = "rst:flex rst:flex-wrap rst:items-center rst:gap-1", E = { start: "rst:justify-start", center: "rst:justify-center", end: "rst:justify-end" }[v], z = (r) => /* @__PURE__ */ u("div", { className: x(C, E, r), "data-pagination-layout": "pages", children: [
|
|
175
|
+
M(!0),
|
|
176
|
+
ot(n, h, N).map(
|
|
177
|
+
(s) => typeof s == "number" ? w("page", s, a.number(s), { label: a.page(s) }) : /* @__PURE__ */ e("span", { "aria-hidden": "true", className: "rst:inline-flex rst:h-11 rst:w-11 rst:items-center rst:justify-center rst:text-sm rst:text-gray-500 rst:dark:text-gray-400", children: a.gap }, s)
|
|
178
|
+
),
|
|
179
|
+
A(!0)
|
|
180
|
+
] }), G = `${S}-picker`, U = `${S}-of`, W = (r) => /* @__PURE__ */ u("div", { className: x(C, E, r), "data-pagination-layout": "compact", children: [
|
|
181
|
+
f && V(!0),
|
|
182
|
+
M(!1),
|
|
183
|
+
/* @__PURE__ */ u("div", { className: "rst:flex rst:items-center rst:gap-2 rst:px-1 rst:text-sm rst:font-medium rst:text-[var(--roster-control-text)]", children: [
|
|
184
|
+
/* @__PURE__ */ e("label", { htmlFor: G, children: a.picker }),
|
|
185
|
+
/* @__PURE__ */ u("span", { className: "rst:relative rst:inline-flex", children: [
|
|
186
|
+
/* @__PURE__ */ e(
|
|
187
|
+
mt,
|
|
188
|
+
{
|
|
189
|
+
id: G,
|
|
190
|
+
describedBy: U,
|
|
191
|
+
page: n,
|
|
192
|
+
pageCount: h,
|
|
193
|
+
number: a.number,
|
|
194
|
+
onCommit: (s) => {
|
|
195
|
+
if (o) {
|
|
196
|
+
c?.(s);
|
|
197
|
+
const k = o(s);
|
|
198
|
+
P ? P(k) : window.location.assign(k);
|
|
199
|
+
} else D(s);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
),
|
|
203
|
+
/* @__PURE__ */ e("svg", { ...Y, width: 16, height: 16, className: "rst:pointer-events-none rst:absolute rst:right-2.5 rst:top-1/2 rst:-translate-y-1/2 rst:text-gray-500 rst:dark:text-gray-400", children: /* @__PURE__ */ e("path", { d: "m6 9 6 6 6-6" }) })
|
|
204
|
+
] }),
|
|
205
|
+
/* @__PURE__ */ e("span", { id: U, className: "rst:tabular-nums", children: a.of(h) })
|
|
206
|
+
] }),
|
|
207
|
+
A(!1),
|
|
208
|
+
f && _(!0)
|
|
209
|
+
] }), tt = /* @__PURE__ */ u("div", { className: x(C, E), "data-pagination-layout": "arrows", children: [
|
|
210
|
+
f && V(!1),
|
|
211
|
+
M(!1),
|
|
212
|
+
A(!1),
|
|
213
|
+
f && _(!1)
|
|
214
|
+
] });
|
|
215
|
+
return (
|
|
216
|
+
/* A query container sizes itself as if it were empty across, so it takes
|
|
217
|
+
the full width it's given; in a slot that sizes to its content (an
|
|
218
|
+
`ml-auto` box, an `auto` grid column) it would be 0 wide. There it
|
|
219
|
+
falls back to 18rem, which is the compact form. The arrows need no
|
|
220
|
+
queries, and size to fit, to sit in a row beside something else. */
|
|
221
|
+
/* @__PURE__ */ u(
|
|
222
|
+
"nav",
|
|
223
|
+
{
|
|
224
|
+
"aria-label": a.nav,
|
|
225
|
+
className: x(
|
|
226
|
+
"rst:font-ui",
|
|
227
|
+
d === "arrows" ? "rst:w-fit" : "rst:@container rst:w-full rst:[contain-intrinsic-inline-size:18rem]",
|
|
228
|
+
m
|
|
229
|
+
),
|
|
230
|
+
"data-pagination": "",
|
|
231
|
+
children: [
|
|
232
|
+
d === "pages" && z(),
|
|
233
|
+
d === "compact" && W(),
|
|
234
|
+
d === "arrows" && tt,
|
|
235
|
+
d === "auto" && /* @__PURE__ */ u(I, { children: [
|
|
236
|
+
z("rst:hidden rst:@[28rem]:flex"),
|
|
237
|
+
W("rst:@[28rem]:hidden")
|
|
238
|
+
] }),
|
|
239
|
+
$ && /* @__PURE__ */ e("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "rst:sr-only", "data-pagination-live": "", children: T.text })
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
)
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
export {
|
|
246
|
+
kt as Pagination
|
|
247
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function p(e,a,s=1){const t=Number.isFinite(a)?Math.max(0,Math.floor(a)):0,n=Number.isFinite(s)?Math.max(0,Math.floor(s)):1,c=g(e,t),o=2*n+5,r=(h,u)=>Array.from({length:u-h+1},(d,f)=>h+f);if(t<=o)return r(1,t);const i=Math.max(c-n,1),m=Math.min(c+n,t),M=i>3,l=m<t-2;return M?l?[1,"gap-start",...r(i,m),"gap-end",t]:[1,"gap-start",...r(t-(o-3),t)]:[...r(1,o-2),"gap-end",t]}const g=(e,a)=>Math.min(Math.max(1,Math.floor(e)||1),Math.max(1,Number.isFinite(a)?Math.floor(a):1));exports.clampPage=g;exports.pageItems=p;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which page numbers a numbered pager shows, and where it skips.
|
|
3
|
+
*
|
|
4
|
+
* Always the same number of slots once there are more pages than fit: the
|
|
5
|
+
* first page, the last, the current one with `siblings` on each side, and a
|
|
6
|
+
* gap marker on each side, which becomes a page number itself near either
|
|
7
|
+
* end. A pager whose width doesn't change as you page through is one whose
|
|
8
|
+
* buttons don't move out from under the pointer.
|
|
9
|
+
*/
|
|
10
|
+
export type PageItem = number | "gap-start" | "gap-end";
|
|
11
|
+
export declare function pageItems(page: number, pageCount: number, siblings?: number): PageItem[];
|
|
12
|
+
/** `page` brought into 1 to `pageCount`. */
|
|
13
|
+
export declare const clampPage: (page: number, pageCount: number) => number;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function x(r, a, s = 1) {
|
|
2
|
+
const t = Number.isFinite(a) ? Math.max(0, Math.floor(a)) : 0, o = Number.isFinite(s) ? Math.max(0, Math.floor(s)) : 1, c = l(r, t), e = 2 * o + 5, n = (m, g) => Array.from({ length: g - m + 1 }, (p, u) => m + u);
|
|
3
|
+
if (t <= e) return n(1, t);
|
|
4
|
+
const i = Math.max(c - o, 1), h = Math.min(c + o, t), M = i > 3, f = h < t - 2;
|
|
5
|
+
return M ? f ? [1, "gap-start", ...n(i, h), "gap-end", t] : [1, "gap-start", ...n(t - (e - 3), t)] : [...n(1, e - 2), "gap-end", t];
|
|
6
|
+
}
|
|
7
|
+
const l = (r, a) => Math.min(Math.max(1, Math.floor(r) || 1), Math.max(1, Number.isFinite(a) ? Math.floor(a) : 1));
|
|
8
|
+
export {
|
|
9
|
+
l as clampPage,
|
|
10
|
+
x as pageItems
|
|
11
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),y=require("react"),a=require("@tanstack/react-table"),c=require("../../../node_modules/@fortawesome/react-fontawesome/dist/index.cjs"),g=require("../../../node_modules/@fortawesome/free-solid-svg-icons/index.cjs"),l=require("../../../lib/utils.cjs"),h=require("../../molecules/Pagination/Pagination.cjs"),r=require("../Table/Table.cjs"),T=a.tableFeatures({rowSortingFeature:a.rowSortingFeature,rowPaginationFeature:a.rowPaginationFeature,sortedRowModel:a.createSortedRowModel(),paginatedRowModel:a.createPaginatedRowModel(),sortFns:a.sortFns});function C({columns:i,data:d,className:u,tableClassName:x,paginationClassName:m,variant:p="default",size:f="md",hoverable:j=!1,paginationLabels:o}){const[w,b]=y.useState([]),s=a.useTable({features:T,data:d,columns:i,onSortingChange:b,state:{sorting:w},initialState:{pagination:{pageIndex:0,pageSize:10}}});return e.jsxs("div",{className:l.cn("rst:font-ui rst:flex rst:flex-col rst:gap-4",u),children:[e.jsxs(r.Table,{variant:p,size:f,hoverable:j,className:x,children:[e.jsx(r.TableHeader,{children:s.getHeaderGroups().map(n=>e.jsx(r.TableRow,{children:n.headers.map(t=>e.jsx(r.TableHead,{children:t.isPlaceholder?null:e.jsxs("div",{className:l.cn("rst:flex rst:items-center rst:gap-2 rst:transition-opacity",t.column.getCanSort()&&"rst:cursor-pointer rst:select-none rst:opacity-80 rst:hover:opacity-100"),onClick:t.column.getToggleSortingHandler(),children:[a.flexRender(t.column.columnDef.header,t.getContext()),t.column.getCanSort()&&e.jsx("span",{className:"rst:w-4 rst:flex rst:justify-center rst:text-primary-500",children:t.column.getIsSorted()==="asc"?e.jsx(c.FontAwesomeIcon,{icon:g.faCaretUp}):t.column.getIsSorted()==="desc"?e.jsx(c.FontAwesomeIcon,{icon:g.faCaretDown}):null})]})},t.id))},n.id))}),e.jsx(r.TableBody,{children:s.getRowModel().rows?.length?s.getRowModel().rows.map(n=>e.jsx(r.TableRow,{children:n.getAllCells().map(t=>e.jsx(r.TableCell,{children:a.flexRender(t.column.columnDef.cell,t.getContext())},t.id))},n.id)):e.jsx(r.TableRow,{children:e.jsx(r.TableCell,{colSpan:i.length,className:"rst:h-24 rst:text-center rst:text-gray-500 rst:dark:text-gray-400 rst:italic",children:"No results found."})})})]}),e.jsxs("div",{className:l.cn("rst:flex rst:flex-col rst:sm:flex-row rst:items-center rst:justify-between rst:gap-4 rst:px-2",m),children:[e.jsx("div",{className:"rst:text-sm rst:font-medium rst:text-gray-500 rst:dark:text-gray-400",children:o?.status?o.status(s.state.pagination.pageIndex+1,s.getPageCount()):e.jsxs(e.Fragment,{children:["Page"," ",e.jsx("strong",{className:"rst:text-gray-900 rst:dark:text-gray-100",children:s.state.pagination.pageIndex+1})," ","of"," ",e.jsx("strong",{className:"rst:text-gray-900 rst:dark:text-gray-100",children:s.getPageCount()})]})}),e.jsx(h.Pagination,{layout:"arrows",align:"end",variant:"outline",page:s.state.pagination.pageIndex+1,pageCount:s.getPageCount(),onPageChange:n=>s.setPageIndex(n-1),labels:o})]})]})}exports.DataTable=C;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ColumnDef, RowData } from '@tanstack/react-table';
|
|
2
|
+
import { PaginationLabels } from '../../molecules/Pagination/Pagination';
|
|
2
3
|
import { TableProps } from '../Table/Table';
|
|
3
4
|
/**
|
|
4
5
|
* The feature set DataTable registers: sorting and pagination, plus the row
|
|
@@ -43,6 +44,12 @@ export interface DataTableProps<TData extends RowData> {
|
|
|
43
44
|
variant?: TableProps["variant"];
|
|
44
45
|
size?: TableProps["size"];
|
|
45
46
|
hoverable?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Replaces the pager's words; see Pagination's `labels`. `status` also
|
|
49
|
+
* replaces the "Page N of M" line beside it. ("No results found." is
|
|
50
|
+
* DataTable's own and isn't covered.)
|
|
51
|
+
*/
|
|
52
|
+
paginationLabels?: Partial<PaginationLabels>;
|
|
46
53
|
}
|
|
47
|
-
export declare function DataTable<TData extends RowData>({ columns, data, className, tableClassName, paginationClassName, variant, size, hoverable, }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
54
|
+
export declare function DataTable<TData extends RowData>({ columns, data, className, tableClassName, paginationClassName, variant, size, hoverable, paginationLabels, }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
48
55
|
export {};
|