@elliemae/ds-pagination 3.70.0-next.2 → 3.70.0-next.4

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,10 +1,11 @@
1
1
  {
2
2
  "name": "@elliemae/ds-pagination",
3
- "version": "3.70.0-next.2",
3
+ "version": "3.70.0-next.4",
4
4
  "license": "MIT",
5
5
  "description": "ICE MT - Dimsum - Pagination",
6
6
  "files": [
7
- "dist"
7
+ "dist",
8
+ "skills"
8
9
  ],
9
10
  "module": "./dist/esm/index.js",
10
11
  "main": "./dist/cjs/index.js",
@@ -37,22 +38,22 @@
37
38
  },
38
39
  "dependencies": {
39
40
  "@xstyled/system": "~3.8.1",
40
- "@elliemae/ds-button-v2": "3.70.0-next.2",
41
- "@elliemae/ds-dropdownmenu-v2": "3.70.0-next.2",
42
- "@elliemae/ds-circular-progress-indicator": "3.70.0-next.2",
43
- "@elliemae/ds-grid": "3.70.0-next.2",
44
- "@elliemae/ds-icons": "3.70.0-next.2",
45
- "@elliemae/ds-system": "3.70.0-next.2",
46
- "@elliemae/ds-typescript-helpers": "3.70.0-next.2",
47
- "@elliemae/ds-typography": "3.70.0-next.2",
48
- "@elliemae/ds-props-helpers": "3.70.0-next.2"
41
+ "@elliemae/ds-circular-progress-indicator": "3.70.0-next.4",
42
+ "@elliemae/ds-button-v2": "3.70.0-next.4",
43
+ "@elliemae/ds-dropdownmenu-v2": "3.70.0-next.4",
44
+ "@elliemae/ds-props-helpers": "3.70.0-next.4",
45
+ "@elliemae/ds-system": "3.70.0-next.4",
46
+ "@elliemae/ds-grid": "3.70.0-next.4",
47
+ "@elliemae/ds-icons": "3.70.0-next.4",
48
+ "@elliemae/ds-typography": "3.70.0-next.4",
49
+ "@elliemae/ds-typescript-helpers": "3.70.0-next.4"
49
50
  },
50
51
  "devDependencies": {
51
52
  "jest": "^30.0.0",
52
53
  "styled-components": "~5.3.9",
53
54
  "styled-system": "^5.1.5",
54
- "@elliemae/ds-monorepo-devops": "3.70.0-next.2",
55
- "@elliemae/ds-test-utils": "3.70.0-next.2"
55
+ "@elliemae/ds-monorepo-devops": "3.70.0-next.4",
56
+ "@elliemae/ds-test-utils": "3.70.0-next.4"
56
57
  },
