diff --git a/.changeset/mighty-fans-retire.md b/.changeset/mighty-fans-retire.md new file mode 100644 index 000000000..a71832f0f --- /dev/null +++ b/.changeset/mighty-fans-retire.md @@ -0,0 +1,7 @@ +--- +'@lion/button': patch +'@lion/overlays': patch +'@lion/tooltip': patch +--- + +Types for overlays, tooltip, button diff --git a/.changeset/silly-mayflies-talk.md b/.changeset/silly-mayflies-talk.md new file mode 100644 index 000000000..6b10aaf96 --- /dev/null +++ b/.changeset/silly-mayflies-talk.md @@ -0,0 +1,9 @@ +--- +'@lion/core': minor +--- + +EventTargetShim + +#### Features + +EventTargetShim is a base class that shims EventTarget for full browser support. diff --git a/.changeset/witty-paws-care.md b/.changeset/witty-paws-care.md new file mode 100644 index 000000000..e00b1c7ed --- /dev/null +++ b/.changeset/witty-paws-care.md @@ -0,0 +1,9 @@ +--- +'@lion/core': minor +--- + +EventTargetShim + +#### Features + +EventTargetShim is a base class that works like EventTarget, on all browsers. diff --git a/packages/core/index.d.ts b/packages/core/index.d.ts index 901842b0d..6c2f0acbe 100644 --- a/packages/core/index.d.ts +++ b/packages/core/index.d.ts @@ -17,6 +17,7 @@ export { DisabledWithTabIndexMixin } from './src/DisabledWithTabIndexMixin.js'; export { SlotMixin } from './src/SlotMixin.js'; export { UpdateStylesMixin } from './src/UpdateStylesMixin.js'; export { browserDetection } from './src/browserDetection.js'; +export { EventTargetShim } from './src/EventTargetShim.js'; export { css, CSSResult, diff --git a/packages/core/index.js b/packages/core/index.js index 3e3c95088..0825204b8 100644 --- a/packages/core/index.js +++ b/packages/core/index.js @@ -56,3 +56,4 @@ export { DisabledWithTabIndexMixin } from './src/DisabledWithTabIndexMixin.js'; export { SlotMixin } from './src/SlotMixin.js'; export { UpdateStylesMixin } from './src/UpdateStylesMixin.js'; export { browserDetection } from './src/browserDetection.js'; +export { EventTargetShim } from './src/EventTargetShim.js'; diff --git a/packages/core/src/EventTargetShim.js b/packages/core/src/EventTargetShim.js new file mode 100644 index 000000000..28afc834b --- /dev/null +++ b/packages/core/src/EventTargetShim.js @@ -0,0 +1,33 @@ +export class EventTargetShim { + constructor() { + const delegate = document.createDocumentFragment(); + + /** + * + * @param {string} type + * @param {EventListener} listener + * @param {Object} [opts] + */ + const delegatedAddEventListener = (type, listener, opts) => + delegate.addEventListener(type, listener, opts); + + /** + * @param {string} type + * @param {EventListener} listener + * @param {Object} [opts] + */ + const delegatedRemoveEventListener = (type, listener, opts) => + delegate.removeEventListener(type, listener, opts); + + /** + * @param {Event|CustomEvent} event + */ + const delegatedDispatchEvent = event => delegate.dispatchEvent(event); + + this.addEventListener = delegatedAddEventListener; + + this.removeEventListener = delegatedRemoveEventListener; + + this.dispatchEvent = delegatedDispatchEvent; + } +} diff --git a/packages/core/test/EventTargetShim.js b/packages/core/test/EventTargetShim.js new file mode 100644 index 000000000..7478912a1 --- /dev/null +++ b/packages/core/test/EventTargetShim.js @@ -0,0 +1,41 @@ +import { expect } from '@open-wc/testing'; +import sinon from 'sinon'; +import { EventTargetShim } from '../src/EventTargetShim.js'; + +describe('EventTargetShim', () => { + class NonElementClass extends EventTargetShim {} + + it('implements "addEventListener"', async () => { + const nonElementClass = new NonElementClass(); + const cb = sinon.spy(); + + nonElementClass.addEventListener('my-event', cb); + expect(cb).to.not.have.been.called; + nonElementClass.dispatchEvent(new Event('my-event')); + expect(cb).to.have.been.called; + }); + + it('implements "removeEventListener"', async () => { + const nonElementClass = new NonElementClass(); + const cb = sinon.spy(); + + nonElementClass.addEventListener('my-event', cb); + expect(cb).to.not.have.been.called; + nonElementClass.dispatchEvent(new Event('my-event')); + expect(cb).to.have.been.calledOnce; + + nonElementClass.removeEventListener('my-event', cb); + nonElementClass.dispatchEvent(new Event('my-event')); + expect(cb).to.have.been.calledOnce; + }); + + it('implements "dispatchEvent"', async () => { + const nonElementClass = new NonElementClass(); + const cb = sinon.spy(); + + nonElementClass.addEventListener('my-event', cb); + expect(cb).to.not.have.been.called; + nonElementClass.dispatchEvent(new Event('my-event')); + expect(cb).to.have.been.called; + }); +});