@justeattakeaway/pie-pagination 0.0.0-stage → 0.1.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 +136 -2
- package/custom-elements.json +255 -0
- package/dist/index.d.ts +111 -0
- package/dist/index.js +160 -0
- package/dist/react.d.ts +122 -0
- package/dist/react.js +25 -0
- package/package.json +57 -4
- package/src/defs-react.ts +3 -0
- package/src/defs.ts +61 -0
- package/src/index.ts +200 -0
- package/src/pagination.scss +53 -0
- package/src/react.ts +29 -0
package/README.md
CHANGED
|
@@ -1,3 +1,137 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @justeattakeaway/pie-pagination
|
|
2
|
+
[Source Code](https://github.com/justeattakeaway/pie/tree/main/packages/components/pie-pagination) | [Design Documentation](https://pie.design/components/pagination) | [NPM](https://www.npmjs.com/package/@justeattakeaway/pie-pagination)
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
<p>
|
|
5
|
+
<a href="https://www.npmjs.com/@justeattakeaway/pie-pagination">
|
|
6
|
+
<img alt="GitHub Workflow Status" src="https://img.shields.io/npm/v/@justeattakeaway/pie-pagination.svg">
|
|
7
|
+
</a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
`@justeattakeaway/pie-pagination` is a Web Component built using the Lit library. It offers a simple and accessible `pagination` component for web applications.
|
|
11
|
+
|
|
12
|
+
## Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Documentation](#documentation)
|
|
16
|
+
- [Properties](#properties)
|
|
17
|
+
- [Slots](#slots)
|
|
18
|
+
- [CSS Variables](#css-variables)
|
|
19
|
+
- [Events](#events)
|
|
20
|
+
- [Usage Examples](#usage-examples)
|
|
21
|
+
- [Questions and Support](#questions-and-support)
|
|
22
|
+
- [Contributing](#contributing)
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
> To install any of our web components in your application, we would suggest following the [getting started guide](https://webc.pie.design/?path=/docs/introduction-getting-started--docs) to set up your project.
|
|
27
|
+
|
|
28
|
+
Ideally, you should install the component using the **`@justeattakeaway/pie-webc`** package, which includes all of the components. Or you can install the individual component package.
|
|
29
|
+
|
|
30
|
+
## Documentation
|
|
31
|
+
|
|
32
|
+
### Properties
|
|
33
|
+
| Prop | Options | Description | Default |
|
|
34
|
+
|---------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
|
|
35
|
+
| `currentPage` | `number`| The currently active page (1-based). This component is fully controlled, so it never updates this value itself; the consumer is responsible for updating it in response to the `pie-pagination-page-change` event. | `1` |
|
|
36
|
+
| `totalPages` | `number`| The total number of pages to render. | `1` |
|
|
37
|
+
| `disabled` | `boolean`| When true, all pagination controls are disabled. | `false` |
|
|
38
|
+
| `aria` | `object`| The ARIA attributes for the pagination landmark. Offers a `label` used for the `aria-label` of the wrapping `<nav>` element. | `undefined` |
|
|
39
|
+
|
|
40
|
+
### Slots
|
|
41
|
+
This component does not use any slots.
|
|
42
|
+
|
|
43
|
+
### CSS Variables
|
|
44
|
+
This component does not expose any CSS variables.
|
|
45
|
+
|
|
46
|
+
### Events
|
|
47
|
+
| Event | Type | Description |
|
|
48
|
+
|-------------------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
49
|
+
| `pie-pagination-page-change` | `CustomEvent` | Fired when the user interacts with any pagination control. The event detail contains `{ currentPage }`, the page the user wants to navigate to. |
|
|
50
|
+
| `pie-pagination-prev` | `CustomEvent` | Fired when the user clicks the "previous" control. The event detail contains `{ currentPage }`. This event fires **in addition to** `pie-pagination-page-change`. |
|
|
51
|
+
| `pie-pagination-next` | `CustomEvent` | Fired when the user clicks the "next" control. The event detail contains `{ currentPage }`. This event fires **in addition to** `pie-pagination-page-change`. |
|
|
52
|
+
|
|
53
|
+
## Usage Examples
|
|
54
|
+
|
|
55
|
+
**For HTML:**
|
|
56
|
+
|
|
57
|
+
```js
|
|
58
|
+
// import as module into a js file e.g. main.js
|
|
59
|
+
import '@justeattakeaway/pie-webc/components/pagination.js'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<!-- pass js file into <script> tag -->
|
|
64
|
+
|
|
65
|
+
<script type="module" src="/main.js"></script>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<pie-pagination currentPage="2" totalPages="10"></pie-pagination>
|
|
70
|
+
|
|
71
|
+
<script>
|
|
72
|
+
const pagination = document.querySelector('pie-pagination');
|
|
73
|
+
|
|
74
|
+
pagination.addEventListener('pie-pagination-page-change', (event) => {
|
|
75
|
+
// The component is controlled — update the prop yourself
|
|
76
|
+
pagination.currentPage = event.detail.currentPage;
|
|
77
|
+
});
|
|
78
|
+
</script>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The `pie-pagination-prev` and `pie-pagination-next` events let you hook into the previous/next controls specifically. They fire in addition to `pie-pagination-page-change`, so you can use either one:
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<pie-pagination currentPage="2" totalPages="10"></pie-pagination>
|
|
85
|
+
|
|
86
|
+
<script>
|
|
87
|
+
const pagination = document.querySelector('pie-pagination');
|
|
88
|
+
|
|
89
|
+
pagination.addEventListener('pie-pagination-prev', (event) => {
|
|
90
|
+
console.log('previous clicked, requested page:', event.detail.currentPage);
|
|
91
|
+
pagination.currentPage = event.detail.currentPage;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
pagination.addEventListener('pie-pagination-next', (event) => {
|
|
95
|
+
console.log('next clicked, requested page:', event.detail.currentPage);
|
|
96
|
+
pagination.currentPage = event.detail.currentPage;
|
|
97
|
+
});
|
|
98
|
+
</script>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**For Native JS Applications, Vue, Angular, Svelte etc.:**
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
// Vue templates (using Nuxt 3)
|
|
105
|
+
import '@justeattakeaway/pie-webc/components/pagination.js'
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**For React Applications:**
|
|
109
|
+
|
|
110
|
+
```jsx
|
|
111
|
+
import { PiePagination } from '@justeattakeaway/pie-webc/react/pagination.js';
|
|
112
|
+
|
|
113
|
+
<PiePagination
|
|
114
|
+
currentPage={currentPage}
|
|
115
|
+
totalPages={totalPages}
|
|
116
|
+
onPiePaginationPageChange={(event) => setCurrentPage(event.detail.currentPage)}
|
|
117
|
+
/>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The `pie-pagination-prev` and `pie-pagination-next` events are exposed as `onPiePaginationPrev` and `onPiePaginationNext`:
|
|
121
|
+
|
|
122
|
+
```jsx
|
|
123
|
+
<PiePagination
|
|
124
|
+
currentPage={currentPage}
|
|
125
|
+
totalPages={totalPages}
|
|
126
|
+
onPiePaginationPrev={(event) => setCurrentPage(event.detail.currentPage)}
|
|
127
|
+
onPiePaginationNext={(event) => setCurrentPage(event.detail.currentPage)}
|
|
128
|
+
/>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Questions and Support
|
|
132
|
+
|
|
133
|
+
If you work at Just Eat Takeaway.com, please contact us on **#help-designsystem**. Otherwise, please raise an issue on [Github](https://github.com/justeattakeaway/pie/issues).
|
|
134
|
+
|
|
135
|
+
## Contributing
|
|
136
|
+
|
|
137
|
+
Check out our [contributing guide](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide) for more information on [local development](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#local-development) and how to run specific [component tests](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#testing).
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "src/defs-react.js",
|
|
8
|
+
"declarations": [],
|
|
9
|
+
"exports": []
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"kind": "javascript-module",
|
|
13
|
+
"path": "src/defs.js",
|
|
14
|
+
"declarations": [
|
|
15
|
+
{
|
|
16
|
+
"kind": "variable",
|
|
17
|
+
"name": "ON_PAGE_CHANGE_EVENT",
|
|
18
|
+
"type": {
|
|
19
|
+
"text": "string"
|
|
20
|
+
},
|
|
21
|
+
"default": "'pie-pagination-page-change'",
|
|
22
|
+
"description": "The event name dispatched when the user interacts with a pagination control.\nThe component is fully controlled: it never changes `currentPage` itself, it\nonly tells the consumer which page the user wants to navigate to."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"kind": "variable",
|
|
26
|
+
"name": "ON_PREV_EVENT",
|
|
27
|
+
"type": {
|
|
28
|
+
"text": "string"
|
|
29
|
+
},
|
|
30
|
+
"default": "'pie-pagination-prev'",
|
|
31
|
+
"description": "The event name dispatched when the user clicks the \"previous\" control."
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"kind": "variable",
|
|
35
|
+
"name": "ON_NEXT_EVENT",
|
|
36
|
+
"type": {
|
|
37
|
+
"text": "string"
|
|
38
|
+
},
|
|
39
|
+
"default": "'pie-pagination-next'",
|
|
40
|
+
"description": "The event name dispatched when the user clicks the \"next\" control."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"kind": "variable",
|
|
44
|
+
"name": "defaultProps",
|
|
45
|
+
"type": {
|
|
46
|
+
"text": "DefaultProps"
|
|
47
|
+
},
|
|
48
|
+
"default": "{ currentPage: 1, totalPages: 1, disabled: false, }"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"exports": [
|
|
52
|
+
{
|
|
53
|
+
"kind": "js",
|
|
54
|
+
"name": "ON_PAGE_CHANGE_EVENT",
|
|
55
|
+
"declaration": {
|
|
56
|
+
"name": "ON_PAGE_CHANGE_EVENT",
|
|
57
|
+
"module": "src/defs.js"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"kind": "js",
|
|
62
|
+
"name": "ON_PREV_EVENT",
|
|
63
|
+
"declaration": {
|
|
64
|
+
"name": "ON_PREV_EVENT",
|
|
65
|
+
"module": "src/defs.js"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"kind": "js",
|
|
70
|
+
"name": "ON_NEXT_EVENT",
|
|
71
|
+
"declaration": {
|
|
72
|
+
"name": "ON_NEXT_EVENT",
|
|
73
|
+
"module": "src/defs.js"
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"kind": "js",
|
|
78
|
+
"name": "defaultProps",
|
|
79
|
+
"declaration": {
|
|
80
|
+
"name": "defaultProps",
|
|
81
|
+
"module": "src/defs.js"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
]
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"kind": "javascript-module",
|
|
88
|
+
"path": "src/index.js",
|
|
89
|
+
"declarations": [
|
|
90
|
+
{
|
|
91
|
+
"kind": "class",
|
|
92
|
+
"description": "",
|
|
93
|
+
"name": "PiePagination",
|
|
94
|
+
"members": [
|
|
95
|
+
{
|
|
96
|
+
"kind": "field",
|
|
97
|
+
"name": "aria",
|
|
98
|
+
"type": {
|
|
99
|
+
"text": "PaginationProps['aria']"
|
|
100
|
+
},
|
|
101
|
+
"privacy": "public",
|
|
102
|
+
"attribute": "aria"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"kind": "field",
|
|
106
|
+
"name": "currentPage",
|
|
107
|
+
"privacy": "public",
|
|
108
|
+
"attribute": "currentPage"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"kind": "field",
|
|
112
|
+
"name": "totalPages",
|
|
113
|
+
"privacy": "public",
|
|
114
|
+
"attribute": "totalPages"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"kind": "field",
|
|
118
|
+
"name": "disabled",
|
|
119
|
+
"privacy": "public",
|
|
120
|
+
"attribute": "disabled"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"kind": "method",
|
|
124
|
+
"name": "_emitPageChange",
|
|
125
|
+
"privacy": "private",
|
|
126
|
+
"parameters": [
|
|
127
|
+
{
|
|
128
|
+
"name": "currentPage",
|
|
129
|
+
"type": {
|
|
130
|
+
"text": "number"
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
"description": "Emits the page change event with the page the user wants to navigate to.\nThe component never updates `currentPage` itself."
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"kind": "method",
|
|
138
|
+
"name": "_handlePreviousClick",
|
|
139
|
+
"privacy": "private",
|
|
140
|
+
"description": "Handles a click on the \"previous\" control."
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"kind": "method",
|
|
144
|
+
"name": "_handleNextClick",
|
|
145
|
+
"privacy": "private",
|
|
146
|
+
"description": "Handles a click on the \"next\" control."
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"kind": "method",
|
|
150
|
+
"name": "_handlePageClick",
|
|
151
|
+
"privacy": "private",
|
|
152
|
+
"parameters": [
|
|
153
|
+
{
|
|
154
|
+
"name": "page",
|
|
155
|
+
"type": {
|
|
156
|
+
"text": "number"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"description": "Handles a click on a page number control."
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"kind": "method",
|
|
164
|
+
"name": "_renderChevronIcon",
|
|
165
|
+
"privacy": "private",
|
|
166
|
+
"parameters": [
|
|
167
|
+
{
|
|
168
|
+
"name": "direction",
|
|
169
|
+
"type": {
|
|
170
|
+
"text": "'previous' | 'next'"
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
"description": "Renders the chevron icon for the previous/next controls, mirroring it for RTL."
|
|
175
|
+
}
|
|
176
|
+
],
|
|
177
|
+
"events": [
|
|
178
|
+
{
|
|
179
|
+
"type": {
|
|
180
|
+
"text": "CustomEvent"
|
|
181
|
+
},
|
|
182
|
+
"description": "when the user interacts with a pagination control.",
|
|
183
|
+
"name": "pie-pagination-page-change"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"type": {
|
|
187
|
+
"text": "CustomEvent"
|
|
188
|
+
},
|
|
189
|
+
"description": "when the user clicks the \"previous\" control.",
|
|
190
|
+
"name": "pie-pagination-prev"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"type": {
|
|
194
|
+
"text": "CustomEvent"
|
|
195
|
+
},
|
|
196
|
+
"description": "when the user clicks the \"next\" control.",
|
|
197
|
+
"name": "pie-pagination-next"
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
"attributes": [
|
|
201
|
+
{
|
|
202
|
+
"name": "aria",
|
|
203
|
+
"type": {
|
|
204
|
+
"text": "PaginationProps['aria']"
|
|
205
|
+
},
|
|
206
|
+
"fieldName": "aria"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "currentPage",
|
|
210
|
+
"fieldName": "currentPage"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"name": "totalPages",
|
|
214
|
+
"fieldName": "totalPages"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"name": "disabled",
|
|
218
|
+
"fieldName": "disabled"
|
|
219
|
+
}
|
|
220
|
+
],
|
|
221
|
+
"mixins": [
|
|
222
|
+
{
|
|
223
|
+
"name": "RtlMixin",
|
|
224
|
+
"package": "@justeattakeaway/pie-webc-core"
|
|
225
|
+
}
|
|
226
|
+
],
|
|
227
|
+
"superclass": {
|
|
228
|
+
"name": "PieElement",
|
|
229
|
+
"package": "@justeattakeaway/pie-webc-core/src/internals/PieElement"
|
|
230
|
+
},
|
|
231
|
+
"tagName": "pie-pagination",
|
|
232
|
+
"customElement": true
|
|
233
|
+
}
|
|
234
|
+
],
|
|
235
|
+
"exports": [
|
|
236
|
+
{
|
|
237
|
+
"kind": "js",
|
|
238
|
+
"name": "*",
|
|
239
|
+
"declaration": {
|
|
240
|
+
"name": "*",
|
|
241
|
+
"module": "src/defs"
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"kind": "js",
|
|
246
|
+
"name": "PiePagination",
|
|
247
|
+
"declaration": {
|
|
248
|
+
"name": "PiePagination",
|
|
249
|
+
"module": "src/index.js"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
]
|
|
255
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
2
|
+
import { CSSResult } from 'lit';
|
|
3
|
+
import { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
4
|
+
import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
|
|
5
|
+
import { PropertyValues } from 'lit';
|
|
6
|
+
import { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
7
|
+
import { TemplateResult } from 'lit-html';
|
|
8
|
+
|
|
9
|
+
declare type AriaProps = {
|
|
10
|
+
label?: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export declare type DefaultProps = ComponentDefaultProps<PaginationProps, 'currentPage' | 'totalPages' | 'disabled'>;
|
|
14
|
+
|
|
15
|
+
export declare const defaultProps: DefaultProps;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The event name dispatched when the user clicks the "next" control.
|
|
19
|
+
* @constant
|
|
20
|
+
*/
|
|
21
|
+
export declare const ON_NEXT_EVENT = "pie-pagination-next";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The event name dispatched when the user interacts with a pagination control.
|
|
25
|
+
* The component is fully controlled: it never changes `currentPage` itself, it
|
|
26
|
+
* only tells the consumer which page the user wants to navigate to.
|
|
27
|
+
* @constant
|
|
28
|
+
*/
|
|
29
|
+
export declare const ON_PAGE_CHANGE_EVENT = "pie-pagination-page-change";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The event name dispatched when the user clicks the "previous" control.
|
|
33
|
+
* @constant
|
|
34
|
+
*/
|
|
35
|
+
export declare const ON_PREV_EVENT = "pie-pagination-prev";
|
|
36
|
+
|
|
37
|
+
export declare interface PaginationProps {
|
|
38
|
+
/**
|
|
39
|
+
* The ARIA attributes for the pagination landmark. Offers a `label` used for
|
|
40
|
+
* the `aria-label` of the wrapping `<nav>` element.
|
|
41
|
+
*/
|
|
42
|
+
aria?: AriaProps;
|
|
43
|
+
/**
|
|
44
|
+
* The currently active page (1-based). This component is fully controlled, so
|
|
45
|
+
* it never updates this value itself; the consumer is responsible for updating
|
|
46
|
+
* it in response to the `pie-pagination-page-change` event.
|
|
47
|
+
* @default 1
|
|
48
|
+
*/
|
|
49
|
+
currentPage?: number;
|
|
50
|
+
/**
|
|
51
|
+
* The total number of pages to render.
|
|
52
|
+
* @default 1
|
|
53
|
+
*/
|
|
54
|
+
totalPages?: number;
|
|
55
|
+
/**
|
|
56
|
+
* When true, all pagination controls are disabled.
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
disabled?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @tagname pie-pagination
|
|
64
|
+
* @event {CustomEvent} pie-pagination-page-change - when the user interacts with a pagination control.
|
|
65
|
+
* @event {CustomEvent} pie-pagination-prev - when the user clicks the "previous" control.
|
|
66
|
+
* @event {CustomEvent} pie-pagination-next - when the user clicks the "next" control.
|
|
67
|
+
*/
|
|
68
|
+
export declare class PiePagination extends PiePagination_base implements PaginationProps {
|
|
69
|
+
aria: PaginationProps['aria'];
|
|
70
|
+
currentPage: number;
|
|
71
|
+
totalPages: number;
|
|
72
|
+
disabled: boolean;
|
|
73
|
+
protected updated(changedProperties: PropertyValues<this>): void;
|
|
74
|
+
/**
|
|
75
|
+
* Emits the page change event with the page the user wants to navigate to.
|
|
76
|
+
* The component never updates `currentPage` itself.
|
|
77
|
+
*
|
|
78
|
+
* @private
|
|
79
|
+
*/
|
|
80
|
+
private _emitPageChange;
|
|
81
|
+
/**
|
|
82
|
+
* Handles a click on the "previous" control.
|
|
83
|
+
*
|
|
84
|
+
* @private
|
|
85
|
+
*/
|
|
86
|
+
private _handlePreviousClick;
|
|
87
|
+
/**
|
|
88
|
+
* Handles a click on the "next" control.
|
|
89
|
+
*
|
|
90
|
+
* @private
|
|
91
|
+
*/
|
|
92
|
+
private _handleNextClick;
|
|
93
|
+
/**
|
|
94
|
+
* Handles a click on a page number control.
|
|
95
|
+
*
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
private _handlePageClick;
|
|
99
|
+
/**
|
|
100
|
+
* Renders the chevron icon for the previous/next controls, mirroring it for RTL.
|
|
101
|
+
*
|
|
102
|
+
* @private
|
|
103
|
+
*/
|
|
104
|
+
private _renderChevronIcon;
|
|
105
|
+
render(): TemplateResult<1>;
|
|
106
|
+
static styles: CSSResult;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
declare const PiePagination_base: GenericConstructor<RTLInterface> & typeof PieElement;
|
|
110
|
+
|
|
111
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { LitElement as u, html as p, unsafeCSS as x } from "lit";
|
|
2
|
+
import { property as g } from "lit/decorators.js";
|
|
3
|
+
import { classMap as f } from "lit/directives/class-map.js";
|
|
4
|
+
import { ifDefined as P } from "lit/directives/if-defined.js";
|
|
5
|
+
import { RtlMixin as y, dispatchCustomEvent as b, safeCustomElement as z } from "@justeattakeaway/pie-webc-core";
|
|
6
|
+
import "@justeattakeaway/pie-icon-button";
|
|
7
|
+
import "@justeattakeaway/pie-icons-webc/dist/IconChevronLeft.js";
|
|
8
|
+
import "@justeattakeaway/pie-icons-webc/dist/IconChevronRight.js";
|
|
9
|
+
const v = class v extends u {
|
|
10
|
+
willUpdate() {
|
|
11
|
+
this.getAttribute("v") || this.setAttribute("v", v.v);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
v.v = "0.1.0";
|
|
15
|
+
let m = v;
|
|
16
|
+
const _ = "*,*:after,*:before{box-sizing:inherit}:host{display:inline-block}.c-pagination{display:inline-block}.c-pagination-list{display:flex;align-items:center;gap:var(--dt-spacing-b);margin:0;padding:0;list-style:none}.c-pagination-item{display:flex;align-items:center}.c-pagination-control{--btn-border-radius: var(--dt-radius-rounded-e);--btn-font-family: var(--dt-font-interactive-l-family);--btn-font-weight: var(--dt-font-interactive-l-weight);--int-states-mixin-bg-color: var(--dt-color-interactive-brand);--btn-text-color: var(--dt-color-content-interactive-light-solid);--btn-padding-vertical-xsmall: 6px;--btn-padding-vertical-small-expressive: 8px;--btn-padding-vertical-small-productive: 10px;--btn-padding-vertical-medium: 12px;--btn-padding-vertical-large: 16px;--btn-padding-horizontal-small: var(--dt-spacing-b);--btn-padding-horizontal-medium: var(--dt-spacing-d);--btn-padding-horizontal-large: var(--dt-spacing-e);position:relative;display:inline-flex;gap:var(--dt-spacing-b);align-items:center;justify-content:center;border:none;border-radius:var(--btn-border-radius);outline:none;background-color:var(--int-states-mixin-bg-color);cursor:pointer;-webkit-user-select:none;user-select:none;text-decoration:none;font-family:var(--btn-font-family);font-size:var(--btn-font-size);font-weight:var(--btn-font-weight);color:var(--btn-text-color);line-height:var(--btn-line-height);inline-size:var(--btn-inline-size)}.c-pagination-control:focus-visible{box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-pagination-control{--btn-font-size: calc(var(--dt-font-interactive-xs-size) * 1px);--btn-line-height: calc(var(--dt-font-interactive-xs-line-height) * 1px);--btn-icon-size: 16px;--icon-size-override: 16px;padding:var(--btn-padding-vertical-xsmall) var(--btn-padding-horizontal-small)}@media(min-width:769px){.c-pagination-control.c-button--responsive{--btn-font-size: calc(var(--dt-font-interactive-s-size) * 1px);--btn-line-height: calc(var(--dt-font-interactive-s-line-height) * 1px);--btn-icon-size: 20px;--icon-size-override: 20px;padding:var(--btn-padding-vertical-small-productive) var(--btn-padding-horizontal-medium)}.c-pagination-control.c-button--responsive.c-button--expressive{--btn-font-size: calc(var(--dt-font-interactive-l-size) * 1px);--btn-line-height: calc(var(--dt-font-interactive-l-line-height) * 1px);--btn-icon-size: 20px;--icon-size-override: 20px;padding:var(--btn-padding-vertical-small-expressive) var(--btn-padding-horizontal-medium)}}.c-pagination-control.c-button--outline,.c-pagination-control.c-button--outline-inverse{padding:calc(var(--btn-padding-vertical-xsmall) - 1px) var(--btn-padding-horizontal-small)}@media(min-width:769px){.c-pagination-control.c-button--outline.c-button--responsive,.c-pagination-control.c-button--outline-inverse.c-button--responsive{padding:calc(var(--btn-padding-vertical-small-productive) - 1px) var(--btn-padding-horizontal-medium)}.c-pagination-control.c-button--outline.c-button--responsive.c-button--expressive,.c-pagination-control.c-button--outline-inverse.c-button--responsive.c-button--expressive{padding:calc(var(--btn-padding-vertical-small-expressive) - 1px) var(--btn-padding-horizontal-medium)}}.c-pagination-control{--int-states-mixin-bg-color: transparent;--btn-text-color: var(--dt-color-content-interactive-secondary-solid)}@media(hover:hover){.c-pagination-control:hover:not(:disabled,.is-disabled,.is-dismissible){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--hover-modifier: var(--dt-color-hover-01);--int-states-mixin-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--hover-modifier));--int-states-mixin-bg-color: hsl(var(--dt-color-transparent-h), var(--dt-color-transparent-s), calc(var(--dt-color-transparent-l) + var(--hover-modifier)))}}.c-pagination-control:active:not(:disabled,.is-disabled,.is-dismissible),.c-pagination-control.is-loading:not(:disabled,.is-disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--active-modifier: var(--dt-color-active-01);--int-states-mixin-bg-color: hsl(var(--dt-color-black-h), var(--dt-color-black-s), var(--dt-color-black-l), var(--active-modifier));--int-states-mixin-bg-color: hsl(var(--dt-color-transparent-h), var(--dt-color-transparent-s), calc(var(--dt-color-transparent-l) + var(--active-modifier)))}@supports (background-color: color-mix(in srgb,black,white)){@media(hover:hover){.c-pagination-control:hover:not(:disabled,.is-disabled,.is-dismissible){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-transparent))}}.c-pagination-control:active:not(:disabled,.is-disabled,.is-dismissible),.c-pagination-control.is-loading:not(:disabled,.is-disabled){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-active-01-bg) var(--dt-color-active-01), var(--dt-color-transparent))}}.c-pagination-control{inline-size:32px;block-size:32px;padding:0;--btn-font-weight: var(--dt-font-body-s-weight)}.c-pagination-control.c-pagination-control--current{--int-states-mixin-bg-color: var(--dt-color-interactive-primary);--btn-text-color: var(--dt-color-content-interactive-primary)}@media(hover:hover){.c-pagination-control.c-pagination-control--current:hover:not(:disabled,.is-disabled,.is-dismissible){--hover-modifier: var(--dt-color-hover-02);--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-primary-h), var(--dt-color-interactive-primary-s), calc(var(--dt-color-interactive-primary-l) + var(--hover-modifier)))}}.c-pagination-control.c-pagination-control--current:active:not(:disabled,.is-disabled,.is-dismissible),.c-pagination-control.c-pagination-control--current.is-loading:not(:disabled,.is-disabled){--active-modifier: var(--dt-color-active-02);--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-primary-h), var(--dt-color-interactive-primary-s), calc(var(--dt-color-interactive-primary-l) + var(--active-modifier)))}@supports (background-color: color-mix(in srgb,black,white)){@media(hover:hover){.c-pagination-control.c-pagination-control--current:hover:not(:disabled,.is-disabled,.is-dismissible){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-hover-02-bg) var(--dt-color-hover-02), var(--dt-color-interactive-primary))}}.c-pagination-control.c-pagination-control--current:active:not(:disabled,.is-disabled,.is-dismissible),.c-pagination-control.c-pagination-control--current.is-loading:not(:disabled,.is-disabled){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-active-02-bg) var(--dt-color-active-02), var(--dt-color-interactive-primary))}}.c-pagination-control.c-pagination-control--current{--btn-font-weight: var(--dt-font-body-strong-s-weight)}.c-pagination-control:disabled{--int-states-mixin-bg-color: transparent;--btn-text-color: var(--dt-color-content-disabled-solid);cursor:not-allowed}", w = "pie-pagination-page-change", $ = "pie-pagination-prev", k = "pie-pagination-next", h = {
|
|
17
|
+
currentPage: 1,
|
|
18
|
+
totalPages: 1,
|
|
19
|
+
disabled: !1
|
|
20
|
+
};
|
|
21
|
+
var C = Object.defineProperty, N = Object.getOwnPropertyDescriptor, l = (t, i, n, e) => {
|
|
22
|
+
for (var a = e > 1 ? void 0 : e ? N(i, n) : i, r = t.length - 1, s; r >= 0; r--)
|
|
23
|
+
(s = t[r]) && (a = (e ? s(i, n, a) : s(a)) || a);
|
|
24
|
+
return e && a && C(i, n, a), a;
|
|
25
|
+
};
|
|
26
|
+
let o = class extends y(m) {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments), this.currentPage = h.currentPage, this.totalPages = h.totalPages, this.disabled = h.disabled;
|
|
29
|
+
}
|
|
30
|
+
updated(t) {
|
|
31
|
+
t.has("totalPages") && this.totalPages < 1 && console.warn(`pie-pagination: "totalPages" must be at least 1, received "${this.totalPages}".`), t.has("currentPage") && this.currentPage < 1 && console.warn(`pie-pagination: "currentPage" must be at least 1, received "${this.currentPage}".`), t.has("currentPage") && this.currentPage > this.totalPages && console.warn(`pie-pagination: "currentPage" (${this.currentPage}) cannot be greater than "totalPages" (${this.totalPages}).`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Emits the page change event with the page the user wants to navigate to.
|
|
35
|
+
* The component never updates `currentPage` itself.
|
|
36
|
+
*
|
|
37
|
+
* @private
|
|
38
|
+
*/
|
|
39
|
+
_emitPageChange(t) {
|
|
40
|
+
b(this, w, { currentPage: t });
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Handles a click on the "previous" control.
|
|
44
|
+
*
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
_handlePreviousClick() {
|
|
48
|
+
if (this.disabled || this.currentPage <= 1) return;
|
|
49
|
+
const t = this.currentPage - 1;
|
|
50
|
+
b(this, $, { currentPage: t }), this._emitPageChange(t);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Handles a click on the "next" control.
|
|
54
|
+
*
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
_handleNextClick() {
|
|
58
|
+
if (this.disabled || this.currentPage >= this.totalPages) return;
|
|
59
|
+
const t = this.currentPage + 1;
|
|
60
|
+
b(this, k, { currentPage: t }), this._emitPageChange(t);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Handles a click on a page number control.
|
|
64
|
+
*
|
|
65
|
+
* @private
|
|
66
|
+
*/
|
|
67
|
+
_handlePageClick(t) {
|
|
68
|
+
this.disabled || t === this.currentPage || this._emitPageChange(t);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Renders the chevron icon for the previous/next controls, mirroring it for RTL.
|
|
72
|
+
*
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
_renderChevronIcon(t) {
|
|
76
|
+
return (t === "previous" ? !this.isRTL : this.isRTL) ? p`<icon-chevron-left></icon-chevron-left>` : p`<icon-chevron-right></icon-chevron-right>`;
|
|
77
|
+
}
|
|
78
|
+
render() {
|
|
79
|
+
const {
|
|
80
|
+
aria: t,
|
|
81
|
+
currentPage: i,
|
|
82
|
+
disabled: n,
|
|
83
|
+
totalPages: e
|
|
84
|
+
} = this, a = Array.from({ length: Math.max(e, 0) }, (c, d) => d + 1), r = n || i <= 1, s = n || i >= e;
|
|
85
|
+
return p`
|
|
86
|
+
<nav
|
|
87
|
+
class="c-pagination"
|
|
88
|
+
aria-label="${(t == null ? void 0 : t.label) ?? "Pagination"}"
|
|
89
|
+
data-test-id="pie-pagination">
|
|
90
|
+
<ol class="c-pagination-list" data-test-id="pie-pagination-list">
|
|
91
|
+
<li class="c-pagination-item">
|
|
92
|
+
<pie-icon-button
|
|
93
|
+
data-test-id="pie-pagination-previous"
|
|
94
|
+
size="xsmall"
|
|
95
|
+
variant="ghost-secondary"
|
|
96
|
+
?disabled="${r}"
|
|
97
|
+
.aria="${{ label: "Previous page" }}"
|
|
98
|
+
@click="${this._handlePreviousClick}">
|
|
99
|
+
${this._renderChevronIcon("previous")}
|
|
100
|
+
</pie-icon-button>
|
|
101
|
+
</li>
|
|
102
|
+
|
|
103
|
+
${a.map((c) => {
|
|
104
|
+
const d = c === i;
|
|
105
|
+
return p`
|
|
106
|
+
<li class="c-pagination-item">
|
|
107
|
+
<button
|
|
108
|
+
type="button"
|
|
109
|
+
class="${f({
|
|
110
|
+
"c-pagination-control": !0,
|
|
111
|
+
"c-pagination-control--current": d
|
|
112
|
+
})}"
|
|
113
|
+
data-test-id="pie-pagination-page"
|
|
114
|
+
?disabled="${n}"
|
|
115
|
+
aria-current="${P(d ? "page" : void 0)}"
|
|
116
|
+
aria-label="Page ${c}"
|
|
117
|
+
@click="${() => this._handlePageClick(c)}">
|
|
118
|
+
${c}
|
|
119
|
+
</button>
|
|
120
|
+
</li>`;
|
|
121
|
+
})}
|
|
122
|
+
|
|
123
|
+
<li class="c-pagination-item">
|
|
124
|
+
<pie-icon-button
|
|
125
|
+
data-test-id="pie-pagination-next"
|
|
126
|
+
size="xsmall"
|
|
127
|
+
variant="ghost-secondary"
|
|
128
|
+
?disabled="${s}"
|
|
129
|
+
.aria="${{ label: "Next page" }}"
|
|
130
|
+
@click="${this._handleNextClick}">
|
|
131
|
+
${this._renderChevronIcon("next")}
|
|
132
|
+
</pie-icon-button>
|
|
133
|
+
</li>
|
|
134
|
+
</ol>
|
|
135
|
+
</nav>`;
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
o.styles = x(_);
|
|
139
|
+
l([
|
|
140
|
+
g({ type: Object })
|
|
141
|
+
], o.prototype, "aria", 2);
|
|
142
|
+
l([
|
|
143
|
+
g({ type: Number })
|
|
144
|
+
], o.prototype, "currentPage", 2);
|
|
145
|
+
l([
|
|
146
|
+
g({ type: Number })
|
|
147
|
+
], o.prototype, "totalPages", 2);
|
|
148
|
+
l([
|
|
149
|
+
g({ type: Boolean })
|
|
150
|
+
], o.prototype, "disabled", 2);
|
|
151
|
+
o = l([
|
|
152
|
+
z("pie-pagination")
|
|
153
|
+
], o);
|
|
154
|
+
export {
|
|
155
|
+
k as ON_NEXT_EVENT,
|
|
156
|
+
w as ON_PAGE_CHANGE_EVENT,
|
|
157
|
+
$ as ON_PREV_EVENT,
|
|
158
|
+
o as PiePagination,
|
|
159
|
+
h as defaultProps
|
|
160
|
+
};
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
2
|
+
import { CSSResult } from 'lit';
|
|
3
|
+
import { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
4
|
+
import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
|
|
5
|
+
import { PropertyValues } from 'lit';
|
|
6
|
+
import * as React_2 from 'react';
|
|
7
|
+
import { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
8
|
+
import { TemplateResult } from 'lit-html';
|
|
9
|
+
|
|
10
|
+
declare type AriaProps = {
|
|
11
|
+
label?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export declare type DefaultProps = ComponentDefaultProps<PaginationProps, 'currentPage' | 'totalPages' | 'disabled'>;
|
|
15
|
+
|
|
16
|
+
export declare const defaultProps: DefaultProps;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The event name dispatched when the user clicks the "next" control.
|
|
20
|
+
* @constant
|
|
21
|
+
*/
|
|
22
|
+
export declare const ON_NEXT_EVENT = "pie-pagination-next";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The event name dispatched when the user interacts with a pagination control.
|
|
26
|
+
* The component is fully controlled: it never changes `currentPage` itself, it
|
|
27
|
+
* only tells the consumer which page the user wants to navigate to.
|
|
28
|
+
* @constant
|
|
29
|
+
*/
|
|
30
|
+
export declare const ON_PAGE_CHANGE_EVENT = "pie-pagination-page-change";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* The event name dispatched when the user clicks the "previous" control.
|
|
34
|
+
* @constant
|
|
35
|
+
*/
|
|
36
|
+
export declare const ON_PREV_EVENT = "pie-pagination-prev";
|
|
37
|
+
|
|
38
|
+
export declare interface PaginationProps {
|
|
39
|
+
/**
|
|
40
|
+
* The ARIA attributes for the pagination landmark. Offers a `label` used for
|
|
41
|
+
* the `aria-label` of the wrapping `<nav>` element.
|
|
42
|
+
*/
|
|
43
|
+
aria?: AriaProps;
|
|
44
|
+
/**
|
|
45
|
+
* The currently active page (1-based). This component is fully controlled, so
|
|
46
|
+
* it never updates this value itself; the consumer is responsible for updating
|
|
47
|
+
* it in response to the `pie-pagination-page-change` event.
|
|
48
|
+
* @default 1
|
|
49
|
+
*/
|
|
50
|
+
currentPage?: number;
|
|
51
|
+
/**
|
|
52
|
+
* The total number of pages to render.
|
|
53
|
+
* @default 1
|
|
54
|
+
*/
|
|
55
|
+
totalPages?: number;
|
|
56
|
+
/**
|
|
57
|
+
* When true, all pagination controls are disabled.
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
disabled?: boolean;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export declare const PiePagination: React_2.ForwardRefExoticComponent<React_2.PropsWithChildren<Omit<React_2.PropsWithoutRef<PaginationProps>, "children">> & React_2.RefAttributes<PiePagination_2> & PiePaginationEvents & ReactBaseType>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @tagname pie-pagination
|
|
67
|
+
* @event {CustomEvent} pie-pagination-page-change - when the user interacts with a pagination control.
|
|
68
|
+
* @event {CustomEvent} pie-pagination-prev - when the user clicks the "previous" control.
|
|
69
|
+
* @event {CustomEvent} pie-pagination-next - when the user clicks the "next" control.
|
|
70
|
+
*/
|
|
71
|
+
declare class PiePagination_2 extends PiePagination_base implements PaginationProps {
|
|
72
|
+
aria: PaginationProps['aria'];
|
|
73
|
+
currentPage: number;
|
|
74
|
+
totalPages: number;
|
|
75
|
+
disabled: boolean;
|
|
76
|
+
protected updated(changedProperties: PropertyValues<this>): void;
|
|
77
|
+
/**
|
|
78
|
+
* Emits the page change event with the page the user wants to navigate to.
|
|
79
|
+
* The component never updates `currentPage` itself.
|
|
80
|
+
*
|
|
81
|
+
* @private
|
|
82
|
+
*/
|
|
83
|
+
private _emitPageChange;
|
|
84
|
+
/**
|
|
85
|
+
* Handles a click on the "previous" control.
|
|
86
|
+
*
|
|
87
|
+
* @private
|
|
88
|
+
*/
|
|
89
|
+
private _handlePreviousClick;
|
|
90
|
+
/**
|
|
91
|
+
* Handles a click on the "next" control.
|
|
92
|
+
*
|
|
93
|
+
* @private
|
|
94
|
+
*/
|
|
95
|
+
private _handleNextClick;
|
|
96
|
+
/**
|
|
97
|
+
* Handles a click on a page number control.
|
|
98
|
+
*
|
|
99
|
+
* @private
|
|
100
|
+
*/
|
|
101
|
+
private _handlePageClick;
|
|
102
|
+
/**
|
|
103
|
+
* Renders the chevron icon for the previous/next controls, mirroring it for RTL.
|
|
104
|
+
*
|
|
105
|
+
* @private
|
|
106
|
+
*/
|
|
107
|
+
private _renderChevronIcon;
|
|
108
|
+
render(): TemplateResult<1>;
|
|
109
|
+
static styles: CSSResult;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
declare const PiePagination_base: GenericConstructor<RTLInterface> & typeof PieElement;
|
|
113
|
+
|
|
114
|
+
declare type PiePaginationEvents = {
|
|
115
|
+
onPiePaginationPageChange?: (event: CustomEvent) => void;
|
|
116
|
+
onPiePaginationPrev?: (event: CustomEvent) => void;
|
|
117
|
+
onPiePaginationNext?: (event: CustomEvent) => void;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
declare type ReactBaseType = React_2.HTMLAttributes<HTMLElement>;
|
|
121
|
+
|
|
122
|
+
export { }
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as a from "react";
|
|
2
|
+
import { createComponent as i } from "@lit/react";
|
|
3
|
+
import { PiePagination as e } from "./index.js";
|
|
4
|
+
import { ON_NEXT_EVENT as r, ON_PAGE_CHANGE_EVENT as m, ON_PREV_EVENT as N, defaultProps as E } from "./index.js";
|
|
5
|
+
const n = i({
|
|
6
|
+
displayName: "PiePagination",
|
|
7
|
+
elementClass: e,
|
|
8
|
+
react: a,
|
|
9
|
+
tagName: "pie-pagination",
|
|
10
|
+
events: {
|
|
11
|
+
onPiePaginationPageChange: "pie-pagination-page-change",
|
|
12
|
+
// when the user interacts with a pagination control.
|
|
13
|
+
onPiePaginationPrev: "pie-pagination-prev",
|
|
14
|
+
// when the user clicks the "previous" control.
|
|
15
|
+
onPiePaginationNext: "pie-pagination-next"
|
|
16
|
+
// when the user clicks the "next" control.
|
|
17
|
+
}
|
|
18
|
+
}), P = n;
|
|
19
|
+
export {
|
|
20
|
+
r as ON_NEXT_EVENT,
|
|
21
|
+
m as ON_PAGE_CHANGE_EVENT,
|
|
22
|
+
N as ON_PREV_EVENT,
|
|
23
|
+
P as PiePagination,
|
|
24
|
+
E as defaultProps
|
|
25
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justeattakeaway/pie-pagination",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "PIE design system pagination built using web components",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/justeattakeaway/pie",
|
|
8
|
+
"directory": "packages/components/pie-pagination"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://webc.pie.design/?path=/docs/components-pagination--overview",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"module": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"custom-elements.json",
|
|
17
|
+
"src",
|
|
18
|
+
"dist",
|
|
19
|
+
"**/*.d.ts"
|
|
20
|
+
],
|
|
21
|
+
"pieMetadata": {
|
|
22
|
+
"componentStatus": "alpha",
|
|
23
|
+
"replaces": {
|
|
24
|
+
"snacks": []
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "run -T vite build",
|
|
29
|
+
"build:react-wrapper": "run -T build-react-wrapper",
|
|
30
|
+
"create:manifest": "run -T cem analyze --litelement",
|
|
31
|
+
"lint:scripts": "run -T eslint .",
|
|
32
|
+
"lint:scripts:fix": "yarn lint:scripts --fix",
|
|
33
|
+
"lint:style": "run -T stylelint ./src/**/*.{css,scss}",
|
|
34
|
+
"lint:style:fix": "yarn lint:style --fix",
|
|
35
|
+
"watch": "run -T vite build --watch",
|
|
36
|
+
"test:browsers": "run -T playwright test -c ./playwright-lit.config.ts",
|
|
37
|
+
"test:browsers:ci": "yarn test:browsers",
|
|
38
|
+
"test:visual": "run -T cross-env-shell PERCY_TOKEN=${PERCY_TOKEN_PIE_PAGINATION} percy exec --allowed-hostname cloudfront.net -- run -T playwright test -c ./playwright-lit-visual.config.ts",
|
|
39
|
+
"test:visual:ci": "yarn test:visual"
|
|
40
|
+
},
|
|
41
|
+
"author": "Just Eat Takeaway.com - Design System Team",
|
|
42
|
+
"license": "Apache-2.0",
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@justeattakeaway/pie-components-config": "0.21.5",
|
|
45
|
+
"@justeattakeaway/pie-css": "1.9.1",
|
|
46
|
+
"@justeattakeaway/pie-monorepo-utils": "0.9.12",
|
|
47
|
+
"@justeattakeaway/pie-wrapper-react": "0.14.5"
|
|
48
|
+
},
|
|
49
|
+
"customElements": "custom-elements.json",
|
|
50
|
+
"sideEffects": [
|
|
51
|
+
"dist/*.js"
|
|
52
|
+
],
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@justeattakeaway/pie-button": "1.15.1",
|
|
55
|
+
"@justeattakeaway/pie-icon-button": "2.8.1",
|
|
56
|
+
"@justeattakeaway/pie-icons-webc": "1.29.5",
|
|
57
|
+
"@justeattakeaway/pie-webc-core": "22.0.1"
|
|
58
|
+
}
|
|
59
|
+
}
|
package/src/defs.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The event name dispatched when the user interacts with a pagination control.
|
|
5
|
+
* The component is fully controlled: it never changes `currentPage` itself, it
|
|
6
|
+
* only tells the consumer which page the user wants to navigate to.
|
|
7
|
+
* @constant
|
|
8
|
+
*/
|
|
9
|
+
export const ON_PAGE_CHANGE_EVENT = 'pie-pagination-page-change';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The event name dispatched when the user clicks the "previous" control.
|
|
13
|
+
* @constant
|
|
14
|
+
*/
|
|
15
|
+
export const ON_PREV_EVENT = 'pie-pagination-prev';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The event name dispatched when the user clicks the "next" control.
|
|
19
|
+
* @constant
|
|
20
|
+
*/
|
|
21
|
+
export const ON_NEXT_EVENT = 'pie-pagination-next';
|
|
22
|
+
|
|
23
|
+
type AriaProps = {
|
|
24
|
+
label?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export interface PaginationProps {
|
|
28
|
+
/**
|
|
29
|
+
* The ARIA attributes for the pagination landmark. Offers a `label` used for
|
|
30
|
+
* the `aria-label` of the wrapping `<nav>` element.
|
|
31
|
+
*/
|
|
32
|
+
aria?: AriaProps;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The currently active page (1-based). This component is fully controlled, so
|
|
36
|
+
* it never updates this value itself; the consumer is responsible for updating
|
|
37
|
+
* it in response to the `pie-pagination-page-change` event.
|
|
38
|
+
* @default 1
|
|
39
|
+
*/
|
|
40
|
+
currentPage?: number;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The total number of pages to render.
|
|
44
|
+
* @default 1
|
|
45
|
+
*/
|
|
46
|
+
totalPages?: number;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* When true, all pagination controls are disabled.
|
|
50
|
+
* @default false
|
|
51
|
+
*/
|
|
52
|
+
disabled?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type DefaultProps = ComponentDefaultProps<PaginationProps, 'currentPage' | 'totalPages' | 'disabled'>;
|
|
56
|
+
|
|
57
|
+
export const defaultProps: DefaultProps = {
|
|
58
|
+
currentPage: 1,
|
|
59
|
+
totalPages: 1,
|
|
60
|
+
disabled: false,
|
|
61
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import {
|
|
2
|
+
html, unsafeCSS, type PropertyValues,
|
|
3
|
+
} from 'lit';
|
|
4
|
+
import { property } from 'lit/decorators.js';
|
|
5
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
6
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
7
|
+
|
|
8
|
+
import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
|
|
9
|
+
import {
|
|
10
|
+
dispatchCustomEvent,
|
|
11
|
+
RtlMixin,
|
|
12
|
+
safeCustomElement,
|
|
13
|
+
} from '@justeattakeaway/pie-webc-core';
|
|
14
|
+
|
|
15
|
+
import '@justeattakeaway/pie-icon-button';
|
|
16
|
+
import '@justeattakeaway/pie-icons-webc/dist/IconChevronLeft.js';
|
|
17
|
+
import '@justeattakeaway/pie-icons-webc/dist/IconChevronRight.js';
|
|
18
|
+
|
|
19
|
+
import styles from './pagination.scss?inline';
|
|
20
|
+
import {
|
|
21
|
+
type PaginationProps,
|
|
22
|
+
defaultProps,
|
|
23
|
+
ON_PAGE_CHANGE_EVENT,
|
|
24
|
+
ON_PREV_EVENT,
|
|
25
|
+
ON_NEXT_EVENT,
|
|
26
|
+
} from './defs';
|
|
27
|
+
|
|
28
|
+
// Valid values available to consumers
|
|
29
|
+
export * from './defs';
|
|
30
|
+
|
|
31
|
+
const componentSelector = 'pie-pagination';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @tagname pie-pagination
|
|
35
|
+
* @event {CustomEvent} pie-pagination-page-change - when the user interacts with a pagination control.
|
|
36
|
+
* @event {CustomEvent} pie-pagination-prev - when the user clicks the "previous" control.
|
|
37
|
+
* @event {CustomEvent} pie-pagination-next - when the user clicks the "next" control.
|
|
38
|
+
*/
|
|
39
|
+
@safeCustomElement('pie-pagination')
|
|
40
|
+
export class PiePagination extends RtlMixin(PieElement) implements PaginationProps {
|
|
41
|
+
@property({ type: Object })
|
|
42
|
+
public aria: PaginationProps['aria'];
|
|
43
|
+
|
|
44
|
+
@property({ type: Number })
|
|
45
|
+
public currentPage = defaultProps.currentPage;
|
|
46
|
+
|
|
47
|
+
@property({ type: Number })
|
|
48
|
+
public totalPages = defaultProps.totalPages;
|
|
49
|
+
|
|
50
|
+
@property({ type: Boolean })
|
|
51
|
+
public disabled = defaultProps.disabled;
|
|
52
|
+
|
|
53
|
+
protected updated (changedProperties: PropertyValues<this>): void {
|
|
54
|
+
if (changedProperties.has('totalPages') && this.totalPages < 1) {
|
|
55
|
+
console.warn(`pie-pagination: "totalPages" must be at least 1, received "${this.totalPages}".`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (changedProperties.has('currentPage') && this.currentPage < 1) {
|
|
59
|
+
console.warn(`pie-pagination: "currentPage" must be at least 1, received "${this.currentPage}".`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (changedProperties.has('currentPage') && this.currentPage > this.totalPages) {
|
|
63
|
+
console.warn(`pie-pagination: "currentPage" (${this.currentPage}) cannot be greater than "totalPages" (${this.totalPages}).`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Emits the page change event with the page the user wants to navigate to.
|
|
69
|
+
* The component never updates `currentPage` itself.
|
|
70
|
+
*
|
|
71
|
+
* @private
|
|
72
|
+
*/
|
|
73
|
+
private _emitPageChange (currentPage: number) {
|
|
74
|
+
dispatchCustomEvent(this, ON_PAGE_CHANGE_EVENT, { currentPage });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Handles a click on the "previous" control.
|
|
79
|
+
*
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
private _handlePreviousClick () {
|
|
83
|
+
if (this.disabled || this.currentPage <= 1) return;
|
|
84
|
+
|
|
85
|
+
const requestedPage = this.currentPage - 1;
|
|
86
|
+
|
|
87
|
+
dispatchCustomEvent(this, ON_PREV_EVENT, { currentPage: requestedPage });
|
|
88
|
+
this._emitPageChange(requestedPage);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Handles a click on the "next" control.
|
|
93
|
+
*
|
|
94
|
+
* @private
|
|
95
|
+
*/
|
|
96
|
+
private _handleNextClick () {
|
|
97
|
+
if (this.disabled || this.currentPage >= this.totalPages) return;
|
|
98
|
+
|
|
99
|
+
const requestedPage = this.currentPage + 1;
|
|
100
|
+
|
|
101
|
+
dispatchCustomEvent(this, ON_NEXT_EVENT, { currentPage: requestedPage });
|
|
102
|
+
this._emitPageChange(requestedPage);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Handles a click on a page number control.
|
|
107
|
+
*
|
|
108
|
+
* @private
|
|
109
|
+
*/
|
|
110
|
+
private _handlePageClick (page: number) {
|
|
111
|
+
if (this.disabled || page === this.currentPage) return;
|
|
112
|
+
this._emitPageChange(page);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Renders the chevron icon for the previous/next controls, mirroring it for RTL.
|
|
117
|
+
*
|
|
118
|
+
* @private
|
|
119
|
+
*/
|
|
120
|
+
private _renderChevronIcon (direction: 'previous' | 'next') {
|
|
121
|
+
const pointsLeft = direction === 'previous' ? !this.isRTL : this.isRTL;
|
|
122
|
+
|
|
123
|
+
return pointsLeft
|
|
124
|
+
? html`<icon-chevron-left></icon-chevron-left>`
|
|
125
|
+
: html`<icon-chevron-right></icon-chevron-right>`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
render () {
|
|
129
|
+
const {
|
|
130
|
+
aria, currentPage, disabled, totalPages,
|
|
131
|
+
} = this;
|
|
132
|
+
|
|
133
|
+
const pages = Array.from({ length: Math.max(totalPages, 0) }, (_, index) => index + 1);
|
|
134
|
+
const isPreviousDisabled = disabled || currentPage <= 1;
|
|
135
|
+
const isNextDisabled = disabled || currentPage >= totalPages;
|
|
136
|
+
|
|
137
|
+
return html`
|
|
138
|
+
<nav
|
|
139
|
+
class="c-pagination"
|
|
140
|
+
aria-label="${aria?.label ?? 'Pagination'}"
|
|
141
|
+
data-test-id="pie-pagination">
|
|
142
|
+
<ol class="c-pagination-list" data-test-id="pie-pagination-list">
|
|
143
|
+
<li class="c-pagination-item">
|
|
144
|
+
<pie-icon-button
|
|
145
|
+
data-test-id="pie-pagination-previous"
|
|
146
|
+
size="xsmall"
|
|
147
|
+
variant="ghost-secondary"
|
|
148
|
+
?disabled="${isPreviousDisabled}"
|
|
149
|
+
.aria="${{ label: 'Previous page' }}"
|
|
150
|
+
@click="${this._handlePreviousClick}">
|
|
151
|
+
${this._renderChevronIcon('previous')}
|
|
152
|
+
</pie-icon-button>
|
|
153
|
+
</li>
|
|
154
|
+
|
|
155
|
+
${pages.map((page) => {
|
|
156
|
+
const isCurrent = page === currentPage;
|
|
157
|
+
const classes = {
|
|
158
|
+
'c-pagination-control': true,
|
|
159
|
+
'c-pagination-control--current': isCurrent,
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
return html`
|
|
163
|
+
<li class="c-pagination-item">
|
|
164
|
+
<button
|
|
165
|
+
type="button"
|
|
166
|
+
class="${classMap(classes)}"
|
|
167
|
+
data-test-id="pie-pagination-page"
|
|
168
|
+
?disabled="${disabled}"
|
|
169
|
+
aria-current="${ifDefined(isCurrent ? 'page' : undefined)}"
|
|
170
|
+
aria-label="Page ${page}"
|
|
171
|
+
@click="${() => this._handlePageClick(page)}">
|
|
172
|
+
${page}
|
|
173
|
+
</button>
|
|
174
|
+
</li>`;
|
|
175
|
+
})}
|
|
176
|
+
|
|
177
|
+
<li class="c-pagination-item">
|
|
178
|
+
<pie-icon-button
|
|
179
|
+
data-test-id="pie-pagination-next"
|
|
180
|
+
size="xsmall"
|
|
181
|
+
variant="ghost-secondary"
|
|
182
|
+
?disabled="${isNextDisabled}"
|
|
183
|
+
.aria="${{ label: 'Next page' }}"
|
|
184
|
+
@click="${this._handleNextClick}">
|
|
185
|
+
${this._renderChevronIcon('next')}
|
|
186
|
+
</pie-icon-button>
|
|
187
|
+
</li>
|
|
188
|
+
</ol>
|
|
189
|
+
</nav>`;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Renders a `CSSResult` generated from SCSS by Vite
|
|
193
|
+
static styles = unsafeCSS(styles);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
declare global {
|
|
197
|
+
interface HTMLElementTagNameMap {
|
|
198
|
+
[componentSelector]: PiePagination;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
@use '@justeattakeaway/pie-css/scss' as p;
|
|
2
|
+
@use '@justeattakeaway/pie-css/scss/mixins/components/button' as btn;
|
|
3
|
+
|
|
4
|
+
:host {
|
|
5
|
+
display: inline-block;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.c-pagination {
|
|
9
|
+
display: inline-block;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.c-pagination-list {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: var(--dt-spacing-b);
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
list-style: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.c-pagination-item {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Page number control.
|
|
27
|
+
// Built from the shared PIE button mixins so it inherits the same typography,
|
|
28
|
+
// interactive states and focus ring as pie-button, but sized as a fixed
|
|
29
|
+
// 32x32 circular control to match the Figma specification.
|
|
30
|
+
.c-pagination-control {
|
|
31
|
+
@include btn.button-base($include-icon-selector: false);
|
|
32
|
+
@include btn.button-size('xsmall');
|
|
33
|
+
@include btn.button-variant('ghost');
|
|
34
|
+
|
|
35
|
+
inline-size: 32px;
|
|
36
|
+
block-size: 32px;
|
|
37
|
+
padding: 0;
|
|
38
|
+
|
|
39
|
+
--btn-font-weight: var(--dt-font-body-s-weight);
|
|
40
|
+
|
|
41
|
+
&.c-pagination-control--current {
|
|
42
|
+
@include btn.button-variant('primary-alternative');
|
|
43
|
+
|
|
44
|
+
--btn-font-weight: var(--dt-font-body-strong-s-weight);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&:disabled {
|
|
48
|
+
--int-states-mixin-bg-color: transparent;
|
|
49
|
+
--btn-text-color: var(--dt-color-content-disabled-solid);
|
|
50
|
+
|
|
51
|
+
cursor: not-allowed;
|
|
52
|
+
}
|
|
53
|
+
}
|
package/src/react.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { createComponent, type EventName } from '@lit/react';
|
|
3
|
+
import { PiePagination as PiePaginationLit } from './index';
|
|
4
|
+
import { type PaginationProps } from './defs';
|
|
5
|
+
|
|
6
|
+
export * from './defs';
|
|
7
|
+
|
|
8
|
+
const PiePaginationReact = createComponent({
|
|
9
|
+
displayName: 'PiePagination',
|
|
10
|
+
elementClass: PiePaginationLit,
|
|
11
|
+
react: React,
|
|
12
|
+
tagName: 'pie-pagination',
|
|
13
|
+
events: {
|
|
14
|
+
onPiePaginationPageChange: 'pie-pagination-page-change' as EventName<CustomEvent>, // when the user interacts with a pagination control.
|
|
15
|
+
onPiePaginationPrev: 'pie-pagination-prev' as EventName<CustomEvent>, // when the user clicks the "previous" control.
|
|
16
|
+
onPiePaginationNext: 'pie-pagination-next' as EventName<CustomEvent>, // when the user clicks the "next" control.
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
type ReactBaseType = React.HTMLAttributes<HTMLElement>;
|
|
21
|
+
|
|
22
|
+
type PiePaginationEvents = {
|
|
23
|
+
onPiePaginationPageChange?: (event: CustomEvent) => void;
|
|
24
|
+
onPiePaginationPrev?: (event: CustomEvent) => void;
|
|
25
|
+
onPiePaginationNext?: (event: CustomEvent) => void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const PiePagination = PiePaginationReact as React.ForwardRefExoticComponent<React.PropsWithChildren<Omit<React.PropsWithoutRef<PaginationProps>, 'children'>>
|
|
29
|
+
& React.RefAttributes<PiePaginationLit> & PiePaginationEvents & ReactBaseType>;
|