57
58
  "peerDependencies": {
58
59
  "@testing-library/react": "^16.0.1",
@@ -0,0 +1,117 @@
1
+ ---
2
+ name: ds-pagination-health-check
3
+ description: >
4
+ Audit the current state of a @elliemae/ds-pagination implementation. Use before starting
5
+ a task that depends on pagination, to verify a foundation before building on it, or when
6
+ diagnosing unexpected behavior. Produces a complete state report: what is correct and sound,
7
+ what requires fixing, what is suboptimal, and what gaps may affect the current task.
8
+ type: health-check
9
+ library: ds-pagination
10
+ library_version: '3.60.0'
11
+ requires:
12
+ - ds-pagination-setup
13
+ - ds-pagination-slots
14
+ ---
15
+
16
+ ## Purpose
17
+
18
+ This skill audits an existing `@elliemae/ds-pagination` integration. It is not a setup guide. It tells you the current state of a pagination implementation that already exists.
19
+
20
+ **Use it:**
21
+
22
+ - Before starting a task that involves pagination — to understand what you are about to touch
23
+ - Before making pagination load-bearing for a new feature — to verify the foundation
24
+ - When pagination is behaving unexpectedly — to surface what the implementation gets wrong
25
+
26
+ ---
27
+
28
+ ## Load the embedded knowledge
29
+
30
+ Load the following skills **as reference knowledge only**. You are reading their embedded understanding of correct patterns — their Common Mistakes, mandatory props, and OOB-first guidance become the diagnostic lens. You are not running them as tasks.
31
+
32
+ - `ds-pagination-setup` — required props, state management, server-side vs client-side model, deprecated API, pageIndex reset
33
+ - `ds-pagination-slots` — slot props have no effect on most pagination primitives in current version; standard HTML props work as the workaround
34
+
35
+ ---
36
+
37
+ ## Procedure
38
+
39
+ ### Step 1 — Locate and read the implementation
40
+
41
+ Find every file where pagination primitives from `@elliemae/ds-pagination` are rendered. For each instance:
42
+
43
+ - Record which primitives are used: `DSPaginationContainer`, `DSPaginator`, `DSPagePrevButton`, `DSPageNextButton`, `DSPerPageSelector`, `DSPaginationSeparator`
44
+ - Record whether the monolithic `DSPagination` (deprecated) is used instead
45
+ - Read where pagination state lives (`pageIndex`, `pageSize`, `pageCount`) — state manager, store, atoms, or `useState`
46
+ - Read every callback handler (`onPageChange`, `onPreviousPage`, `onNextPage`, `onPageSizeChange`)
47
+ - Check whether `isLoadingPageCount` is used where `pageCount` may be async
48
+ - Check whether `TablePagination` (or equivalent) is defined at module level
49
+ - Check what `data` is passed to the consuming DataTable — full dataset or current page slice
50
+
51
+ ### Step 2 — Apply diagnostic checks
52
+
53
+ **CRITICAL** — prevents correct function; fix before proceeding
54
+ **HIGH** — meaningful risk; should fix
55
+ **MEDIUM** — suboptimal; worth addressing
56
+ **SOUND** — correct; rely on it
57
+
58
+ #### Assembly checks
59
+
60
+ - [ ] Composable parts are used — not the deprecated monolithic `DSPagination` component
61
+ - [ ] `TablePagination` (or equivalent component) is defined at module level — not inside another component body
62
+ - [ ] `data` passed to any consuming DataTable is the current page slice — DataTable renders what it receives
63
+
64
+ #### State management checks
65
+
66
+ - [ ] `pageIndex`, `pageSize`, `pageCount` live in the project's state manager — not `useState`
67
+ - [ ] No `useEffect` watching pagination state to dispatch API calls — consequences belong inside the callbacks
68
+ - [ ] `pageIndex` resets to 1 inside `onPageSizeChange` — not doing so leaves users on a non-existent page
69
+
70
+ #### Loading state checks
71
+
72
+ - [ ] `isLoadingPageCount={true}` is used when `pageCount` is async — absence renders `0` or broken state
73
+ - [ ] `isLoadingPageCount` and `pageCount ?? 0` are treated as independent concerns — the `?? 0` is a null-safety guard, not a spinner trigger
74
+
75
+ #### Memoization checks
76
+
77
+ - [ ] `onPageChange`, `onPreviousPage`, `onNextPage`, `onPageSizeChange` are wrapped in `useCallback`
78
+ - [ ] `perPageOptions` is stable (`useMemo` if constructed inline)
79
+ - [ ] `pageDetails` is stable (`useMemo` if constructed inline)
80
+
81
+ #### Deprecated API check
82
+
83
+ - [ ] Capital-P `Pagination` render prop is used where DataTable integration is present — not deprecated lowercase `pagination` prop
84
+
85
+ #### Pagination model check
86
+
87
+ - [ ] Every page or size change dispatches an API call — client-side array slicing is only acceptable as a temporary, explicitly owned workaround with a documented remediation plan
88
+
89
+ ### Step 3 — Produce the state report
90
+
91
+ **Foundation — what is correct and sound**
92
+ What the implementation gets right. Be specific — this is what you can rely on.
93
+
94
+ **Critical issues — fix before proceeding**
95
+ Each item with file, location, and pointer to the `ds-pagination-setup` skill section covering the fix.
96
+
97
+ **Warnings — should address, not blocking**
98
+ Each item with context on the risk.
99
+
100
+ **Awareness — no action needed, good to know**
101
+ Suboptimal patterns that are not breaking.
102
+
103
+ **Gaps relevant to this task**
104
+ What the current task will require that is not yet present in the implementation.
105
+
106
+ ---
107
+
108
+ ## What this skill does NOT do
109
+
110
+ - It does not generate or modify code
111
+ - It does not run the setup skill as a task
112
+ - It does not replace human judgment on trade-offs
113
+
114
+ ## When this isn't enough
115
+
116
+ **ICE internal:** Microsoft Teams — Dimsum channel (informal) / Jira Dimsum board (formal)
117
+ **Partners:** Your organization's Dimsum point of contact
@@ -0,0 +1,322 @@
1
+ ---
2
+ name: ds-pagination-setup
3
+ description: >
4
+ Composable pagination bar assembly for @elliemae/ds-pagination. DSPaginationContainer,
5
+ DSPaginator, DSPagePrevButton, DSPageNextButton, DSPerPageSelector, DSPaginationSeparator.
6
+ State (pageIndex, pageSize, pageCount) in project state manager — not useState. isLoadingPageCount
7
+ on DSPaginator for async page count. DSPagination (monolithic) is the legacy API — never use.
8
+ pageIndex resets to 1 on pageSize change.
9
+ type: core
10
+ library: ds-pagination
11
+ library_version: '3.60.0'
12
+ sources:
13
+ - '@elliemae/ds-pagination:dist/types/react-desc-prop-types.d.ts'
14
+ - '@elliemae/ds-pagination:dist/types/parts/DSPaginator/react-desc-prop-types.d.ts'
15
+ - '@elliemae/ds-pagination:dist/types/parts/DSPerPageSelector/react-desc-prop-types.d.ts'
16
+ ---
17
+
18
+ ## Setup
19
+
20
+ Define `PaginationBar` at module level — never inside another component. Read pagination state from the project's state manager. The most common stacks in ICE codebases, in order of prevalence: RTK (Redux Toolkit), vanilla Redux, Redux-Saga (pre-RTK codebases), and other solutions that need to be discovered before writing any state shape.
21
+
22
+ **On pagination model — ideal vs current reality:** The correct long-term model is server-side pagination: every page or size change dispatches an API call, and the backend returns only the requested slice. This is how `DSPagination` is meant to be used. If the current backend does not yet support paginated endpoints and an in-memory slice is the temporary reality, that is a legitimate constraint — not something to pretend away. If that is the situation: surface it explicitly, confirm the team understands the tradeoff, verify there is a documented remediation plan to move to server-side when backend support is available, and proceed. A deliberate, owned compromise is different from an unexamined shortcut. The example below shows the server-side model — if adapting to an in-memory slice, the `fetchPage` dispatches become local slice operations, and the team explicitly owns the data freshness and memory cost implications.
23
+
24
+ ```jsx
25
+ import {
26
+ DSPageNextButton,
27
+ DSPagePrevButton,
28
+ DSPaginationContainer,
29
+ DSPaginationSeparator,
30
+ DSPaginator,
31
+ DSPerPageSelector,
32
+ } from '@elliemae/ds-pagination';
33
+
34
+ const PaginationBar = () => {
35
+ const { pageIndex, pageSize, pageCount } = useSelector(selectPaginationState);
36
+ const dispatch = useDispatch();
37
+
38
+ const onPreviousPage = useCallback(() => {
39
+ dispatch(fetchPage({ page: pageIndex - 1, pageSize }));
40
+ }, [dispatch, pageIndex, pageSize]);
41
+
42
+ const onNextPage = useCallback(() => {
43
+ dispatch(fetchPage({ page: pageIndex + 1, pageSize }));
44
+ }, [dispatch, pageIndex, pageSize]);
45
+
46
+ const onPageChange = useCallback(
47
+ (idx) => {
48
+ dispatch(fetchPage({ page: idx, pageSize }));
49
+ },
50
+ [dispatch, pageSize],
51
+ );
52
+
53
+ const onPageSizeChange = useCallback(
54
+ (newPageSize) => {
55
+ dispatch(setPageSize(newPageSize));
56
+ dispatch(setPageIndex(1));
57
+ dispatch(fetchPage({ page: 1, pageSize: newPageSize }));
58
+ },
59
+ [dispatch],
60
+ );
61
+
62
+ return (
63
+ <DSPaginationContainer>
64
+ <DSPerPageSelector pageSize={pageSize} onPageSizeChange={onPageSizeChange} />
65
+ <DSPaginationSeparator mr={24} />
66
+ <DSPagePrevButton canPreviousPage={pageIndex !== 1} onPreviousPage={onPreviousPage} />
67
+ <DSPaginationSeparator />
68
+ <DSPaginator pageCount={pageCount} pageIndex={pageIndex} onPageChange={onPageChange} />
69
+ <DSPaginationSeparator />
70
+ <DSPageNextButton canNextPage={pageIndex !== pageCount} onNextPage={onNextPage} />
71
+ </DSPaginationContainer>
72
+ );
73
+ };
74
+ ```
75
+
76
+ ## Core Patterns
77
+
78
+ ### Basic prev/page/next bar (no per-page selector)
79
+
80
+ ```jsx
81
+ const PaginationBar = () => {
82
+ const { pageIndex, pageCount } = useSelector(selectPaginationState);
83
+ const dispatch = useDispatch();
84
+ const onPreviousPage = useCallback(() => dispatch(fetchPage({ page: pageIndex - 1 })), [dispatch, pageIndex]);
85
+ const onPageChange = useCallback((idx) => dispatch(fetchPage({ page: idx })), [dispatch]);
86
+ const onNextPage = useCallback(() => dispatch(fetchPage({ page: pageIndex + 1 })), [dispatch, pageIndex]);
87
+
88
+ return (
89
+ <DSPaginationContainer>
90
+ <DSPagePrevButton canPreviousPage={pageIndex !== 1} onPreviousPage={onPreviousPage} />
91
+ <DSPaginationSeparator />
92
+ <DSPaginator pageCount={pageCount} pageIndex={pageIndex} onPageChange={onPageChange} />
93
+ <DSPaginationSeparator />
94
+ <DSPageNextButton canNextPage={pageIndex !== pageCount} onNextPage={onNextPage} />
95
+ </DSPaginationContainer>
96
+ );
97
+ };
98
+ ```
99
+
100
+ ### Async page count with isLoadingPageCount
101
+
102
+ `isLoadingPageCount={true}` shows a spinner in `DSPaginator` instead of the page picker. While loading, also guard `canPreviousPage` and `canNextPage` — the total page count is unknown so navigation should be disabled.
103
+
104
+ ```jsx
105
+ <DSPagePrevButton canPreviousPage={!isPageCountLoading && pageIndex !== 1} onPreviousPage={onPreviousPage} />
106
+ <DSPaginationSeparator />
107
+ <DSPaginator
108
+ pageCount={pageCount}
109
+ isLoadingPageCount={isPageCountLoading}
110
+ pageIndex={pageIndex}
111
+ onPageChange={onPageChange}
112
+ />
113
+ <DSPaginationSeparator />
114
+ <DSPageNextButton canNextPage={!isPageCountLoading && pageIndex !== pageCount} onNextPage={onNextPage} />
115
+ ```
116
+
117
+ If `pageCount` in your state can be `null` or `undefined` while loading, add a fallback: `pageCount={pageCount ?? 0}`. This prevents passing an invalid type — it is a null-safety guard unrelated to `isLoadingPageCount`.
118
+
119
+ ### Per-page selector — options array vs step-based
120
+
121
+ Two configuration modes for `DSPerPageSelector`:
122
+
123
+ ```jsx
124
+ // Explicit options array — use when you need specific values including non-numeric options
125
+ <DSPerPageSelector
126
+ pageSize={pageSize}
127
+ onPageSizeChange={onPageSizeChange}
128
+ perPageOptions={[10, 20, 50, { type: 'single', dsId: 'all', label: 'All', value: totalRecords }]}
129
+ />
130
+
131
+ // Step-based — use when you want a generated range from minPerPage to maxPerPage
132
+ <DSPerPageSelector
133
+ pageSize={pageSize}
134
+ onPageSizeChange={onPageSizeChange}
135
+ minPerPage={10}
136
+ maxPerPage={50}
137
+ perPageStep={10}
138
+ />
139
+ ```
140
+
141
+ Both modes require `onPageSizeChange` to reset `pageIndex` to 1.
142
+
143
+ ### Segmented paginator with pageDetails
144
+
145
+ `pageDetails` provides per-page range summaries in the paginator dropdown. `pageDetailsTitle` labels the column. Build server-side or derive from dataset slice metadata.
146
+
147
+ ```jsx
148
+ const pageDetails = pages.map((p) => `${p.firstRecord}-${p.lastRecord}`);
149
+
150
+ <DSPaginator
151
+ pageCount={pageCount}
152
+ pageIndex={pageIndex}
153
+ onPageChange={onPageChange}
154
+ pageDetailsTitle="Records"
155
+ pageDetails={pageDetails}
156
+ />;
157
+ ```
158
+
159
+ ## Common Mistakes
160
+
161
+ ### CRITICAL Using DSPagination (monolithic) instead of composable parts
162
+
163
+ Wrong:
164
+
165
+ ```jsx
166
+ import { DSPagination } from '@elliemae/ds-pagination';
167
+ <DSPagination pageIndex={pageIndex} pageCount={pageCount} onPageChange={handlePageChange} />;
168
+ ```
169
+
170
+ Correct:
171
+
172
+ ```jsx
173
+ import {
174
+ DSPaginationContainer,
175
+ DSPaginator,
176
+ DSPagePrevButton,
177
+ DSPageNextButton,
178
+ DSPaginationSeparator,
179
+ } from '@elliemae/ds-pagination';
180
+
181
+ <DSPaginationContainer>
182
+ <DSPagePrevButton canPreviousPage={pageIndex !== 1} onPreviousPage={handlePrevious} />
183
+ <DSPaginationSeparator />
184
+ <DSPaginator pageCount={pageCount} pageIndex={pageIndex} onPageChange={handlePageChange} />
185
+ <DSPaginationSeparator />
186
+ <DSPageNextButton canNextPage={pageIndex !== pageCount} onNextPage={handleNext} />
187
+ </DSPaginationContainer>;
188
+ ```
189
+
190
+ `DSPagination` is the pre-v3.15 monolithic API, kept only for backward compatibility — its namespace is marked `// LEGACY WAY OF USING THE PAGINATION COMPONENT`. All new implementations use the composable parts.
191
+
192
+ Source: https://dimsum.mortgagetech.ice.com/iframe.html?id=components-pagination-features--basic
193
+
194
+ ---
195
+
196
+ ### HIGH Not resetting pageIndex to 1 when pageSize changes
197
+
198
+ Wrong:
199
+
200
+ ```jsx
201
+ const onPageSizeChange = useCallback(
202
+ (newPageSize) => {
203
+ dispatch(setPageSize(newPageSize));
204
+ dispatch(fetchPage({ page: pageIndex, pageSize: newPageSize }));
205
+ },
206
+ [dispatch, pageIndex, pageSize],
207
+ );
208
+ ```
209
+
210
+ Correct:
211
+
212
+ ```jsx
213
+ const onPageSizeChange = useCallback(
214
+ (newPageSize) => {
215
+ dispatch(setPageSize(newPageSize));
216
+ dispatch(setPageIndex(1));
217
+ dispatch(fetchPage({ page: 1, pageSize: newPageSize }));
218
+ },
219
+ [dispatch],
220
+ );
221
+ ```
222
+
223
+ When page size changes, the total page count changes. The current `pageIndex` may no longer exist in the new page layout.
224
+
225
+ Source: https://dimsum.mortgagetech.ice.com/iframe.html?id=components-pagination-features--per-page-selector-with-options
226
+
227
+ ---
228
+
229
+ ### HIGH Non-primitive pagination props not memoized
230
+
231
+ Every callback and non-primitive prop passed to pagination primitives must be a stable reference.
232
+
233
+ | Prop | Component | Memoization |
234
+ | ------------------ | ------------------- | ------------------------------- |
235
+ | `onPreviousPage` | `DSPagePrevButton` | `useCallback` |
236
+ | `onNextPage` | `DSPageNextButton` | `useCallback` |
237
+ | `onPageChange` | `DSPaginator` | `useCallback` |
238
+ | `onPageSizeChange` | `DSPerPageSelector` | `useCallback` |
239
+ | `perPageOptions` | `DSPerPageSelector` | `useMemo` if constructed inline |
240
+ | `pageDetails` | `DSPaginator` | `useMemo` if constructed inline |
241
+
242
+ Source: https://dimsum.mortgagetech.ice.com/iframe.html?id=components-pagination-features--basic
243
+
244
+ ---
245
+
246
+ ### MEDIUM Passing 0 for pageCount while total count is loading
247
+
248
+ Wrong:
249
+
250
+ ```jsx
251
+ <DSPaginator pageCount={0} pageIndex={pageIndex} onPageChange={onPageChange} />
252
+ ```
253
+
254
+ Correct:
255
+
256
+ ```jsx
257
+ <DSPaginator
258
+ pageCount={pageCount}
259
+ isLoadingPageCount={isPageCountLoading}
260
+ pageIndex={pageIndex}
261
+ onPageChange={onPageChange}
262
+ />
263
+ ```
264
+
265
+ `isLoadingPageCount={true}` shows the spinner regardless of `pageCount`. Without it, the paginator renders whatever value `pageCount` has — including `0`, which displays as a broken state.
266
+
267
+ Source: https://dimsum.mortgagetech.ice.com/iframe.html?id=components-pagination-features--loading-page-count
268
+
269
+ ---
270
+
271
+ ### HIGH Client-side array slicing used without deliberate team ownership
272
+
273
+ ```jsx
274
+ const pagedData = allRecords.slice((pageIndex - 1) * pageSize, pageIndex * pageSize);
275
+ const pageCount = Math.ceil(allRecords.length / pageSize);
276
+ ```
277
+
278
+ Client-side slicing is not automatically wrong — it is a known tradeoff that is sometimes the right call given backend constraints. What makes it a problem is when it is implemented without explicit team awareness: the full dataset is in memory and growing stale the moment the source data changes, there is no backend cost saving, and compounding with sorting and filtering multiplies the fragility.
279
+
280
+ Before implementing or accepting a client-side slice approach, surface these questions to the team:
281
+
282
+ - Does the backend currently support paginated endpoints? If not, is this on a roadmap?
283
+ - Has the team acknowledged the data freshness implication (in-memory snapshot vs live data)?
284
+ - Is there a documented plan to migrate to server-side pagination when backend support is available?
285
+
286
+ If the answer to all three is yes and the team owns the decision — proceed. Document the temporary nature explicitly in code. If the team has not considered these questions, raise them before writing the implementation.
287
+
288
+ Source: https://dimsum.mortgagetech.ice.com/iframe.html?id=components-pagination-features--basic
289
+
290
+ ---
291
+
292
+ ### HIGH Managing pagination state with useState instead of the project state manager
293
+
294
+ Wrong:
295
+
296
+ ```jsx
297
+ const [pageIndex, setPageIndex] = useState(1);
298
+ const [pageSize, setPageSize] = useState(10);
299
+ ```
300
+
301
+ Correct:
302
+
303
+ ```jsx
304
+ const { pageIndex, pageSize, pageCount } = useSelector(selectPaginationState);
305
+ const dispatch = useDispatch();
306
+ ```
307
+
308
+ Stories use `useState` as a teaching simplification. Production code must use the project's state manager. Pagination state drives API calls and is shared across the view — it cannot be local component state.
309
+
310
+ ---
311
+
312
+ ## When composable parts are not enough
313
+
314
+ If the six composable primitives cannot satisfy the layout or behavior requirement:
315
+
316
+ 1. Confirm the requirement with UI/UX — most pagination variations are achievable via composition, ordering, and xstyled props on the primitives.
317
+ 2. Contact the Dimsum team to validate whether a first-class solution should be added.
318
+
319
+ **ICE internal:** Microsoft Teams — Dimsum channel (informal) / Jira Dimsum board (formal)
320
+ **Partners:** Your organization's Dimsum point of contact
321
+
322
+ See also: `@elliemae/ds-data-table` `Pagination` render prop — if this pagination bar is used with a DataTable, load the DataTable pagination skill for the integration wiring.
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: ds-pagination-slots
3
+ description: >
4
+ Slot injection surface for @elliemae/ds-pagination. Verified against v3.60.0 via probe.
5
+ DSPaginationContainer (ROOT, WRAPPER) and DSPaginationSeparator (SEPARATOR) have functional
6
+ slot injection. DSPaginator, DSPagePrevButton, DSPageNextButton, and DSPerPageSelector slot
7
+ props have no effect in the current version — use standard HTML props on those four directly.
8
+ type: core
9
+ library: ds-pagination
10
+ library_version: '3.60.0'
11
+ requires:
12
+ - ds-pagination-setup
13
+ sources:
14
+ - '@elliemae/ds-pagination:dist/types/react-desc-prop-types.d.ts'
15
+ - '@elliemae/ds-pagination:dist/types/parts/DSPaginationContainer/react-desc-prop-types.d.ts'
16
+ ---
17
+
18
+ ## Slot surface — DOM hierarchy
19
+
20
+ Slots are injection points into specific rendered DOM nodes. Understanding the hierarchy is required to inject props at the correct level.
21
+
22
+ **About this map:** Verified against `@elliemae/ds-pagination@3.60.0` via probe tests. Slot names are governed by the Dimsum breaking change protocol — renames are intentional and documented. If something doesn't match your installed version, inspect the rendered HTML in your environment. If you cannot do it autonomously, ask the human in the loop to render the component with synthetic data only — not production data containing real user information.
23
+
24
+ Each entry shows: `slot-key (data-dimsum-slot="value") · tag[role] · notes`.
25
+
26
+ ```
27
+ DSPaginationContainer renders:
28
+
29
+ ROOT (dsPaginationRoot) · div ← inject aria-label, data-* here
30
+ └── WRAPPER (dsPaginationWrapper) · div
31
+ ├── DSPerPageSelector ← no dsPaginationPerPageSelector in DOM (slot prop not active in current version)
32
+ │ └── dsButtonRoot · button (inner dropdown trigger)
33
+ │ └── dsTypographyRoot · span
34
+ ├── SEPARATOR (dsPaginationSeparator) · div ← functional ✓
35
+ ├── DSPagePrevButton ← no dsPaginationPrevPage in DOM (slot prop not active in current version)
36
+ │ └── dsButtonRoot · button (inner button)
37
+ │ └── dsIconRoot · span
38
+ │ └── dsIconSvg · svg
39
+ ├── SEPARATOR (dsPaginationSeparator) · div ← functional ✓
40
+ ├── DSPaginator ← no dsPaginationPaginator in DOM (slot prop not active in current version)
41
+ │ └── dsButtonRoot · button (inner dropdown trigger)
42
+ │ ├── dsTypographyRoot · span
43
+ │ └── dsIconRoot · span
44
+ │ └── dsIconSvg · svg
45
+ ├── SEPARATOR (dsPaginationSeparator) · div ← functional ✓
46
+ └── DSPageNextButton ← no dsPaginationNextButton in DOM (slot prop not active in current version)
47
+ └── dsButtonRoot · button (inner button)
48
+ └── dsIconRoot · span
49
+ └── dsIconSvg · svg
50
+ ```
51
+
52
+ ### What works
53
+
54
+ `DSPaginationContainer` slot props (`dsPaginationRoot`, `dsPaginationWrapper`) accept injection:
55
+
56
+ ```jsx
57
+ <DSPaginationContainer dsPaginationRoot={{ 'aria-label': 'Loan results pagination', 'data-section': 'pagination' }}>
58
+ ...
59
+ </DSPaginationContainer>
60
+ ```
61
+
62
+ `DSPaginationSeparator` slot prop (`dsPaginationSeparator`) also works.
63
+
64
+ ### What doesn't work
65
+
66
+ `DSPaginator`, `DSPagePrevButton`, `DSPageNextButton`, and `DSPerPageSelector` do not produce their own `dsPagination*` slot attributes. Passing e.g. `dsPaginationPaginator={{ ... }}` to `DSPaginator` has no effect at runtime.
67
+
68
+ **Current workaround:** Use standard HTML props directly on these components — `aria-*` and `data-*` attributes passed directly as props work correctly on all of them:
69
+
70
+ ```jsx
71
+ <DSPagePrevButton
72
+ canPreviousPage={pageIndex !== 1}
73
+ onPreviousPage={onPreviousPage}
74
+ aria-label="Go to previous page"
75
+ data-testid="pagination-prev"
76
+ />
77
+
78
+ <DSPaginator
79
+ pageCount={pageCount}
80
+ pageIndex={pageIndex}
81
+ onPageChange={onPageChange}
82
+ aria-label="Page selector"
83
+ />
84
+ ```
85
+
86
+ This gap is tracked by the Dimsum team. Contact them if slot injection on these components is required for your use case.
87
+
88
+ ## When this isn't enough
89
+
90
+ **ICE internal:** Microsoft Teams — Dimsum channel (informal) / Jira Dimsum board (formal)
91
+ **Partners:** Your organization's Dimsum point of contact