@internetarchive/modal-manager 0.3.4 → 0.9.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/modal-manager.d.ts +5 -1
- package/dist/src/modal-manager.js +24 -3
- package/dist/src/modal-manager.js.map +1 -1
- package/dist/src/shoelace/active-elements.d.ts +15 -0
- package/dist/src/shoelace/active-elements.js +27 -0
- package/dist/src/shoelace/active-elements.js.map +1 -0
- package/dist/src/shoelace/modal.d.ts +24 -0
- package/dist/src/shoelace/modal.js +131 -0
- package/dist/src/shoelace/modal.js.map +1 -0
- package/dist/src/shoelace/tabbable.d.ts +9 -0
- package/dist/src/shoelace/tabbable.js +168 -0
- package/dist/src/shoelace/tabbable.js.map +1 -0
- package/dist/test/modal-manager.test.js +2 -2
- package/dist/test/modal-manager.test.js.map +1 -1
- package/dist/test/modal-template.test.js +1 -1
- package/dist/test/modal-template.test.js.map +1 -1
- package/index.html +1 -1
- package/package.json +11 -12
- package/src/modal-manager.ts +30 -3
- package/src/shoelace/active-elements.ts +32 -0
- package/src/shoelace/modal.ts +165 -0
- package/src/shoelace/tabbable.ts +221 -0
- package/test/modal-manager.test.ts +3 -3
- package/test/modal-template.test.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-manager.test.js","sourceRoot":"","sources":["../../test/modal-manager.test.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAkB,IAAI,EAAE,MAAM,KAAK,CAAC;AAE3C,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG7D,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,oBAAoB,EAAE,GAAS,EAAE;QAClC,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAS,EAAE;QACnD,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;6BACL,gBAAgB,CAAC,IAAI;KAC7C,CAAC,CAAiB,CAAC;QAEpB,EAAE,CAAC,kBAAkB,GAAI,KAAmC,CAAC;QAC7D,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9C,EAAE,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,GAAS,EAAE;;QACzD,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;6BACL,gBAAgB,CAAC,IAAI;KAC7C,CAAC,CAAiB,CAAC;QAEpB,MAAM,QAAQ,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAE3C,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QACpC,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAS,EAAE;QACtD,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAEjC,UAAU,CAAC,GAAG,EAAE;YACd,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QACnD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAS,EAAE;QACtD,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,UAAU,CAAC,GAAG,EAAE;YACd,EAAE,CAAC,UAAU,EAAE,CAAC;QAClB,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;QACnD,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,kBAAkB,EAAE,GAAS,EAAE;QAChC,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAS,EAAE;QAC/E,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QAClE,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAChC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC5B,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;QACjE,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAS,EAAE;;QACjF,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC;QACF,EAAE,CAAC,SAAS,CAAC;YACX,MAAM;YACN,uBAAuB,EAAE,QAAQ;SAClC,CAAC,CAAC;QACH,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,QAAQ,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAC3C,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QAEpC,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,GAAS,EAAE;QACpF,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC;QACF,EAAE,CAAC,SAAS,CAAC;YACX,MAAM;YACN,uBAAuB,EAAE,QAAQ;SAClC,CAAC,CAAC;QACH,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QACzB,EAAE,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,GAAS,EAAE;;QACjF,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,MAAM,QAAQ,GAAG,GAAS,EAAE;YAC1B,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC,CAAC;QACF,EAAE,CAAC,SAAS,CAAC;YACX,MAAM;YACN,uBAAuB,EAAE,QAAQ;SAClC,CAAC,CAAC;QACH,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,KAAK,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,0CAAE,aAAa,CAAC,eAAe,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAC3C,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QAEvC,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAS,EAAE;;QAClE,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAEjC,MAAM,KAAK,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAC7D,MAAM,WAAW,GAAG,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,UAAU,0CAAE,aAAa,CAAC,eAAe,CAAC,CAAC;QACtE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAC3C,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QAEvC,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,uEAAuE,EAAE,GAAS,EAAE;;QACrF,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAAiB,CAAC;QAEpB,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACnC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,QAAQ,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAC3C,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QAEpC,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAS,EAAE;;QAC3F,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAA0B,CAAC;QAE7B,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,oBAAoB,GAAG,KAAK,CAAC;QACpC,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,QAAQ,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAC3C,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QAEpC,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAS,EAAE;;QACnD,MAAM,EAAE,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAA;;KAE7B,CAAC,CAA0B,CAAC;QAE7B,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC;QAC9B,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,EAAE,CAAC,CAAC;QAEzB,MAAM,QAAQ,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,YAAY,CAAC,CAAC;QAC5D,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;IAChC,CAAC,CAAA,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { fixture, expect, oneEvent, elementUpdated } from '@open-wc/testing';\nimport { TemplateResult, html } from 'lit';\n\nimport '../src/modal-manager';\nimport { ModalConfig } from '../src/modal-config';\nimport { ModalManager } from '../src/modal-manager';\nimport { ModalManagerMode } from '../src/modal-manager-mode';\nimport { ModalManagerInterface } from '../src/modal-manager-interface';\n\ndescribe('Modal Manager', () => {\n it('defaults to closed', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n expect(el.mode).to.equal('closed');\n });\n\n it('can be closed by calling closeModal', async () => {\n const el = (await fixture(html`\n <modal-manager .mode=${ModalManagerMode.Open}></modal-manager>\n `)) as ModalManager;\n\n el.customModalContent = ('foo' as unknown) as TemplateResult;\n await elementUpdated(el);\n\n expect(el.customModalContent).to.equal('foo');\n el.closeModal();\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n expect(el.customModalContent).to.equal(undefined);\n });\n\n it('can be closed by clicking on the backdrop', async () => {\n const el = (await fixture(html`\n <modal-manager .mode=${ModalManagerMode.Open}></modal-manager>\n `)) as ModalManager;\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n\n backdrop?.dispatchEvent(clickEvent);\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n });\n\n it('emits a modeChanged event when opening', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n\n setTimeout(() => {\n el.showModal({ config });\n });\n const response = await oneEvent(el, 'modeChanged');\n expect(response.detail.mode).to.equal(ModalManagerMode.Open);\n });\n\n it('emits a modeChanged event when closing', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n\n setTimeout(() => {\n el.closeModal();\n });\n const response = await oneEvent(el, 'modeChanged');\n expect(response.detail.mode).to.equal(ModalManagerMode.Closed);\n });\n\n it('can show a modal', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n expect(el.mode).to.equal(ModalManagerMode.Open);\n });\n\n it('sets the --containerHeight CSS property when the window resizes', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n const event = new Event('resize');\n const propBefore = el.style.getPropertyValue('--containerHeight');\n expect(propBefore).to.equal('');\n window.dispatchEvent(event);\n await elementUpdated(el);\n const propAfter = el.style.getPropertyValue('--containerHeight');\n expect(propAfter).to.not.equal('');\n });\n\n it('calls the userClosedModalCallback when the user taps the backdrop', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n let callbackCalled = false;\n const callback = (): void => {\n callbackCalled = true;\n };\n el.showModal({\n config,\n userClosedModalCallback: callback,\n });\n await elementUpdated(el);\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n backdrop?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(callbackCalled).to.equal(true);\n });\n\n it('does not call the userClosedModalCallback when the modal just closes', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n let callbackCalled = false;\n const callback = (): void => {\n callbackCalled = true;\n };\n el.showModal({\n config,\n userClosedModalCallback: callback,\n });\n await elementUpdated(el);\n el.closeModal();\n await elementUpdated(el);\n expect(callbackCalled).to.equal(false);\n });\n\n it('calls the userClosedModalCallback when the user taps the backdrop', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n let callbackCalled = false;\n const callback = (): void => {\n callbackCalled = true;\n };\n el.showModal({\n config,\n userClosedModalCallback: callback,\n });\n await elementUpdated(el);\n\n const modal = el.shadowRoot?.querySelector('modal-template');\n const closeButton = modal?.shadowRoot?.querySelector('.close-button');\n const clickEvent = new MouseEvent('click');\n closeButton?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(callbackCalled).to.equal(true);\n });\n\n it('mode is set to closed when close button is pressed', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n\n expect(el.mode).to.equal('open');\n\n const modal = el.shadowRoot?.querySelector('modal-template');\n const closeButton = modal?.shadowRoot?.querySelector('.close-button');\n const clickEvent = new MouseEvent('click');\n closeButton?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n });\n\n it('allows the user to close by clicking on the backdrop if configured to', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n config.closeOnBackdropClick = true;\n el.showModal({ config });\n await elementUpdated(el);\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n backdrop?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n });\n\n it(\"dont't allow the user to close by clicking on the backdrop if configured to\", async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManagerInterface;\n\n const config = new ModalConfig();\n config.closeOnBackdropClick = false;\n el.showModal({ config });\n await elementUpdated(el);\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n backdrop?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(el.getMode()).to.equal('open');\n });\n\n it('ia logo should not visible on modal', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManagerInterface;\n\n const config = new ModalConfig();\n config.showHeaderLogo = false;\n el.showModal({ config });\n await elementUpdated(el);\n\n const logoIcon = el.shadowRoot?.querySelector('.logo-icon');\n expect(logoIcon).to.not.exist;\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"modal-manager.test.js","sourceRoot":"","sources":["../../test/modal-manager.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { fixture, expect, oneEvent, elementUpdated } from '@open-wc/testing';\nimport { TemplateResult, html } from 'lit';\n\nimport '../src/modal-manager';\nimport { ModalConfig } from '../src/modal-config';\nimport { ModalManager } from '../src/modal-manager';\nimport { ModalManagerMode } from '../src/modal-manager-mode';\nimport { ModalManagerInterface } from '../src/modal-manager-interface';\n\ndescribe('Modal Manager', () => {\n it('defaults to closed', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n expect(el.mode).to.equal('closed');\n });\n\n it('can be closed by calling closeModal', async () => {\n const el = (await fixture(html`\n <modal-manager .mode=${ModalManagerMode.Open}></modal-manager>\n `)) as ModalManager;\n\n el.customModalContent = 'foo' as unknown as TemplateResult;\n await elementUpdated(el);\n\n expect(el.customModalContent).to.equal('foo');\n el.closeModal();\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n expect(el.customModalContent).to.equal(undefined);\n });\n\n it('can be closed by clicking on the backdrop', async () => {\n const el = (await fixture(html`\n <modal-manager .mode=${ModalManagerMode.Open}></modal-manager>\n `)) as ModalManager;\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n\n backdrop?.dispatchEvent(clickEvent);\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n });\n\n it('emits a modeChanged event when opening', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n\n setTimeout(() => {\n el.showModal({ config });\n });\n const response = await oneEvent(el, 'modeChanged', false);\n expect(response.detail.mode).to.equal(ModalManagerMode.Open);\n });\n\n it('emits a modeChanged event when closing', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n\n setTimeout(() => {\n el.closeModal();\n });\n const response = await oneEvent(el, 'modeChanged', false);\n expect(response.detail.mode).to.equal(ModalManagerMode.Closed);\n });\n\n it('can show a modal', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n expect(el.mode).to.equal(ModalManagerMode.Open);\n });\n\n it('sets the --containerHeight CSS property when the window resizes', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n const event = new Event('resize');\n const propBefore = el.style.getPropertyValue('--containerHeight');\n expect(propBefore).to.equal('');\n window.dispatchEvent(event);\n await elementUpdated(el);\n const propAfter = el.style.getPropertyValue('--containerHeight');\n expect(propAfter).to.not.equal('');\n });\n\n it('calls the userClosedModalCallback when the user taps the backdrop', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n let callbackCalled = false;\n const callback = (): void => {\n callbackCalled = true;\n };\n el.showModal({\n config,\n userClosedModalCallback: callback,\n });\n await elementUpdated(el);\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n backdrop?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(callbackCalled).to.equal(true);\n });\n\n it('does not call the userClosedModalCallback when the modal just closes', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n let callbackCalled = false;\n const callback = (): void => {\n callbackCalled = true;\n };\n el.showModal({\n config,\n userClosedModalCallback: callback,\n });\n await elementUpdated(el);\n el.closeModal();\n await elementUpdated(el);\n expect(callbackCalled).to.equal(false);\n });\n\n it('calls the userClosedModalCallback when the user taps the backdrop', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n let callbackCalled = false;\n const callback = (): void => {\n callbackCalled = true;\n };\n el.showModal({\n config,\n userClosedModalCallback: callback,\n });\n await elementUpdated(el);\n\n const modal = el.shadowRoot?.querySelector('modal-template');\n const closeButton = modal?.shadowRoot?.querySelector('.close-button');\n const clickEvent = new MouseEvent('click');\n closeButton?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(callbackCalled).to.equal(true);\n });\n\n it('mode is set to closed when close button is pressed', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n el.showModal({ config });\n await elementUpdated(el);\n\n expect(el.mode).to.equal('open');\n\n const modal = el.shadowRoot?.querySelector('modal-template');\n const closeButton = modal?.shadowRoot?.querySelector('.close-button');\n const clickEvent = new MouseEvent('click');\n closeButton?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n });\n\n it('allows the user to close by clicking on the backdrop if configured to', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManager;\n\n const config = new ModalConfig();\n config.closeOnBackdropClick = true;\n el.showModal({ config });\n await elementUpdated(el);\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n backdrop?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(el.mode).to.equal('closed');\n });\n\n it(\"dont't allow the user to close by clicking on the backdrop if configured to\", async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManagerInterface;\n\n const config = new ModalConfig();\n config.closeOnBackdropClick = false;\n el.showModal({ config });\n await elementUpdated(el);\n\n const backdrop = el.shadowRoot?.querySelector('.backdrop');\n const clickEvent = new MouseEvent('click');\n backdrop?.dispatchEvent(clickEvent);\n\n await elementUpdated(el);\n\n expect(el.getMode()).to.equal('open');\n });\n\n it('ia logo should not visible on modal', async () => {\n const el = (await fixture(html`\n <modal-manager></modal-manager>\n `)) as ModalManagerInterface;\n\n const config = new ModalConfig();\n config.showHeaderLogo = false;\n el.showModal({ config });\n await elementUpdated(el);\n\n const logoIcon = el.shadowRoot?.querySelector('.logo-icon');\n expect(logoIcon).to.not.exist;\n });\n});\n"]}
|
|
@@ -35,7 +35,7 @@ describe('Modal Template', () => {
|
|
|
35
35
|
setTimeout(() => {
|
|
36
36
|
closeButton === null || closeButton === void 0 ? void 0 : closeButton.dispatchEvent(clickEvent);
|
|
37
37
|
});
|
|
38
|
-
const response = yield oneEvent(el, 'closeButtonPressed');
|
|
38
|
+
const response = yield oneEvent(el, 'closeButtonPressed', false);
|
|
39
39
|
expect(response).to.exist;
|
|
40
40
|
}));
|
|
41
41
|
it('shows the processing indicator if configured to', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal-template.test.js","sourceRoot":"","sources":["../../test/modal-template.test.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,mCAAmC,EAAE,GAAS,EAAE;;QACjD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,CAAA,qCAAqC,CAAC,CAAC;QAEpE,MAAM,cAAc,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;QACxE,MAAM,QAAQ,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,WAAW,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,UAAU,CAAgB,CAAC;QAEtE,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;QAC7B,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;QAC3B,oEAAoE;QACpE,MAAM,CAAC,QAAQ,IAAI,cAAe,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAS,EAAE;;QAC3D,MAAM,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC;QAEzB,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,CAAA;gCACD,MAAM;KACjC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;IAC7B,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAS,EAAE;;QAC3E,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,IAAI,CAAA,qCAAqC,CAAC,CAAC;QAEpE,MAAM,WAAW,GAAG,MAAA,EAAE,CAAC,UAAU,0CAAE,aAAa,CAAC,eAAe,CAAC,CAAC;QAClE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QAE3C,UAAU,CAAC,GAAG,EAAE;YACd,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,aAAa,CAAC,UAAU,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,oBAAoB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"modal-template.test.js","sourceRoot":"","sources":["../../test/modal-template.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { fixture, expect, oneEvent } from '@open-wc/testing';\nimport { html } from 'lit';\nimport '../src/modal-template';\nimport { ModalConfig } from '../src/modal-config';\n\ndescribe('Modal Template', () => {\n it('has correct default configuration', async () => {\n const el = await fixture(html` <modal-template></modal-template> `);\n\n const processingLogo = el.shadowRoot?.querySelector('.processing-logo');\n const headline = el.shadowRoot?.querySelector('.headline');\n const message = el.shadowRoot?.querySelector('.message');\n const title = el.shadowRoot?.querySelector('h1.title') as HTMLElement;\n\n expect(headline).to.not.exist;\n expect(message).to.not.exist;\n expect(title).to.not.exist;\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n expect('hidden' in processingLogo!.classList);\n });\n\n it('does not show the title if one not provided', async () => {\n const config = new ModalConfig();\n config.title = undefined;\n\n const el = await fixture(html`\n <modal-template .config=${config}></modal-template>\n `);\n\n const title = el.shadowRoot?.querySelector('h1.title');\n expect(title).to.not.exist;\n });\n\n it('emits closeButtonPressed event when close button is pressed', async () => {\n const el = await fixture(html` <modal-template></modal-template> `);\n\n const closeButton = el.shadowRoot?.querySelector('.close-button');\n const clickEvent = new MouseEvent('click');\n\n setTimeout(() => {\n closeButton?.dispatchEvent(clickEvent);\n });\n const response = await oneEvent(el, 'closeButtonPressed', false);\n expect(response).to.exist;\n });\n\n it('shows the processing indicator if configured to', async () => {\n const config = new ModalConfig();\n config.showProcessingIndicator = true;\n\n const el = await fixture(html`\n <modal-template .config=${config}></modal-template>\n `);\n\n const processingLogo = el.shadowRoot?.querySelector('.processing-logo');\n const classList = processingLogo?.classList ?? [];\n expect('hidden' in classList).to.equal(false);\n });\n\n it('shows the close button if configured to', async () => {\n const config = new ModalConfig();\n config.showCloseButton = true;\n const el = await fixture(html`\n <modal-template .config=${config}></modal-template>\n `);\n\n const closeButton = el.shadowRoot?.querySelector('.close-button');\n expect(closeButton).to.exist;\n });\n\n it('hides the close button if configured to', async () => {\n const config = new ModalConfig();\n config.showCloseButton = false;\n const el = await fixture(html`\n <modal-template .config=${config}></modal-template>\n `);\n\n const closeButton = el.shadowRoot?.querySelector('.close-button');\n expect(closeButton).to.not.exist;\n });\n\n it('shows the properties from the config', async () => {\n const config = new ModalConfig();\n config.title = html`Boop`;\n config.subtitle = html`Bop`;\n config.headline = html`Foo`;\n config.message = html`Bar`;\n\n const el = await fixture(html`\n <modal-template .config=${config}></modal-template>\n `);\n\n const title = el.shadowRoot?.querySelector('h1');\n const subtitle = el.shadowRoot?.querySelector('h2');\n\n const headline = el.shadowRoot?.querySelector('.headline');\n const message = el.shadowRoot?.querySelector('.message');\n\n expect(title).to.exist;\n expect(title?.innerText).to.equal('Boop');\n\n expect(subtitle).to.exist;\n expect(subtitle?.innerText).to.equal('Bop');\n\n expect(headline).to.exist;\n expect(headline?.textContent).to.equal('Foo');\n\n expect(message).to.exist;\n expect(message?.textContent).to.equal('Bar');\n });\n});\n"]}
|
package/index.html
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@internetarchive/modal-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1-alpha.0",
|
|
4
4
|
"description": "A Modal Manager Web Component",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,28 +37,27 @@
|
|
|
37
37
|
"throttle-debounce": "^5.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@open-wc/eslint-config": "^2.
|
|
41
|
-
"@open-wc/testing": "^
|
|
40
|
+
"@open-wc/eslint-config": "^9.2.2",
|
|
41
|
+
"@open-wc/testing": "^4.0.0",
|
|
42
42
|
"@open-wc/testing-karma": "^3.0.0",
|
|
43
43
|
"@types/mocha": "^10.0.0",
|
|
44
44
|
"@types/node": "^20.8.4",
|
|
45
45
|
"@types/throttle-debounce": "^5.0.0",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
47
|
-
"@typescript-eslint/parser": "^
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
|
47
|
+
"@typescript-eslint/parser": "^7.1.0",
|
|
48
48
|
"concurrently": "^8.0.0",
|
|
49
49
|
"deepmerge": "^4.0.0",
|
|
50
50
|
"es-dev-server": "^2.0.0",
|
|
51
|
-
"eslint": "^
|
|
51
|
+
"eslint": "^8.57.0",
|
|
52
52
|
"eslint-config-prettier": "^6.11.0",
|
|
53
|
-
"husky": "^
|
|
53
|
+
"husky": "^9.0.0",
|
|
54
54
|
"lint-staged": "^14.0.1",
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"prettier": "^2.0.4",
|
|
55
|
+
"madge": "^6.0.0",
|
|
56
|
+
"prettier": "^2.7.1",
|
|
58
57
|
"rimraf": "^5.0.5",
|
|
59
|
-
"tslib": "^
|
|
58
|
+
"tslib": "^2.4.0",
|
|
60
59
|
"typedoc": "^0.25.0",
|
|
61
|
-
"typescript": "^4.
|
|
60
|
+
"typescript": "^4.7.4",
|
|
62
61
|
"vite": "^4.4.11"
|
|
63
62
|
},
|
|
64
63
|
"eslintConfig": {
|
package/src/modal-manager.ts
CHANGED
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
} from 'lit';
|
|
9
9
|
import { property, customElement, query } from 'lit/decorators.js';
|
|
10
10
|
|
|
11
|
+
import Modal from './shoelace/modal';
|
|
12
|
+
|
|
11
13
|
import './modal-template';
|
|
12
14
|
import { ModalTemplate } from './modal-template';
|
|
13
15
|
import { ModalConfig } from './modal-config';
|
|
@@ -38,7 +40,7 @@ export class ModalManager extends LitElement implements ModalManagerInterface {
|
|
|
38
40
|
@property({ type: Object }) customModalContent?: TemplateResult;
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
|
-
*
|
|
43
|
+
* This hostBridge handles environmental-specific interactions such as adding classes
|
|
42
44
|
* to the body tag or event listeners needed to support the modal manager in the host environment.
|
|
43
45
|
*
|
|
44
46
|
* There is a default `ModalManagerHostBridge`, but consumers can override it with a custom
|
|
@@ -61,6 +63,20 @@ export class ModalManager extends LitElement implements ModalManagerInterface {
|
|
|
61
63
|
*/
|
|
62
64
|
@query('modal-template') private modalTemplate!: ModalTemplate;
|
|
63
65
|
|
|
66
|
+
// Imported tab handling from shoelace
|
|
67
|
+
public modal = new Modal(this);
|
|
68
|
+
|
|
69
|
+
async firstUpdated(): Promise<void> {
|
|
70
|
+
// Give the browser a chance to paint
|
|
71
|
+
// eslint-disable-next-line no-promise-executor-return
|
|
72
|
+
await new Promise(r => setTimeout(r, 0));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
disconnectedCallback() {
|
|
76
|
+
super.disconnectedCallback();
|
|
77
|
+
this.modal.deactivate();
|
|
78
|
+
}
|
|
79
|
+
|
|
64
80
|
/** @inheritdoc */
|
|
65
81
|
render(): TemplateResult {
|
|
66
82
|
return html`
|
|
@@ -68,7 +84,7 @@ export class ModalManager extends LitElement implements ModalManagerInterface {
|
|
|
68
84
|
<div class="backdrop" @click=${this.backdropClicked}></div>
|
|
69
85
|
<modal-template
|
|
70
86
|
@closeButtonPressed=${this.closeButtonPressed}
|
|
71
|
-
tabindex="
|
|
87
|
+
tabindex="-1"
|
|
72
88
|
>
|
|
73
89
|
${this.customModalContent}
|
|
74
90
|
</modal-template>
|
|
@@ -86,6 +102,7 @@ export class ModalManager extends LitElement implements ModalManagerInterface {
|
|
|
86
102
|
this.mode = ModalManagerMode.Closed;
|
|
87
103
|
this.customModalContent = undefined;
|
|
88
104
|
this.modalTemplate.config = new ModalConfig();
|
|
105
|
+
this.modal.deactivate();
|
|
89
106
|
}
|
|
90
107
|
|
|
91
108
|
/**
|
|
@@ -131,7 +148,17 @@ export class ModalManager extends LitElement implements ModalManagerInterface {
|
|
|
131
148
|
this.customModalContent = options.customModalContent;
|
|
132
149
|
this.mode = ModalManagerMode.Open;
|
|
133
150
|
await this.modalTemplate.updateComplete;
|
|
134
|
-
|
|
151
|
+
|
|
152
|
+
this.modal.activate();
|
|
153
|
+
|
|
154
|
+
// document.addEventListener('keydown', this.tabHandler);
|
|
155
|
+
|
|
156
|
+
// this.firstFocusableElement.focus();
|
|
157
|
+
// console.log('firstFocusableElement', this.firstFocusableElement);
|
|
158
|
+
// console.log('lastFocusableElement', this.lastFocusableElement);
|
|
159
|
+
// console.log('focusableContent', this.focusableContent);
|
|
160
|
+
|
|
161
|
+
// this.modalTemplate.focus();
|
|
135
162
|
}
|
|
136
163
|
|
|
137
164
|
/** @inheritdoc */
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Use a generator so we can iterate and possibly break early.
|
|
3
|
+
* @example
|
|
4
|
+
* // to operate like a regular array. This kinda nullifies generator benefits, but worth knowing if you need the whole array.
|
|
5
|
+
* const allActiveElements = [...activeElements()]
|
|
6
|
+
*
|
|
7
|
+
* // Early return
|
|
8
|
+
* for (const activeElement of activeElements()) {
|
|
9
|
+
* if (<cond>) {
|
|
10
|
+
* break; // Break the loop, dont need to iterate over the whole array or store an array in memory!
|
|
11
|
+
* }
|
|
12
|
+
* }
|
|
13
|
+
*/
|
|
14
|
+
export function* activeElements(
|
|
15
|
+
activeElement: Element | null = document.activeElement
|
|
16
|
+
): Generator<Element> {
|
|
17
|
+
if (activeElement === null || activeElement === undefined) return;
|
|
18
|
+
|
|
19
|
+
yield activeElement;
|
|
20
|
+
|
|
21
|
+
if (
|
|
22
|
+
'shadowRoot' in activeElement &&
|
|
23
|
+
activeElement.shadowRoot &&
|
|
24
|
+
activeElement.shadowRoot.mode !== 'closed'
|
|
25
|
+
) {
|
|
26
|
+
yield* activeElements(activeElement.shadowRoot.activeElement);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function getDeepestActiveElement() {
|
|
31
|
+
return [...activeElements()].pop();
|
|
32
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { activeElements, getDeepestActiveElement } from './active-elements.js';
|
|
2
|
+
import { getTabbableElements } from './tabbable.js';
|
|
3
|
+
|
|
4
|
+
let activeModals: HTMLElement[] = [];
|
|
5
|
+
|
|
6
|
+
export default class Modal {
|
|
7
|
+
element: HTMLElement;
|
|
8
|
+
isExternalActivated: boolean = false;
|
|
9
|
+
tabDirection: 'forward' | 'backward' = 'forward';
|
|
10
|
+
currentFocus: HTMLElement | null = null;
|
|
11
|
+
previousFocus: HTMLElement | null = null;
|
|
12
|
+
elementsWithTabbableControls: string[];
|
|
13
|
+
|
|
14
|
+
constructor(element: HTMLElement) {
|
|
15
|
+
this.element = element;
|
|
16
|
+
|
|
17
|
+
this.elementsWithTabbableControls = ['iframe'];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Activates focus trapping. */
|
|
21
|
+
activate() {
|
|
22
|
+
activeModals.push(this.element);
|
|
23
|
+
document.addEventListener('focusin', this.handleFocusIn);
|
|
24
|
+
document.addEventListener('keydown', this.handleKeyDown);
|
|
25
|
+
document.addEventListener('keyup', this.handleKeyUp);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Deactivates focus trapping. */
|
|
29
|
+
deactivate() {
|
|
30
|
+
activeModals = activeModals.filter(modal => modal !== this.element);
|
|
31
|
+
this.currentFocus = null;
|
|
32
|
+
document.removeEventListener('focusin', this.handleFocusIn);
|
|
33
|
+
document.removeEventListener('keydown', this.handleKeyDown);
|
|
34
|
+
document.removeEventListener('keyup', this.handleKeyUp);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Determines if this modal element is currently active or not. */
|
|
38
|
+
isActive() {
|
|
39
|
+
// The "active" modal is always the most recent one shown
|
|
40
|
+
return activeModals[activeModals.length - 1] === this.element;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Activates external modal behavior and temporarily disables focus trapping. */
|
|
44
|
+
activateExternal() {
|
|
45
|
+
this.isExternalActivated = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Deactivates external modal behavior and re-enables focus trapping. */
|
|
49
|
+
deactivateExternal() {
|
|
50
|
+
this.isExternalActivated = false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private checkFocus() {
|
|
54
|
+
if (this.isActive() && !this.isExternalActivated) {
|
|
55
|
+
const tabbableElements = getTabbableElements(this.element);
|
|
56
|
+
if (!this.element.matches(':focus-within')) {
|
|
57
|
+
const start = tabbableElements[0];
|
|
58
|
+
const end = tabbableElements[tabbableElements.length - 1];
|
|
59
|
+
const target = this.tabDirection === 'forward' ? start : end;
|
|
60
|
+
|
|
61
|
+
if (typeof target?.focus === 'function') {
|
|
62
|
+
this.currentFocus = target;
|
|
63
|
+
target.focus({ preventScroll: false });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private handleFocusIn = () => {
|
|
70
|
+
if (!this.isActive()) return;
|
|
71
|
+
this.checkFocus();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
private possiblyHasTabbableChildren(element: HTMLElement) {
|
|
75
|
+
return (
|
|
76
|
+
this.elementsWithTabbableControls.includes(
|
|
77
|
+
element.tagName.toLowerCase()
|
|
78
|
+
) || element.hasAttribute('controls')
|
|
79
|
+
// Should we add a data-attribute for people to set just in case they have an element where we don't know if it has possibly tabbable elements?
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private handleKeyDown = (event: KeyboardEvent) => {
|
|
84
|
+
if (event.key !== 'Tab' || this.isExternalActivated) return;
|
|
85
|
+
if (!this.isActive()) return;
|
|
86
|
+
|
|
87
|
+
// Because sometimes focus can actually be taken over from outside sources,
|
|
88
|
+
// we don't want to rely on `this.currentFocus`. Instead we check the actual `activeElement` and
|
|
89
|
+
// recurse through shadowRoots.
|
|
90
|
+
const currentActiveElement = getDeepestActiveElement();
|
|
91
|
+
this.previousFocus = currentActiveElement as HTMLElement | null;
|
|
92
|
+
|
|
93
|
+
if (
|
|
94
|
+
this.previousFocus &&
|
|
95
|
+
this.possiblyHasTabbableChildren(this.previousFocus)
|
|
96
|
+
) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (event.shiftKey) {
|
|
101
|
+
this.tabDirection = 'backward';
|
|
102
|
+
} else {
|
|
103
|
+
this.tabDirection = 'forward';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const tabbableElements = getTabbableElements(this.element);
|
|
107
|
+
|
|
108
|
+
let currentFocusIndex = tabbableElements.findIndex(
|
|
109
|
+
el => el === currentActiveElement
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
this.previousFocus = this.currentFocus;
|
|
113
|
+
|
|
114
|
+
const addition = this.tabDirection === 'forward' ? 1 : -1;
|
|
115
|
+
|
|
116
|
+
// eslint-disable-next-line
|
|
117
|
+
while (true) {
|
|
118
|
+
if (currentFocusIndex + addition >= tabbableElements.length) {
|
|
119
|
+
currentFocusIndex = 0;
|
|
120
|
+
} else if (currentFocusIndex + addition < 0) {
|
|
121
|
+
currentFocusIndex = tabbableElements.length - 1;
|
|
122
|
+
} else {
|
|
123
|
+
currentFocusIndex += addition;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.previousFocus = this.currentFocus;
|
|
127
|
+
const nextFocus =
|
|
128
|
+
/** @type {HTMLElement} */ tabbableElements[currentFocusIndex];
|
|
129
|
+
|
|
130
|
+
// This is a special case. We need to make sure we're not calling .focus() if we're already focused on an element
|
|
131
|
+
// that possibly has "controls"
|
|
132
|
+
if (this.tabDirection === 'backward') {
|
|
133
|
+
if (
|
|
134
|
+
this.previousFocus &&
|
|
135
|
+
this.possiblyHasTabbableChildren(this.previousFocus)
|
|
136
|
+
) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (nextFocus && this.possiblyHasTabbableChildren(nextFocus)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
this.currentFocus = nextFocus;
|
|
147
|
+
this.currentFocus?.focus({ preventScroll: false });
|
|
148
|
+
|
|
149
|
+
// Check to make sure focus actually changed. It may not always be the next focus, we just don't want it to be the previousFocus.
|
|
150
|
+
const allActiveElements = [...activeElements()];
|
|
151
|
+
if (
|
|
152
|
+
allActiveElements.includes(this.currentFocus) ||
|
|
153
|
+
!allActiveElements.includes(this.previousFocus!)
|
|
154
|
+
) {
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
setTimeout(() => this.checkFocus());
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
private handleKeyUp = () => {
|
|
163
|
+
this.tabDirection = 'forward';
|
|
164
|
+
};
|
|
165
|
+
}
|