From c2147949a8886bd8416ab32333a7e1d4366ed607 Mon Sep 17 00:00:00 2001 From: Sasha Firsov Date: Sat, 5 Aug 2023 14:19:49 -0700 Subject: [PATCH 1/2] callback typings for on/addEventListener --- src/CssChain.d.ts | 93 ++++++++++++++++++++----------------- test/CssChain-types.test.ts | 62 +++++++++++-------------- 2 files changed, 78 insertions(+), 77 deletions(-) diff --git a/src/CssChain.d.ts b/src/CssChain.d.ts index 61174a9..f206ad9 100644 --- a/src/CssChain.d.ts +++ b/src/CssChain.d.ts @@ -8,105 +8,112 @@ import { HTMLElementMixin as AnyElement } from './HTMLElementMixin'; * @param el Node|Node[] css selector to be applied on node(s) * @param protoArr prototype(s) for members and methods of CssChain */ -export function CssChain(css?: string|AnyElement|Array|HTMLElement, el?: Document|Node|Node[], protoArr?: string|T|string[]): CssChainCollection&T; +export function CssChain(css?: string|AnyElement|Array|HTMLElement, el?: Document|Node|Node[], protoArr?: string|T|string[]): CssChainT; /** CssChain as Array and HTMLElementMixin dual interface */ export type CssChainT = CssChainCollection & T; - +interface CssChainEvent extends Omit{ + target:T +} /** CssChain Array part */ -export interface CssChainCollection extends Array, AnyElement +export interface CssChainCollection extends Array, Omit { - forEach(callbackfn: (value: AnyElement&T, index: number, array: CssChainCollection) => void, thisArg?: any) : CssChainCollection; + forEach(callbackFn: (value: AnyElement&T, index: number, array: CssChainT) => void, thisArg?: any) : CssChainT; /** (alias for `getAttribute`) returns 1st element attribute value or `undefined` for empty collection */ - attr(name:string): CssChainCollection; + attr(name:string): CssChainT; /** (alias for `setAttribute`) sets elements attribute, returns CssChain */ - attr(name:string, value:string): CssChainCollection; + attr(name:string, value:string): CssChainT; /** (alias for `setAttribute`) sets elements attribute with value from callback, returns CssChain */ - attr(name:string, valueCallback:( (el:T, i:number, arr:CssChainCollection)=>string) ): CssChainCollection; - /** (alias for `setAttribute`) sets `css`-defined sub-tree elements attribute, returns CssChain */ - attr(name:string, valueOrCallback:string | ( (el:T, i:number, arrCss:CssChainCollection, arrThis:CssChainCollection)=>string), css:string): CssChainCollection; + attr(name:string, valueCallback:( (el:T, i:number, arr:CssChainCollection)=>string) ): CssChainT; + /** (alias for `setAttribute`) sets `css`-defined subtree elements attribute, returns CssChain */ + attr(name:string, valueOrCallback:string | ( (el:T, i:number, arrCss:CssChainCollection, arrThis:CssChainCollection)=>string), css:string): CssChainT; /** returns 1st element property value or `undefined` for empty collection */ prop(name:string): any; /** sets elements property, returns CssChain */ - prop(name:string, valueOrCallback:any | ( (el:T, i:number, arr:CssChainCollection)=>string)): CssChainCollection; - /** sets `css`-defined sub-tree elements property, returns CssChain */ - prop(name:string, valueOrCallback:any | ( (el:T, i:number, arrCss:CssChainCollection, arrThis:CssChainCollection)=>string), css:string): CssChainCollection; + prop(name:string, valueOrCallback:any | ( (el:T, i:number, arr:CssChainCollection)=>string)): CssChainT; + /** sets `css`-defined subtree elements property, returns CssChain */ + prop(name:string, valueOrCallback:any | ( (el:T, i:number, arrCss:CssChainCollection, arrThis:CssChainCollection)=>string), css:string): CssChainT; /** selects 1st elements by @param css string from each collection element, returns CssChain */ querySelector(css: string): CssChainT; /** selects child elements by @param css string, returns CssChain */ querySelectorAll(css: string): CssChainT; /** alias to [querySelectorAll](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll) */ - $(css: string): CssChainCollection; + $(css: string): CssChainT; /** set of parents of current set which [matches](https://developer.mozilla.org/en-US/docs/Web/API/Element/matches) the selector, duplications removed */ - parent(css: string): CssChainCollection; + parent(css: string): CssChainT; + + addEventListener(type: K, listener: (this: T, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions):CssChainT; /** alias to [addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) */ - on( eventName:string, listener: (ev: Event) => any ): CssChainCollection; + on( eventName:string, listener: (this:T , ev: CssChainEvent) => any ): CssChainT; + on( eventName:string, listener: (this:E , ev: CssChainEvent) => any ): CssChainT; + on( eventName:string, listener: (this:E ) => any ): CssChainT; + on( eventName:string, listener: (this:T) => any ): CssChainT; /** appends html or node */ append(htmlOrElement: string|string[]|Node|Node[]|CssChainT): CssChainT; /** delete all nodes, returns empty CssChain */ - remove(): CssChainCollection; + remove(): CssChainT; /** alias to [removeEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener) */ - remove(eventName:string,callback:any): CssChainCollection; + remove(eventName:string,callback:any): CssChainT; /** removes content of collection nodes, collection nodes remain */ - erase(): CssChainCollection; + erase(): CssChainT; /** returns text of whole collection */ txt(): string; /** sets text for each element from `val` */ - txt(val: string): CssChainCollection; + txt(val: string): CssChainT; /** sets text for each element from callback */ - txt( valCb: (el:T,i:number,arr:CssChainCollection)=>string): CssChainCollection; + txt( valCb: (el:T,i:number,arr:CssChainCollection)=>string): CssChainT; /** sets text for each element from `val` */ - txt(val: string, css: string|CssChainCollection): CssChainCollection; + txt(val: string, css: string|CssChainCollection): CssChainT; /** sets text for each element from callback */ - txt( valCb: (el:T,i:number,arrCss:CssChainCollection,arrThis:CssChainCollection)=>string, css: string|CssChainCollection): CssChainCollection; + txt( valCb: (el:T,i:number,arrCss:CssChainCollection,arrThis:CssChainCollection)=>string, css: string|CssChainCollection): CssChainT; /** sets text for children elements defined by css, returns original collection */ - txt(val: any, css: string|CssChainCollection): CssChainCollection; + txt(val: any, css: string|CssChainCollection): CssChainT; /** returns concatenated innerHTML of collection */ html(): string; /** sets innerHTML of each collection element */ - html( callback: ((el:T,i:number,arr:CssChainCollection)=>string) ): CssChainCollection; + html( callback: ((el:T,i:number,arr:CssChainCollection)=>string) ): CssChainT; /** sets innerHTML of each collection element */ - html( htmlStr: string): CssChainCollection; + html( htmlStr: string): CssChainT; /** array duplicated within each collection element */ - html( htmlStrArr: string[] | T[] ): CssChainCollection; + html( htmlStrArr: string[] | T[] ): CssChainT; /** sets html for children elements defined by css. `val` type is one of above. Returns original collection */ - html( val: string, css: string ): CssChainCollection; + html( val: string, css: string ): CssChainT; /** returns collection of cloned elements of current one by [Node.cloneNode(deep)](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode) */ cloneNode(...args: any[]): CssChainT; /** clone nodes(deep) or objects(shallow). Returns cloned collection */ - clone(): CssChainCollection; + clone(): CssChainT; /** clone nodes to be inserted into document using [Document.importNode()](https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode) */ - clone(doc:Document): CssChainCollection; + clone(doc:Document): CssChainT; /** when callback result is a string or node it is used as return value */ - clone(count: number, cb: ((clonedNode:T, index:number)=>void) ): CssChainCollection; + clone(count: number, cb: ((clonedNode:T, index:number)=>void) ): CssChainT; /** alias of `clone(arr.length) */ - clone( arr: any[] | CssChainCollection ): CssChainCollection; + clone( arr: any[] | CssChainCollection ): CssChainT; /** call callback after clone */ - clone( arr: any[] | CssChainCollection, callback:(( clonedNode:T, dataItem:any, index:number, arr:any[] )=>void) ): CssChainCollection; + clone( arr: any[] | CssChainCollection, callback:(( clonedNode:T, dataItem:any, index:number, arr:any[] )=>void) ): CssChainT; /** append HTML text or nodes */ - append( html:string | string[] | Node[] | CssChainT ): CssChainCollection; + append( html:string | string[] | Node[] | CssChainT ): CssChainT; /** returns all slots */ - slots(): CssChainCollection; + slots(): CssChainT; /** `slots('')` - returns slot without name
* `slots(',name1,name2...')` - returns named slots. Blank name defines unnamed(default) slot */ - slots(nameCsv:string): CssChainCollection; + slots(nameCsv:string): CssChainT; /** slots(name, val | cb(el,i,arr) )` assigns slot content, alias to [HTMLSlotElement.assign(nodes)](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSlotElement/assign) when `cb` is defined slots content is set by `html(cb)` */ - slots(nameCsv:string, val: string|Node|(((name:string,i:number,arr:CssChainCollection)=>string))): CssChainCollection; + slots(nameCsv:string, val: string|Node|(((name:string,i:number,arr:CssChainCollection)=>string))): CssChainT; /** would render the current node as a template with immediate children with `slot='xxx'` as assignedNodes payload for ``. There is no default slot in such case as the inner DOM serves the default content. */ - template(): CssChainCollection; + template(): CssChainT; /** typically `template('template')` would extract the template defined by selector, clone it with assigned slots from remaining children */ - template(css:string): CssChainCollection; + template(css:string): CssChainT; /** the children are used as slot content within node clone which is set as a child */ - template(node:Node): CssChainCollection; + template(node:Node): CssChainT; /** returns a sequence of the elements assigned to this slot (and no other nodes). * @@ -124,13 +131,13 @@ export interface CssChainCollection extends Array, AnyElement assignedNodes(f: any): CssChainT; /** retrieves firstElementChild for each collection element */ - get firstElementChild(): CssChainCollection; + get firstElementChild(): CssChainT; /** retrieves firstChild for each collection element */ - get firstChild(): CssChainCollection; + get firstChild(): CssChainT; /** retrieves child nodes for each collection element */ - get childNodes(): CssChainCollection; + get childNodes(): CssChainT; /** retrieves children nodes for each collection element */ - get children(): CssChainCollection; + get children(): CssChainT; } export default CssChain; diff --git a/test/CssChain-types.test.ts b/test/CssChain-types.test.ts index 254e23f..84d6eef 100644 --- a/test/CssChain-types.test.ts +++ b/test/CssChain-types.test.ts @@ -56,7 +56,7 @@ class DemoElement extends HTMLElement { window.customElements.define( 'demo-element', DemoElement); describe('CssChain', () => { - const isBlankNodeSet = ($X:CssChainT) => { + const isBlankNodeSet = ($X: CssChainT) => { expect(Array.isArray($X)).to.equal(true); expect($X).to.be.an('array'); expect($X.length).to.equal(0); @@ -125,7 +125,7 @@ describe('CssChain', () => { it('checked in checkbox with click and click handlers', async () => { const el = await fixture(html`
`); - const $X = $$('input', el); + const $X = $$('input', el); expect($X[0].checked).to.equal(false); expect($X.checked).to.equal(false); @@ -143,25 +143,24 @@ describe('CssChain', () => { expect($X.checked).to.equal(false); expect($X[1].checked).to.equal(false); - $X.addEventListener('click', function (this:DemoElement) { - this.calledFromClick = true; + $X.addEventListener('click', function (this:HTMLInputElement) { + this.value = 'clicked'; }) - .addEventListener('change', function () { - // @ts-ignore - this.calledFromChange = 'checked=' + this.checked; - }) - .click(); + .addEventListener('change', function () { + this.title = 'checked=' + this.checked; + }) + .click(); - expect($X[0].calledFromClick).to.equal(true); - expect($X[1].calledFromClick).to.equal(true); + expect($X[0].value).to.equal('clicked'); + expect($X[1].value).to.equal('clicked'); - expect($X[0].calledFromChange).to.equal('checked=true'); - expect($X[1].calledFromChange).to.equal('checked=true'); + expect($X[0].title).to.equal('checked=true'); + expect($X[1].title).to.equal('checked=true'); }); it('$.on(evName, cb )', async () => { const el = await fixture(html`
`); - const $X = $$('input', el); + const $X = $$('input', el); expect($X[0].checked).to.equal(false); expect($X.checked).to.equal(false); @@ -179,21 +178,18 @@ describe('CssChain', () => { expect($X.checked).to.equal(false); expect($X[1].checked).to.equal(false); - $X.on('click', function () { - // @ts-ignore - this.calledFromClick = true; - }) - .on('change', function () { - // @ts-ignore - this.calledFromChange = 'checked=' + this.checked; - }) + expect($X[0].value).to.equal('1'); + expect($X[1].value).to.equal('2'); + + $X .on('click', ev=>ev.target.title = "clicked") + .on('change', ev=>ev.target.value = 'checked=' + ev.target.checked) .click(); - expect($X[0].calledFromClick).to.equal(true); - expect($X[1].calledFromClick).to.equal(true); + expect($X[0].title).to.equal('clicked'); + expect($X[1].title).to.equal('clicked'); - expect($X[0].calledFromChange).to.equal('checked=true'); - expect($X[1].calledFromChange).to.equal('checked=true'); + expect($X[0].value).to.equal('checked=true'); + expect($X[1].value).to.equal('checked=true'); }); it('custom element from import', async () => { const el = await fixture(html` @@ -282,13 +278,12 @@ describe('CssChain', () => {
`); const $X = $$('input', el); - function markClick() { - // @ts-ignore + function markClick(this:HTMLInputElement) { this.name = 'clicked'; } $X.on('click', markClick) - .click(); + .click(); // ON expect($X[0].name).to.equal('clicked'); expect($X[1].name).to.equal('clicked'); @@ -297,17 +292,16 @@ describe('CssChain', () => { $X.name = "false"; $X.on('click', function () { - // @ts-ignore - this.title = 'changed' + this.title = 'changed='+this.checked }); $X.remove('click', markClick); - $X.click(); + $X.click(); // OFF expect($X[0].name).to.equal('false'); expect($X[1].name).to.equal('false'); - expect($X[0].title).to.equal('changed'); - expect($X[1].title).to.equal('changed'); + expect($X[0].title).to.equal('changed=false'); + expect($X[1].title).to.equal('changed=false'); }); it('$(el)', async () => { From 3bdda04fca388554c5e58bd1b64f3558e0bdce49 Mon Sep 17 00:00:00 2001 From: Sasha Firsov Date: Sat, 5 Aug 2023 14:36:42 -0700 Subject: [PATCH 2/2] 1.1.9 callback typings for on/addEventListener, chain return type unified --- README.md | 10 +- coverage/lcov-report/ApiChain.js.html | 2 +- coverage/lcov-report/CssChain.js.html | 2 +- coverage/lcov-report/CssChainElement.js.html | 2 +- .../lcov-report/css-chain-element.js.html | 2 +- coverage/lcov-report/index.html | 2 +- coverage/lcov-report/slots-in-shadow.js.html | 2 +- .../lcov-report/slots-light-vs-shadow.js.html | 2 +- dist/CssChain.d.ts | 93 ++++++++++--------- package-lock.json | 18 ++-- package.json | 4 +- 11 files changed, 73 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index fed06ae..4db238d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Collection API inherits the element API and Array. [![NPM version][npm-image]][npm-url] [![coverage][coverage-image]][coverage-url] ## Live demo -https://unpkg.com/css-chain-test@1.1.8/dist/demo.html +https://unpkg.com/css-chain-test@1.1.9/dist/demo.html # [CssChain](https://github.com/sashafirsov/css-chain/blob/main/CssChain.js) ## html elements methods @@ -132,7 +132,7 @@ If you customize the configuration a lot, you can consider moving them to indivi [npm-image]: https://img.shields.io/npm/v/css-chain.svg [npm-url]: https://npmjs.org/package/css-chain-test -[coverage-image]: https://unpkg.com/css-chain-test@1.1.8/coverage/coverage.svg -[coverage-url]: https://unpkg.com/css-chain-test@1.1.8/coverage/lcov-report/index.html -[PokeApi-explorer-image]: https://unpkg.com/css-chain-test@1.1.8/src/PokeApi-Explorer.png -[PokeApi-explorer-url]: https://unpkg.com/css-chain-test@1.1.8/dist/PokeApi-Explorer.html +[coverage-image]: https://unpkg.com/css-chain-test@1.1.9/coverage/coverage.svg +[coverage-url]: https://unpkg.com/css-chain-test@1.1.9/coverage/lcov-report/index.html +[PokeApi-explorer-image]: https://unpkg.com/css-chain-test@1.1.9/src/PokeApi-Explorer.png +[PokeApi-explorer-url]: https://unpkg.com/css-chain-test@1.1.9/dist/PokeApi-Explorer.html diff --git a/coverage/lcov-report/ApiChain.js.html b/coverage/lcov-report/ApiChain.js.html index 4cfa57a..4f5a3a3 100644 --- a/coverage/lcov-report/ApiChain.js.html +++ b/coverage/lcov-report/ApiChain.js.html @@ -295,7 +295,7 @@

All files ApiChain.js