fix(core): add DisabledWithTabIndexMixin to manage disabled and tabindex
This commit is contained in:
parent
0d64792ff5
commit
e5b174e7b9
3 changed files with 194 additions and 0 deletions
|
|
@ -52,3 +52,4 @@ export { DomHelpersMixin } from './src/DomHelpersMixin.js';
|
|||
export { LionSingleton } from './src/LionSingleton.js';
|
||||
export { SlotMixin } from './src/SlotMixin.js';
|
||||
export { DisabledMixin } from './src/DisabledMixin.js';
|
||||
export { DisabledWithTabIndexMixin } from './src/DisabledWithTabIndexMixin.js';
|
||||
|
|
|
|||
86
packages/core/src/DisabledWithTabIndexMixin.js
Normal file
86
packages/core/src/DisabledWithTabIndexMixin.js
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import { dedupeMixin } from './dedupeMixin.js';
|
||||
import { DisabledMixin } from './DisabledMixin.js';
|
||||
|
||||
/**
|
||||
* #DisabledWithTabIndexMixin
|
||||
*
|
||||
* @polymerMixin
|
||||
* @mixinFunction
|
||||
*/
|
||||
export const DisabledWithTabIndexMixin = dedupeMixin(
|
||||
superclass =>
|
||||
// eslint-disable-next-line no-shadow
|
||||
class DisabledWithTabIndexMixin extends DisabledMixin(superclass) {
|
||||
static get properties() {
|
||||
return {
|
||||
// we use a property here as if we use the native tabIndex we can not set a default value
|
||||
// in the constructor as it synchronously sets the attribute which is not allowed in the
|
||||
// constructor phase
|
||||
tabIndex: {
|
||||
type: Number,
|
||||
reflect: true,
|
||||
attribute: 'tabindex',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.__isUserSettingTabIndex = true;
|
||||
|
||||
this.__restoreTabIndexTo = 0;
|
||||
this.__internalSetTabIndex(0);
|
||||
}
|
||||
|
||||
makeRequestToBeDisabled() {
|
||||
super.makeRequestToBeDisabled();
|
||||
if (this.__requestedToBeDisabled === false) {
|
||||
this.__restoreTabIndexTo = this.tabIndex;
|
||||
}
|
||||
}
|
||||
|
||||
retractRequestToBeDisabled() {
|
||||
super.retractRequestToBeDisabled();
|
||||
if (this.__requestedToBeDisabled === true) {
|
||||
this.__internalSetTabIndex(this.__restoreTabIndexTo);
|
||||
}
|
||||
}
|
||||
|
||||
__internalSetTabIndex(value) {
|
||||
this.__isUserSettingTabIndex = false;
|
||||
this.tabIndex = value;
|
||||
this.__isUserSettingTabIndex = true;
|
||||
}
|
||||
|
||||
_requestUpdate(name, oldValue) {
|
||||
super._requestUpdate(name, oldValue);
|
||||
|
||||
if (name === 'disabled') {
|
||||
if (this.disabled) {
|
||||
this.__internalSetTabIndex(-1);
|
||||
} else {
|
||||
this.__internalSetTabIndex(this.__restoreTabIndexTo);
|
||||
}
|
||||
}
|
||||
|
||||
if (name === 'tabIndex') {
|
||||
if (this.__isUserSettingTabIndex) {
|
||||
this.__restoreTabIndexTo = this.tabIndex;
|
||||
}
|
||||
|
||||
if (this.tabIndex !== -1 && this.__requestedToBeDisabled === true) {
|
||||
this.__internalSetTabIndex(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
firstUpdated(changedProperties) {
|
||||
super.firstUpdated(changedProperties);
|
||||
// for ShadyDom the timing is a little different and we need to make sure
|
||||
// the tabindex gets correctly updated here
|
||||
if (this.disabled) {
|
||||
this.__internalSetTabIndex(-1);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
107
packages/core/test/DisabledWithTabIndexMixin.test.js
Normal file
107
packages/core/test/DisabledWithTabIndexMixin.test.js
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
import { expect, fixture, html } from '@open-wc/testing';
|
||||
|
||||
import { LitElement } from '../index.js';
|
||||
import { DisabledWithTabIndexMixin } from '../src/DisabledWithTabIndexMixin.js';
|
||||
|
||||
describe('DisabledWithTabIndexMixin', () => {
|
||||
before(() => {
|
||||
class WithTabIndex extends DisabledWithTabIndexMixin(LitElement) {}
|
||||
customElements.define('can-be-disabled-with-tab-index', WithTabIndex);
|
||||
});
|
||||
|
||||
it('has an initial tabIndex of 0', async () => {
|
||||
const el = await fixture(html`
|
||||
<can-be-disabled-with-tab-index></can-be-disabled-with-tab-index>
|
||||
`);
|
||||
expect(el.tabIndex).to.equal(0);
|
||||
expect(el.getAttribute('tabindex')).to.equal('0');
|
||||
});
|
||||
|
||||
it('sets tabIndex to -1 if disabled', async () => {
|
||||
const el = await fixture(html`
|
||||
<can-be-disabled-with-tab-index></can-be-disabled-with-tab-index>
|
||||
`);
|
||||
el.disabled = true;
|
||||
expect(el.tabIndex).to.equal(-1);
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('-1');
|
||||
});
|
||||
|
||||
it('disabled does not override user provided tabindex', async () => {
|
||||
const el = await fixture(html`
|
||||
<can-be-disabled-with-tab-index tabindex="5" disabled></can-be-disabled-with-tab-index>
|
||||
`);
|
||||
expect(el.getAttribute('tabindex')).to.equal('-1');
|
||||
el.disabled = false;
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('5');
|
||||
});
|
||||
|
||||
it('can be disabled imperatively', async () => {
|
||||
const el = await fixture(html`
|
||||
<can-be-disabled-with-tab-index disabled></can-be-disabled-with-tab-index>
|
||||
`);
|
||||
expect(el.getAttribute('tabindex')).to.equal('-1');
|
||||
|
||||
el.disabled = false;
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('0');
|
||||
expect(el.hasAttribute('disabled')).to.equal(false);
|
||||
|
||||
el.disabled = true;
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('-1');
|
||||
expect(el.hasAttribute('disabled')).to.equal(true);
|
||||
});
|
||||
|
||||
it('will not allow to change tabIndex after makeRequestToBeDisabled()', async () => {
|
||||
const el = await fixture(html`
|
||||
<can-be-disabled-with-tab-index></can-be-disabled-with-tab-index>
|
||||
`);
|
||||
el.makeRequestToBeDisabled();
|
||||
|
||||
el.tabIndex = 5;
|
||||
expect(el.tabIndex).to.equal(-1);
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('-1');
|
||||
});
|
||||
|
||||
it('will restore last tabIndex after retractRequestToBeDisabled()', async () => {
|
||||
const el = await fixture(html`
|
||||
<can-be-disabled-with-tab-index tabindex="5"></can-be-disabled-with-tab-index>
|
||||
`);
|
||||
el.makeRequestToBeDisabled();
|
||||
expect(el.tabIndex).to.equal(-1);
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('-1');
|
||||
el.retractRequestToBeDisabled();
|
||||
expect(el.tabIndex).to.equal(5);
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('5');
|
||||
|
||||
el.makeRequestToBeDisabled();
|
||||
el.tabIndex = 12;
|
||||
el.retractRequestToBeDisabled();
|
||||
expect(el.tabIndex).to.equal(12);
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('12');
|
||||
|
||||
el.makeRequestToBeDisabled();
|
||||
el.tabIndex = 13;
|
||||
el.tabIndex = 14;
|
||||
el.retractRequestToBeDisabled();
|
||||
expect(el.tabIndex).to.equal(14);
|
||||
await el.updateComplete;
|
||||
expect(el.getAttribute('tabindex')).to.equal('14');
|
||||
});
|
||||
|
||||
it('may allow multiple calls to retractRequestToBeDisabled', async () => {
|
||||
const el = await fixture(html`
|
||||
<can-be-disabled-with-tab-index disabled></can-be-disabled-with-tab-index>
|
||||
`);
|
||||
el.retractRequestToBeDisabled();
|
||||
el.retractRequestToBeDisabled();
|
||||
expect(el.disabled).to.be.true;
|
||||
expect(el.tabIndex).to.be.equal(-1);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue