@prenta/admin 1.17.16 → 1.17.18
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/CHANGELOG.md +12 -0
- package/dist/__tests__/components/virtual-window.test.d.ts +2 -0
- package/dist/__tests__/components/virtual-window.test.d.ts.map +1 -0
- package/dist/__tests__/components/virtual-window.test.js +22 -0
- package/dist/__tests__/components/virtual-window.test.js.map +1 -0
- package/dist/__tests__/views/collection-list-paging.test.d.ts +2 -0
- package/dist/__tests__/views/collection-list-paging.test.d.ts.map +1 -0
- package/dist/__tests__/views/collection-list-paging.test.js +101 -0
- package/dist/__tests__/views/collection-list-paging.test.js.map +1 -0
- package/dist/components/virtual-window.d.ts +28 -0
- package/dist/components/virtual-window.d.ts.map +1 -0
- package/dist/components/virtual-window.js +62 -0
- package/dist/components/virtual-window.js.map +1 -0
- package/dist/prenta-admin.css +1 -1
- package/dist/views/CollectionList.d.ts +13 -0
- package/dist/views/CollectionList.d.ts.map +1 -1
- package/dist/views/CollectionList.js +83 -35
- package/dist/views/CollectionList.js.map +1 -1
- package/dist/views/MediaBrowser.d.ts.map +1 -1
- package/dist/views/MediaBrowser.js +80 -23
- package/dist/views/MediaBrowser.js.map +1 -1
- package/dist/views/Pages/PagesListView.d.ts.map +1 -1
- package/dist/views/Pages/PagesListView.js +35 -2
- package/dist/views/Pages/PagesListView.js.map +1 -1
- package/dist/views/Posts/PostsListView.d.ts.map +1 -1
- package/dist/views/Posts/PostsListView.js +14 -2
- package/dist/views/Posts/PostsListView.js.map +1 -1
- package/package.json +7 -6
- package/src/__tests__/components/virtual-window.test.tsx +29 -0
- package/src/__tests__/views/collection-list-paging.test.tsx +112 -0
- package/src/components/virtual-window.tsx +81 -0
- package/src/views/CollectionList.tsx +116 -41
- package/src/views/MediaBrowser.tsx +155 -90
- package/src/views/Pages/PagesListView.tsx +67 -27
- package/src/views/Posts/PostsListView.tsx +29 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @actuate-media/cms-admin
|
|
2
2
|
|
|
3
|
+
## 1.17.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- be0b1a3: Window the media browser and the page, post, and collection tables so a long list mounts only the visible rows.
|
|
8
|
+
|
|
9
|
+
## 1.17.17
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 7583be2: Page the collection list with the keyset cursor instead of an offset page number.
|
|
14
|
+
|
|
3
15
|
## 1.17.16
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-window.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/components/virtual-window.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { useRef } from 'react';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { render, screen } from '@testing-library/react';
|
|
6
|
+
import { useVirtualWindow } from '../../components/virtual-window.js';
|
|
7
|
+
function Probe({ count, height }) {
|
|
8
|
+
const scrollRef = useRef(null);
|
|
9
|
+
const windowed = useVirtualWindow({ count, scrollRef, estimateSize: 40, overscan: 2 });
|
|
10
|
+
return (_jsxs("div", { ref: scrollRef, style: { height, overflow: 'auto' }, children: [_jsx("span", { "data-testid": "rendered", children: windowed.rows.length }), windowed.rows.map((row) => (_jsxs("div", { children: ["row ", row.index] }, row.key)))] }));
|
|
11
|
+
}
|
|
12
|
+
describe('useVirtualWindow', () => {
|
|
13
|
+
it('mounts a window of a 1k-row list instead of every row', () => {
|
|
14
|
+
render(_jsx(Probe, { count: 1000, height: 200 }));
|
|
15
|
+
const rendered = Number(screen.getByTestId('rendered').textContent);
|
|
16
|
+
expect(rendered).toBeGreaterThan(0);
|
|
17
|
+
expect(rendered).toBeLessThan(40);
|
|
18
|
+
expect(screen.getByText('row 0')).toBeTruthy();
|
|
19
|
+
expect(screen.queryByText('row 999')).toBeNull();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=virtual-window.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-window.test.js","sourceRoot":"","sources":["../../../src/__tests__/components/virtual-window.test.tsx"],"names":[],"mappings":";AAAA,gCAAgC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAA;AAErE,SAAS,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAqC;IACjE,MAAM,SAAS,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAC9C,MAAM,QAAQ,GAAG,gBAAgB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAA;IACtF,OAAO,CACL,eAAK,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,aACtD,8BAAkB,UAAU,YAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAQ,EACzD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAC1B,kCAAwB,GAAG,CAAC,KAAK,KAAvB,GAAG,CAAC,GAAG,CAAuB,CACzC,CAAC,IACE,CACP,CAAA;AACH,CAAC;AAED,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;QAC/D,MAAM,CAAC,KAAC,KAAK,IAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAI,CAAC,CAAA;QAC3C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,CAAA;QACnE,MAAM,CAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;QACnC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;QACjC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;QAC9C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IAClD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-list-paging.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/views/collection-list-paging.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
5
|
+
import { buildCollectionListUrl } from '../../views/CollectionList.js';
|
|
6
|
+
/**
|
|
7
|
+
* Collection list pages with the keyset cursor from `listDocuments`, not
|
|
8
|
+
* OFFSET `page`. Deep pages of a large collection must not send `skip`.
|
|
9
|
+
*/
|
|
10
|
+
const seen = [];
|
|
11
|
+
vi.mock('../../lib/api.js', () => ({
|
|
12
|
+
cmsApi: vi.fn(async () => ({ data: {}, status: 200 })),
|
|
13
|
+
ensureCsrfToken: vi.fn(async () => { }),
|
|
14
|
+
}));
|
|
15
|
+
vi.mock('../../lib/useApiData.js', () => ({
|
|
16
|
+
useApiData: (endpoint) => {
|
|
17
|
+
seen.push(endpoint);
|
|
18
|
+
const cursor = new URL(`http://localhost${endpoint}`).searchParams.get('cursor');
|
|
19
|
+
return {
|
|
20
|
+
data: {
|
|
21
|
+
docs: [
|
|
22
|
+
{
|
|
23
|
+
id: '1',
|
|
24
|
+
title: 'Hello',
|
|
25
|
+
status: 'DRAFT',
|
|
26
|
+
updatedAt: '2026-01-01T00:00:00Z',
|
|
27
|
+
data: { title: 'Hello' },
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
total: 60,
|
|
31
|
+
nextCursor: cursor ? null : 'cursor-2',
|
|
32
|
+
},
|
|
33
|
+
loading: false,
|
|
34
|
+
error: null,
|
|
35
|
+
refetch: vi.fn(),
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
}));
|
|
39
|
+
const CONFIG = {
|
|
40
|
+
collections: {
|
|
41
|
+
posts: {
|
|
42
|
+
slug: 'posts',
|
|
43
|
+
labels: { singular: 'Post', plural: 'Posts' },
|
|
44
|
+
fields: { title: { type: 'text', label: 'Title' } },
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
beforeEach(() => {
|
|
49
|
+
seen.length = 0;
|
|
50
|
+
});
|
|
51
|
+
describe('buildCollectionListUrl', () => {
|
|
52
|
+
it('omits OFFSET page and sends the keyset cursor', () => {
|
|
53
|
+
const first = buildCollectionListUrl({
|
|
54
|
+
collectionSlug: 'posts',
|
|
55
|
+
pick: 'title,slug',
|
|
56
|
+
cursor: null,
|
|
57
|
+
search: '',
|
|
58
|
+
sort: null,
|
|
59
|
+
order: 'asc',
|
|
60
|
+
filters: {},
|
|
61
|
+
});
|
|
62
|
+
const params = new URL(`http://localhost${first}`).searchParams;
|
|
63
|
+
expect(params.get('page')).toBeNull();
|
|
64
|
+
expect(params.get('pageSize')).toBe('25');
|
|
65
|
+
expect(params.get('cursor')).toBeNull();
|
|
66
|
+
expect(params.get('pick')).toBe('title,slug');
|
|
67
|
+
const next = buildCollectionListUrl({
|
|
68
|
+
collectionSlug: 'posts',
|
|
69
|
+
pick: 'title,slug',
|
|
70
|
+
cursor: 'doc-25',
|
|
71
|
+
search: 'hello',
|
|
72
|
+
sort: 'updatedAt',
|
|
73
|
+
order: 'desc',
|
|
74
|
+
filters: { status: 'PUBLISHED' },
|
|
75
|
+
});
|
|
76
|
+
const nextParams = new URL(`http://localhost${next}`).searchParams;
|
|
77
|
+
expect(nextParams.get('page')).toBeNull();
|
|
78
|
+
expect(nextParams.get('cursor')).toBe('doc-25');
|
|
79
|
+
expect(nextParams.get('search')).toBe('hello');
|
|
80
|
+
expect(nextParams.get('sort')).toBe('updatedAt');
|
|
81
|
+
expect(nextParams.get('order')).toBe('desc');
|
|
82
|
+
expect(nextParams.get('filter.status')).toBe('PUBLISHED');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('CollectionList paging', () => {
|
|
86
|
+
it('requests the next page with nextCursor and returns without an offset', async () => {
|
|
87
|
+
const { CollectionList } = await import('../../views/CollectionList.js');
|
|
88
|
+
render(_jsx(CollectionList, { collectionSlug: "posts", config: CONFIG, onNavigate: vi.fn() }));
|
|
89
|
+
const first = seen[seen.length - 1] ?? '';
|
|
90
|
+
expect(new URL(`http://localhost${first}`).searchParams.get('page')).toBeNull();
|
|
91
|
+
fireEvent.click(screen.getByRole('button', { name: 'Next' }));
|
|
92
|
+
const afterNext = seen[seen.length - 1] ?? '';
|
|
93
|
+
expect(new URL(`http://localhost${afterNext}`).searchParams.get('cursor')).toBe('cursor-2');
|
|
94
|
+
expect(screen.getByText('Page 2 of 3')).toBeTruthy();
|
|
95
|
+
fireEvent.click(screen.getByRole('button', { name: 'Previous' }));
|
|
96
|
+
const afterPrev = seen[seen.length - 1] ?? '';
|
|
97
|
+
expect(new URL(`http://localhost${afterPrev}`).searchParams.get('cursor')).toBeNull();
|
|
98
|
+
expect(screen.getByText('Page 1 of 3')).toBeTruthy();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
//# sourceMappingURL=collection-list-paging.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection-list-paging.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/collection-list-paging.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type RefObject } from 'react';
|
|
2
|
+
export interface VirtualWindowRow {
|
|
3
|
+
index: number;
|
|
4
|
+
key: string | number | bigint;
|
|
5
|
+
start: number;
|
|
6
|
+
size: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Window of row indexes for a scroll parent. A measured scroller mounts only
|
|
10
|
+
* the visible range plus overscan. A shell with no layout height (admin
|
|
11
|
+
* render tests) still windows a long list against the initial viewport, and
|
|
12
|
+
* mounts a short list in full so those tests keep finding every row (#422).
|
|
13
|
+
*/
|
|
14
|
+
export declare function useVirtualWindow(options: {
|
|
15
|
+
count: number;
|
|
16
|
+
scrollRef: RefObject<HTMLElement | null>;
|
|
17
|
+
estimateSize: number;
|
|
18
|
+
overscan?: number;
|
|
19
|
+
}): {
|
|
20
|
+
rows: VirtualWindowRow[];
|
|
21
|
+
paddingTop: number;
|
|
22
|
+
paddingBottom: number;
|
|
23
|
+
};
|
|
24
|
+
export declare function VirtualTablePadding({ height, columns }: {
|
|
25
|
+
height: number;
|
|
26
|
+
columns: number;
|
|
27
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
28
|
+
//# sourceMappingURL=virtual-window.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-window.d.ts","sourceRoot":"","sources":["../../src/components/virtual-window.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAGnD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;CACb;AAYD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IACxC,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG;IAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAwC1E;AAED,wBAAgB,mBAAmB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,kDAO3F"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
4
|
+
const INITIAL_VIEWPORT = 640;
|
|
5
|
+
function rowsInRange(start, end, estimateSize) {
|
|
6
|
+
const rows = [];
|
|
7
|
+
for (let index = start; index < end; index++) {
|
|
8
|
+
rows.push({ index, key: index, start: index * estimateSize, size: estimateSize });
|
|
9
|
+
}
|
|
10
|
+
return rows;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Window of row indexes for a scroll parent. A measured scroller mounts only
|
|
14
|
+
* the visible range plus overscan. A shell with no layout height (admin
|
|
15
|
+
* render tests) still windows a long list against the initial viewport, and
|
|
16
|
+
* mounts a short list in full so those tests keep finding every row (#422).
|
|
17
|
+
*/
|
|
18
|
+
export function useVirtualWindow(options) {
|
|
19
|
+
const { count, scrollRef, estimateSize, overscan = 8 } = options;
|
|
20
|
+
const getScrollElement = useCallback(() => scrollRef.current, [scrollRef]);
|
|
21
|
+
const estimate = useCallback(() => estimateSize, [estimateSize]);
|
|
22
|
+
const virtualizer = useVirtualizer({
|
|
23
|
+
count,
|
|
24
|
+
getScrollElement,
|
|
25
|
+
estimateSize: estimate,
|
|
26
|
+
overscan,
|
|
27
|
+
initialRect: { width: 1024, height: 640 },
|
|
28
|
+
});
|
|
29
|
+
const items = virtualizer.getVirtualItems();
|
|
30
|
+
// Zero-height shells (happy-dom) report an empty range. Short lists stay
|
|
31
|
+
// fully mounted. A 1k-row list still windows against the initial viewport
|
|
32
|
+
// so the first paint does not build a node per row.
|
|
33
|
+
if (items.length === 0) {
|
|
34
|
+
if (count === 0 || count * estimateSize <= INITIAL_VIEWPORT) {
|
|
35
|
+
return { rows: rowsInRange(0, count, estimateSize), paddingTop: 0, paddingBottom: 0 };
|
|
36
|
+
}
|
|
37
|
+
const end = Math.min(count, Math.ceil(INITIAL_VIEWPORT / estimateSize) + overscan);
|
|
38
|
+
return {
|
|
39
|
+
rows: rowsInRange(0, end, estimateSize),
|
|
40
|
+
paddingTop: 0,
|
|
41
|
+
paddingBottom: Math.max(0, count * estimateSize - end * estimateSize),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const first = items[0];
|
|
45
|
+
const last = items[items.length - 1];
|
|
46
|
+
return {
|
|
47
|
+
rows: items.map((item) => ({
|
|
48
|
+
index: item.index,
|
|
49
|
+
key: item.key,
|
|
50
|
+
start: item.start,
|
|
51
|
+
size: item.size,
|
|
52
|
+
})),
|
|
53
|
+
paddingTop: first.start,
|
|
54
|
+
paddingBottom: Math.max(0, virtualizer.getTotalSize() - last.end),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function VirtualTablePadding({ height, columns }) {
|
|
58
|
+
if (height <= 0)
|
|
59
|
+
return null;
|
|
60
|
+
return (_jsx("tr", { "aria-hidden": "true", children: _jsx("td", { colSpan: columns, style: { height, padding: 0, border: 0 } }) }));
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=virtual-window.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-window.js","sourceRoot":"","sources":["../../src/components/virtual-window.tsx"],"names":[],"mappings":"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"}
|