feat(pagination): add types
This commit is contained in:
parent
278798636c
commit
0ed995ad06
4 changed files with 59 additions and 24 deletions
5
.changeset/ninety-vans-cheer.md
Normal file
5
.changeset/ninety-vans-cheer.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@lion/pagination': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Add types for pagination package.
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
import { LitElement, html, css } from '@lion/core';
|
import { LitElement, html, css } from '@lion/core';
|
||||||
import { LocalizeMixin } from '@lion/localize';
|
import { LocalizeMixin } from '@lion/localize';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('lit-html').TemplateResult} TemplateResult
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `LionPagination` is a class for custom Pagination element (`<lion-pagination>` web component).
|
* `LionPagination` is a class for custom Pagination element (`<lion-pagination>` web component).
|
||||||
*
|
*
|
||||||
* @customElement lion-pagination
|
* @customElement lion-pagination
|
||||||
* @extends LitElement
|
|
||||||
*/
|
*/
|
||||||
|
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110
|
||||||
export class LionPagination extends LocalizeMixin(LitElement) {
|
export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
static get styles() {
|
static get styles() {
|
||||||
return css`
|
return css`
|
||||||
|
|
@ -32,7 +37,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
static get localizeNamespaces() {
|
static get localizeNamespaces() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
'lion-pagination': locale => {
|
'lion-pagination': /** @param {string} locale */ locale => {
|
||||||
switch (locale) {
|
switch (locale) {
|
||||||
case 'bg-BG':
|
case 'bg-BG':
|
||||||
return import('../translations/bg.js');
|
return import('../translations/bg.js');
|
||||||
|
|
@ -92,6 +97,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {number} value */
|
||||||
set current(value) {
|
set current(value) {
|
||||||
if (value !== this.current) {
|
if (value !== this.current) {
|
||||||
const oldValue = this.current;
|
const oldValue = this.current;
|
||||||
|
|
@ -101,8 +107,9 @@ export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {number} */
|
||||||
get current() {
|
get current() {
|
||||||
return this.__current;
|
return this.__current || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
@ -144,6 +151,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Go to the specific page
|
* Go to the specific page
|
||||||
|
* @param {number} pageNumber
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
goto(pageNumber) {
|
goto(pageNumber) {
|
||||||
|
|
@ -175,7 +183,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate nav list based on current page selection.
|
* Calculate nav list based on current page selection.
|
||||||
* @returns {Array}
|
* @returns {(number|'...')[]}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
__calculateNavList() {
|
__calculateNavList() {
|
||||||
|
|
@ -190,29 +198,27 @@ export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
const pos5 = this.current + 1;
|
const pos5 = this.current + 1;
|
||||||
// if pos 3 is lower than 4 we have a predefined list of elements
|
// if pos 3 is lower than 4 we have a predefined list of elements
|
||||||
if (pos4 <= 4) {
|
if (pos4 <= 4) {
|
||||||
const list = Array(this.__visiblePages)
|
const list = /** @type {(number|'...')[]} */ ([...Array(this.__visiblePages)].map(
|
||||||
.fill()
|
(_, idx) => start + idx,
|
||||||
.map((_, idx) => start + idx);
|
));
|
||||||
list.push('...');
|
list.push('...');
|
||||||
list.push(this.count);
|
list.push(this.count);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
// if we are close to the end of the list with the current page then we have again a predefined list
|
// if we are close to the end of the list with the current page then we have again a predefined list
|
||||||
if (finish - pos4 <= 3) {
|
if (finish - pos4 <= 3) {
|
||||||
const list = [];
|
const list = /** @type {(number|'...')[]} */ ([]);
|
||||||
list.push(1);
|
list.push(1);
|
||||||
list.push('...');
|
list.push('...');
|
||||||
const listRemaining = Array(this.__visiblePages)
|
const listRemaining = [...Array(this.__visiblePages)].map(
|
||||||
.fill()
|
(_, idx) => this.count - this.__visiblePages + 1 + idx,
|
||||||
.map((_, idx) => this.count - this.__visiblePages + 1 + idx);
|
);
|
||||||
return list.concat(listRemaining);
|
return list.concat(listRemaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [start, '...', pos3, pos4, pos5, '...', finish];
|
return [start, '...', pos3, pos4, pos5, '...', finish];
|
||||||
}
|
}
|
||||||
return Array(finish - start + 1)
|
return [...Array(finish - start + 1)].map((_, idx) => start + idx);
|
||||||
.fill()
|
|
||||||
.map((_, idx) => start + idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -266,7 +272,7 @@ export class LionPagination extends LocalizeMixin(LitElement) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render navigation list
|
* Render navigation list
|
||||||
* @returns {TemplateResult} nav list template
|
* @returns {TemplateResult[]} nav list template
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
_renderNavList() {
|
_renderNavList() {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
import { html, fixture, expect } from '@open-wc/testing';
|
import { html, fixture as _fixture, expect } from '@open-wc/testing';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
|
|
||||||
import '../lion-pagination.js';
|
import '../lion-pagination.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('../src/LionPagination').LionPagination} LionPagination
|
||||||
|
* @typedef {import('lit-html').TemplateResult} TemplateResult
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fixture = /** @type {(arg: TemplateResult) => Promise<LionPagination>} */ (_fixture);
|
||||||
|
|
||||||
describe('Pagination', () => {
|
describe('Pagination', () => {
|
||||||
it('has states for count and current', async () => {
|
it('has states for count and current', async () => {
|
||||||
const el = await fixture(html` <lion-pagination count="4"></lion-pagination> `);
|
const el = await fixture(html` <lion-pagination count="4"></lion-pagination> `);
|
||||||
|
|
@ -17,34 +24,44 @@ describe('Pagination', () => {
|
||||||
|
|
||||||
it('disables the previous button if on first page', async () => {
|
it('disables the previous button if on first page', async () => {
|
||||||
const el = await fixture(html` <lion-pagination count="4"></lion-pagination> `);
|
const el = await fixture(html` <lion-pagination count="4"></lion-pagination> `);
|
||||||
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
|
const buttons = Array.from(
|
||||||
|
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
|
||||||
|
);
|
||||||
expect(buttons[0]).to.has.attribute('disabled');
|
expect(buttons[0]).to.has.attribute('disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('disables the next button if on last page', async () => {
|
it('disables the next button if on last page', async () => {
|
||||||
const el = await fixture(html` <lion-pagination count="4" current="4"></lion-pagination> `);
|
const el = await fixture(html` <lion-pagination count="4" current="4"></lion-pagination> `);
|
||||||
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
|
const buttons = Array.from(
|
||||||
|
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
|
||||||
|
);
|
||||||
expect(buttons[buttons.length - 1]).to.has.attribute('disabled');
|
expect(buttons[buttons.length - 1]).to.has.attribute('disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('User interaction', () => {
|
describe('User interaction', () => {
|
||||||
it('can go to previous page with previous button', async () => {
|
it('can go to previous page with previous button', async () => {
|
||||||
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
|
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
|
||||||
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
|
const buttons = Array.from(
|
||||||
|
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
|
||||||
|
);
|
||||||
buttons[0].click();
|
buttons[0].click();
|
||||||
expect(el.current).to.equal(1);
|
expect(el.current).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can go to next page with next button', async () => {
|
it('can go to next page with next button', async () => {
|
||||||
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
|
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
|
||||||
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
|
const buttons = Array.from(
|
||||||
|
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
|
||||||
|
);
|
||||||
buttons[buttons.length - 1].click();
|
buttons[buttons.length - 1].click();
|
||||||
expect(el.current).to.equal(3);
|
expect(el.current).to.equal(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('goes to the page when clicking on its button', async () => {
|
it('goes to the page when clicking on its button', async () => {
|
||||||
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
|
const el = await fixture(html` <lion-pagination count="6" current="2"></lion-pagination> `);
|
||||||
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
|
const buttons = Array.from(
|
||||||
|
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
|
||||||
|
);
|
||||||
buttons[5].click();
|
buttons[5].click();
|
||||||
expect(el.current).to.equal(5);
|
expect(el.current).to.equal(5);
|
||||||
});
|
});
|
||||||
|
|
@ -54,7 +71,9 @@ describe('Pagination', () => {
|
||||||
const el = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-pagination count="6" current="2" @current-changed=${changeSpy}></lion-pagination>
|
<lion-pagination count="6" current="2" @current-changed=${changeSpy}></lion-pagination>
|
||||||
`);
|
`);
|
||||||
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
|
const buttons = Array.from(
|
||||||
|
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
|
||||||
|
);
|
||||||
const previous = buttons[0];
|
const previous = buttons[0];
|
||||||
const next = buttons[buttons.length - 1];
|
const next = buttons[buttons.length - 1];
|
||||||
const page5 = buttons[5];
|
const page5 = buttons[5];
|
||||||
|
|
@ -77,7 +96,9 @@ describe('Pagination', () => {
|
||||||
const el = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-pagination count="6" current="2" @current-changed=${changeSpy}></lion-pagination>
|
<lion-pagination count="6" current="2" @current-changed=${changeSpy}></lion-pagination>
|
||||||
`);
|
`);
|
||||||
const page2 = el.shadowRoot.querySelector("button[aria-current='true']");
|
const page2 = /** @type {HTMLElement} */ (el.shadowRoot?.querySelector(
|
||||||
|
"button[aria-current='true']",
|
||||||
|
));
|
||||||
page2.click();
|
page2.click();
|
||||||
expect(changeSpy).to.not.be.called;
|
expect(changeSpy).to.not.be.called;
|
||||||
expect(el.current).to.equal(2);
|
expect(el.current).to.equal(2);
|
||||||
|
|
@ -111,7 +132,9 @@ describe('Pagination', () => {
|
||||||
describe('Accessibility', () => {
|
describe('Accessibility', () => {
|
||||||
it('sets aria-current to the current page', async () => {
|
it('sets aria-current to the current page', async () => {
|
||||||
const el = await fixture(html` <lion-pagination count="3"></lion-pagination> `);
|
const el = await fixture(html` <lion-pagination count="3"></lion-pagination> `);
|
||||||
const buttons = Array.from(el.shadowRoot.querySelectorAll('button'));
|
const buttons = Array.from(
|
||||||
|
/** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'),
|
||||||
|
);
|
||||||
// button[0] is the previous button
|
// button[0] is the previous button
|
||||||
expect(buttons[1].getAttribute('aria-current')).to.equal('true');
|
expect(buttons[1].getAttribute('aria-current')).to.equal('true');
|
||||||
expect(buttons[2].getAttribute('aria-current')).to.equal('false');
|
expect(buttons[2].getAttribute('aria-current')).to.equal('false');
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
"packages/listbox/src/*.js",
|
"packages/listbox/src/*.js",
|
||||||
"packages/localize/**/*.js",
|
"packages/localize/**/*.js",
|
||||||
"packages/overlays/**/*.js",
|
"packages/overlays/**/*.js",
|
||||||
|
"packages/pagination/**/*.js",
|
||||||
"packages/radio-group/**/*.js",
|
"packages/radio-group/**/*.js",
|
||||||
"packages/singleton-manager/**/*.js",
|
"packages/singleton-manager/**/*.js",
|
||||||
"packages/tabs/**/*.js",
|
"packages/tabs/**/*.js",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue