@izumisy-tailor/tailor-data-viewer 0.2.28 → 0.2.30
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
|
@@ -121,7 +121,7 @@ export function useCollection(
|
|
|
121
121
|
// ---------------------------------------------------------------------------
|
|
122
122
|
const [filters, setFiltersState] = useState<Filter[]>(initialFilters);
|
|
123
123
|
const [sortStates, setSortStates] = useState<SortState[]>(initialSort);
|
|
124
|
-
const [pageSize] = useState(initialPageSize);
|
|
124
|
+
const [pageSize, setPageSizeState] = useState(initialPageSize);
|
|
125
125
|
const [cursor, setCursor] = useState<string | null>(null);
|
|
126
126
|
const [paginationDirection, setPaginationDirection] = useState<
|
|
127
127
|
"forward" | "backward"
|
|
@@ -233,6 +233,13 @@ export function useCollection(
|
|
|
233
233
|
setCurrentPage(1);
|
|
234
234
|
}, []);
|
|
235
235
|
|
|
236
|
+
const setPageSize = useCallback((size: number) => {
|
|
237
|
+
setPageSizeState(size);
|
|
238
|
+
setCursor(null);
|
|
239
|
+
setPaginationDirection("forward");
|
|
240
|
+
setCurrentPage(1);
|
|
241
|
+
}, []);
|
|
242
|
+
|
|
236
243
|
const setPageInfo = useCallback((pageInfo: PageInfo) => {
|
|
237
244
|
setCurrentPageInfo(pageInfo);
|
|
238
245
|
}, []);
|
|
@@ -324,6 +331,7 @@ export function useCollection(
|
|
|
324
331
|
setSort,
|
|
325
332
|
clearSort,
|
|
326
333
|
pageSize,
|
|
334
|
+
setPageSize,
|
|
327
335
|
cursor,
|
|
328
336
|
paginationDirection,
|
|
329
337
|
nextPage,
|
|
@@ -210,4 +210,73 @@ describe("Pagination", () => {
|
|
|
210
210
|
expect(() => render(<Pagination />)).toThrow();
|
|
211
211
|
console.error = globalThis.console.error;
|
|
212
212
|
});
|
|
213
|
+
|
|
214
|
+
// ===========================================================================
|
|
215
|
+
// Page size switcher
|
|
216
|
+
// ===========================================================================
|
|
217
|
+
|
|
218
|
+
it("does not render page-size selector when pageSizeOptions is not provided", () => {
|
|
219
|
+
render(
|
|
220
|
+
<TestProviders>
|
|
221
|
+
<Pagination />
|
|
222
|
+
</TestProviders>,
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
expect(screen.queryByLabelText("Rows per page")).not.toBeInTheDocument();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("renders page-size selector when pageSizeOptions is provided", () => {
|
|
229
|
+
render(
|
|
230
|
+
<TestProviders collection={{ pageSize: 20 }}>
|
|
231
|
+
<Pagination pageSizeOptions={[10, 20, 50]} />
|
|
232
|
+
</TestProviders>,
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
const select = screen.getByLabelText("Rows per page");
|
|
236
|
+
expect(select).toBeInTheDocument();
|
|
237
|
+
expect(select).toHaveValue("20");
|
|
238
|
+
|
|
239
|
+
const options = select.querySelectorAll("option");
|
|
240
|
+
expect(options).toHaveLength(3);
|
|
241
|
+
expect(options[0]).toHaveValue("10");
|
|
242
|
+
expect(options[1]).toHaveValue("20");
|
|
243
|
+
expect(options[2]).toHaveValue("50");
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("calls setPageSize when page-size option is changed", () => {
|
|
247
|
+
const setPageSize = vi.fn();
|
|
248
|
+
render(
|
|
249
|
+
<TestProviders collection={{ pageSize: 20, setPageSize }}>
|
|
250
|
+
<Pagination pageSizeOptions={[10, 20, 50]} />
|
|
251
|
+
</TestProviders>,
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
fireEvent.change(screen.getByLabelText("Rows per page"), {
|
|
255
|
+
target: { value: "50" },
|
|
256
|
+
});
|
|
257
|
+
expect(setPageSize).toHaveBeenCalledWith(50);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it("supports custom rowsPerPage label", () => {
|
|
261
|
+
render(
|
|
262
|
+
<TestProviders collection={{ pageSize: 20 }}>
|
|
263
|
+
<Pagination
|
|
264
|
+
pageSizeOptions={[10, 20, 50]}
|
|
265
|
+
labels={{ rowsPerPage: "表示件数" }}
|
|
266
|
+
/>
|
|
267
|
+
</TestProviders>,
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
expect(screen.getByLabelText("表示件数")).toBeInTheDocument();
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("does not render page-size selector when pageSizeOptions is empty", () => {
|
|
274
|
+
render(
|
|
275
|
+
<TestProviders>
|
|
276
|
+
<Pagination pageSizeOptions={[]} />
|
|
277
|
+
</TestProviders>,
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
expect(screen.queryByLabelText("Rows per page")).not.toBeInTheDocument();
|
|
281
|
+
});
|
|
213
282
|
});
|
|
@@ -86,11 +86,23 @@ export interface PaginationLabels {
|
|
|
86
86
|
previous?: string;
|
|
87
87
|
next?: string;
|
|
88
88
|
last?: string;
|
|
89
|
+
/** Label displayed next to the page-size selector (default: "Rows per page"). */
|
|
90
|
+
rowsPerPage?: string;
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
export interface PaginationProps {
|
|
92
94
|
/** Aria-labels for pagination buttons (defaults to English). */
|
|
93
95
|
labels?: PaginationLabels;
|
|
96
|
+
/**
|
|
97
|
+
* Available page-size options shown in a dropdown selector.
|
|
98
|
+
* When provided, a page-size switcher is rendered.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```tsx
|
|
102
|
+
* <Pagination pageSizeOptions={[10, 20, 50, 100]} />
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
pageSizeOptions?: number[];
|
|
94
106
|
}
|
|
95
107
|
|
|
96
108
|
const btnClass =
|
|
@@ -113,7 +125,7 @@ const btnClass =
|
|
|
113
125
|
* </DataTable.Provider>
|
|
114
126
|
* ```
|
|
115
127
|
*/
|
|
116
|
-
export function Pagination({ labels }: PaginationProps = {}) {
|
|
128
|
+
export function Pagination({ labels, pageSizeOptions }: PaginationProps = {}) {
|
|
117
129
|
const { pageInfo } = useDataTableContext();
|
|
118
130
|
const {
|
|
119
131
|
nextPage,
|
|
@@ -124,15 +136,40 @@ export function Pagination({ labels }: PaginationProps = {}) {
|
|
|
124
136
|
totalPages,
|
|
125
137
|
goToFirstPage,
|
|
126
138
|
goToLastPage,
|
|
139
|
+
pageSize,
|
|
140
|
+
setPageSize,
|
|
127
141
|
} = useCollectionContext();
|
|
128
142
|
|
|
129
143
|
const firstLabel = labels?.first ?? "First page";
|
|
130
144
|
const previousLabel = labels?.previous ?? "Previous page";
|
|
131
145
|
const nextLabel = labels?.next ?? "Next page";
|
|
132
146
|
const lastLabel = labels?.last ?? "Last page";
|
|
147
|
+
const rowsPerPageLabel = labels?.rowsPerPage ?? "Rows per page";
|
|
133
148
|
|
|
134
149
|
return (
|
|
135
150
|
<div className="flex items-center justify-end gap-2 py-2">
|
|
151
|
+
{pageSizeOptions && pageSizeOptions.length > 0 && (
|
|
152
|
+
<div className="flex items-center gap-1.5">
|
|
153
|
+
<label
|
|
154
|
+
htmlFor="pagination-page-size"
|
|
155
|
+
className="text-sm text-muted-foreground whitespace-nowrap"
|
|
156
|
+
>
|
|
157
|
+
{rowsPerPageLabel}
|
|
158
|
+
</label>
|
|
159
|
+
<select
|
|
160
|
+
id="pagination-page-size"
|
|
161
|
+
className="h-8 rounded-md border bg-transparent px-2 text-sm"
|
|
162
|
+
value={pageSize}
|
|
163
|
+
onChange={(e) => setPageSize(Number(e.target.value))}
|
|
164
|
+
>
|
|
165
|
+
{pageSizeOptions.map((size) => (
|
|
166
|
+
<option key={size} value={size}>
|
|
167
|
+
{size}
|
|
168
|
+
</option>
|
|
169
|
+
))}
|
|
170
|
+
</select>
|
|
171
|
+
</div>
|
|
172
|
+
)}
|
|
136
173
|
{totalPages !== null && (
|
|
137
174
|
<span className="text-sm text-muted-foreground tabular-nums">
|
|
138
175
|
{currentPage} / {totalPages}
|
package/src/component/table.tsx
CHANGED
|
@@ -12,7 +12,8 @@ interface TableRootProps extends ComponentProps<"table"> {
|
|
|
12
12
|
|
|
13
13
|
function Root({ className, tableLayout = "fixed", ...props }: TableRootProps) {
|
|
14
14
|
return (
|
|
15
|
-
|
|
15
|
+
/* TODO: bg-card should be something specific (bg-table?) */
|
|
16
|
+
<div className="relative w-full overflow-x-auto rounded-md border bg-card">
|
|
16
17
|
<table
|
|
17
18
|
className={cn(
|
|
18
19
|
"w-full caption-bottom text-sm",
|
package/src/component/types.ts
CHANGED
|
@@ -463,6 +463,8 @@ export interface UseCollectionReturn<
|
|
|
463
463
|
// Pagination operations
|
|
464
464
|
/** Number of items per page */
|
|
465
465
|
pageSize: number;
|
|
466
|
+
/** Update the number of items per page (resets pagination to page 1) */
|
|
467
|
+
setPageSize: (size: number) => void;
|
|
466
468
|
/** Current cursor position */
|
|
467
469
|
cursor: string | null;
|
|
468
470
|
/** Current pagination direction */
|