From 0ed995ad06a051cfcd5365b77be7768cd806d195 Mon Sep 17 00:00:00 2001 From: Joren Broekema Date: Wed, 30 Sep 2020 12:15:56 +0200 Subject: [PATCH] feat(pagination): add types --- .changeset/ninety-vans-cheer.md | 5 +++ packages/pagination/src/LionPagination.js | 36 +++++++++------- .../pagination/test/lion-pagination.test.js | 41 +++++++++++++++---- tsconfig.json | 1 + 4 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 .changeset/ninety-vans-cheer.md diff --git a/.changeset/ninety-vans-cheer.md b/.changeset/ninety-vans-cheer.md new file mode 100644 index 000000000..d903cb903 --- /dev/null +++ b/.changeset/ninety-vans-cheer.md @@ -0,0 +1,5 @@ +--- +'@lion/pagination': minor +--- + +Add types for pagination package. diff --git a/packages/pagination/src/LionPagination.js b/packages/pagination/src/LionPagination.js index c5b714877..e6668b92a 100644 --- a/packages/pagination/src/LionPagination.js +++ b/packages/pagination/src/LionPagination.js @@ -1,11 +1,16 @@ import { LitElement, html, css } from '@lion/core'; import { LocalizeMixin } from '@lion/localize'; + +/** + * @typedef {import('lit-html').TemplateResult} TemplateResult + */ + /** * `LionPagination` is a class for custom Pagination element (`` web component). * * @customElement lion-pagination - * @extends LitElement */ +// @ts-expect-error https://github.com/microsoft/TypeScript/issues/40110 export class LionPagination extends LocalizeMixin(LitElement) { static get styles() { return css` @@ -32,7 +37,7 @@ export class LionPagination extends LocalizeMixin(LitElement) { static get localizeNamespaces() { return [ { - 'lion-pagination': locale => { + 'lion-pagination': /** @param {string} locale */ locale => { switch (locale) { case 'bg-BG': return import('../translations/bg.js'); @@ -92,6 +97,7 @@ export class LionPagination extends LocalizeMixin(LitElement) { }; } + /** @param {number} value */ set current(value) { if (value !== this.current) { const oldValue = this.current; @@ -101,8 +107,9 @@ export class LionPagination extends LocalizeMixin(LitElement) { } } + /** @returns {number} */ get current() { - return this.__current; + return this.__current || 0; } constructor() { @@ -144,6 +151,7 @@ export class LionPagination extends LocalizeMixin(LitElement) { /** * Go to the specific page + * @param {number} pageNumber * @public */ goto(pageNumber) { @@ -175,7 +183,7 @@ export class LionPagination extends LocalizeMixin(LitElement) { /** * Calculate nav list based on current page selection. - * @returns {Array} + * @returns {(number|'...')[]} * @private */ __calculateNavList() { @@ -190,29 +198,27 @@ export class LionPagination extends LocalizeMixin(LitElement) { const pos5 = this.current + 1; // if pos 3 is lower than 4 we have a predefined list of elements if (pos4 <= 4) { - const list = Array(this.__visiblePages) - .fill() - .map((_, idx) => start + idx); + const list = /** @type {(number|'...')[]} */ ([...Array(this.__visiblePages)].map( + (_, idx) => start + idx, + )); list.push('...'); list.push(this.count); return 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) { - const list = []; + const list = /** @type {(number|'...')[]} */ ([]); list.push(1); list.push('...'); - const listRemaining = Array(this.__visiblePages) - .fill() - .map((_, idx) => this.count - this.__visiblePages + 1 + idx); + const listRemaining = [...Array(this.__visiblePages)].map( + (_, idx) => this.count - this.__visiblePages + 1 + idx, + ); return list.concat(listRemaining); } return [start, '...', pos3, pos4, pos5, '...', finish]; } - return Array(finish - start + 1) - .fill() - .map((_, idx) => start + idx); + return [...Array(finish - start + 1)].map((_, idx) => start + idx); } /** @@ -266,7 +272,7 @@ export class LionPagination extends LocalizeMixin(LitElement) { /** * Render navigation list - * @returns {TemplateResult} nav list template + * @returns {TemplateResult[]} nav list template * @protected */ _renderNavList() { diff --git a/packages/pagination/test/lion-pagination.test.js b/packages/pagination/test/lion-pagination.test.js index fa8340dfd..c04a38d45 100644 --- a/packages/pagination/test/lion-pagination.test.js +++ b/packages/pagination/test/lion-pagination.test.js @@ -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 '../lion-pagination.js'; +/** + * @typedef {import('../src/LionPagination').LionPagination} LionPagination + * @typedef {import('lit-html').TemplateResult} TemplateResult + */ + +const fixture = /** @type {(arg: TemplateResult) => Promise} */ (_fixture); + describe('Pagination', () => { it('has states for count and current', async () => { const el = await fixture(html` `); @@ -17,34 +24,44 @@ describe('Pagination', () => { it('disables the previous button if on first page', async () => { const el = await fixture(html` `); - 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'); }); it('disables the next button if on last page', async () => { const el = await fixture(html` `); - 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'); }); describe('User interaction', () => { it('can go to previous page with previous button', async () => { const el = await fixture(html` `); - const buttons = Array.from(el.shadowRoot.querySelectorAll('button')); + const buttons = Array.from( + /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'), + ); buttons[0].click(); expect(el.current).to.equal(1); }); it('can go to next page with next button', async () => { const el = await fixture(html` `); - const buttons = Array.from(el.shadowRoot.querySelectorAll('button')); + const buttons = Array.from( + /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'), + ); buttons[buttons.length - 1].click(); expect(el.current).to.equal(3); }); it('goes to the page when clicking on its button', async () => { const el = await fixture(html` `); - const buttons = Array.from(el.shadowRoot.querySelectorAll('button')); + const buttons = Array.from( + /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'), + ); buttons[5].click(); expect(el.current).to.equal(5); }); @@ -54,7 +71,9 @@ describe('Pagination', () => { const el = await fixture(html` `); - const buttons = Array.from(el.shadowRoot.querySelectorAll('button')); + const buttons = Array.from( + /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'), + ); const previous = buttons[0]; const next = buttons[buttons.length - 1]; const page5 = buttons[5]; @@ -77,7 +96,9 @@ describe('Pagination', () => { const el = await fixture(html` `); - const page2 = el.shadowRoot.querySelector("button[aria-current='true']"); + const page2 = /** @type {HTMLElement} */ (el.shadowRoot?.querySelector( + "button[aria-current='true']", + )); page2.click(); expect(changeSpy).to.not.be.called; expect(el.current).to.equal(2); @@ -111,7 +132,9 @@ describe('Pagination', () => { describe('Accessibility', () => { it('sets aria-current to the current page', async () => { const el = await fixture(html` `); - const buttons = Array.from(el.shadowRoot.querySelectorAll('button')); + const buttons = Array.from( + /** @type {ShadowRoot} */ (el.shadowRoot).querySelectorAll('button'), + ); // button[0] is the previous button expect(buttons[1].getAttribute('aria-current')).to.equal('true'); expect(buttons[2].getAttribute('aria-current')).to.equal('false'); diff --git a/tsconfig.json b/tsconfig.json index fe9a45862..6d0c71db3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -34,6 +34,7 @@ "packages/listbox/src/*.js", "packages/localize/**/*.js", "packages/overlays/**/*.js", + "packages/pagination/**/*.js", "packages/radio-group/**/*.js", "packages/singleton-manager/**/*.js", "packages/tabs/**/*.js",