feat(pagination): add types

This commit is contained in:
Joren Broekema 2020-09-30 12:15:56 +02:00 committed by Thomas Allmer
parent 278798636c
commit 0ed995ad06
4 changed files with 59 additions and 24 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/pagination': minor
---
Add types for pagination package.

View file

@ -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() {

View file

@ -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');

View file

@ -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",