Merge pull request #1054 from ing-bank/fix/input-stepper-slot-usage

fix(input-stepper): make use of prefix and suffix slots
This commit is contained in:
gerjanvangeest 2020-10-28 13:36:01 +01:00 committed by GitHub
commit 7acaf4c047
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 33 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/input-stepper': patch
---
fix(input-stepper): make use of prefix and suffix slots

View file

@ -34,8 +34,6 @@ export class LionInputStepper extends LionInput {
type: Number, type: Number,
reflect: true, reflect: true,
}, },
__disableIncrementor: { attribute: false },
__disableDecrementor: { attribute: false },
}; };
} }
@ -50,8 +48,6 @@ export class LionInputStepper extends LionInput {
super(); super();
/** @param {string} modelValue */ /** @param {string} modelValue */
this.parser = modelValue => parseFloat(modelValue); this.parser = modelValue => parseFloat(modelValue);
this.__disableIncrementor = false;
this.__disableDecrementor = false;
this.min = Infinity; this.min = Infinity;
this.max = Infinity; this.max = Infinity;
this.step = 1; this.step = 1;
@ -104,6 +100,15 @@ export class LionInputStepper extends LionInput {
} }
} }
// @ts-ignore
get slots() {
return {
...super.slots,
prefix: () => this.__getDecrementButtonNode(),
suffix: () => this.__getIncrementButtonNode(),
};
}
/** /**
* Set aria labels and apply validators * Set aria labels and apply validators
* @private * @private
@ -150,8 +155,12 @@ export class LionInputStepper extends LionInput {
*/ */
__toggleSpinnerButtonsState() { __toggleSpinnerButtonsState() {
const { min, max } = this.values; const { min, max } = this.values;
this.__disableIncrementor = this.currentValue >= max && max !== Infinity; const decrementButton = this.__getSlot('prefix');
this.__disableDecrementor = this.currentValue <= min && min !== Infinity; const incrementButton = this.__getSlot('suffix');
const disableIncrementor = this.currentValue >= max && max !== Infinity;
const disableDecrementor = this.currentValue <= min && min !== Infinity;
decrementButton[disableDecrementor ? 'setAttribute' : 'removeAttribute']('disabled', 'true');
incrementButton[disableIncrementor ? 'setAttribute' : 'removeAttribute']('disabled', 'true');
this.setAttribute('aria-valuenow', `${this.currentValue}`); this.setAttribute('aria-valuenow', `${this.currentValue}`);
this.dispatchEvent( this.dispatchEvent(
new CustomEvent('user-input-changed', { new CustomEvent('user-input-changed', {
@ -160,6 +169,19 @@ export class LionInputStepper extends LionInput {
); );
} }
/**
* Get slotted element
* @param {String} slotName - slot name
* @returns {HTMLButtonElement|Object}
*/
__getSlot(slotName) {
return (
/** @type {HTMLElement[]} */ (Array.from(this.children)).find(
child => child.slot === slotName,
) || {}
);
}
/** /**
* Increment the value based on given step or default step value is 1 * Increment the value based on given step or default step value is 1
* @private * @private
@ -186,6 +208,40 @@ export class LionInputStepper extends LionInput {
} }
} }
/**
* Get the increment button node
* @returns {Element|null}
*/
__getIncrementButtonNode() {
const renderParent = document.createElement('div');
/** @type {typeof LionInputStepper} */ (this.constructor).render(
this._incrementorTemplate(),
renderParent,
{
scopeName: this.localName,
eventContext: this,
},
);
return renderParent.firstElementChild;
}
/**
* Get the decrement button node
* @returns {Element|null}
*/
__getDecrementButtonNode() {
const renderParent = document.createElement('div');
/** @type {typeof LionInputStepper} */ (this.constructor).render(
this._decrementorTemplate(),
renderParent,
{
scopeName: this.localName,
eventContext: this,
},
);
return renderParent.firstElementChild;
}
/** /**
* Toggle +/- buttons on change * Toggle +/- buttons on change
* @override * @override
@ -196,61 +252,56 @@ export class LionInputStepper extends LionInput {
} }
/** /**
* Override after template to none * Get the decrementor button sign template
* @override * @returns {String|import('lit-element').TemplateResult}
*/ */
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
_inputGroupAfterTemplate() { _decrementorSignTemplate() {
return html``; return '';
} }
/** /**
* Override before template to none * Get the incrementor button sign template
* @override * @returns {String|import('lit-element').TemplateResult}
*/ */
// eslint-disable-next-line class-methods-use-this // eslint-disable-next-line class-methods-use-this
_inputGroupBeforeTemplate() { _incrementorSignTemplate() {
return html``; return '';
} }
/** /**
* Override prefix template for the increment button * Get the increment button template
* @override * @returns {import('lit-element').TemplateResult}
*/ */
// eslint-disable-next-line class-methods-use-this _decrementorTemplate() {
_inputGroupPrefixTemplate() {
return html` return html`
<button <button
?disabled=${this.disabled || this.readOnly || this.__disableDecrementor} ?disabled=${this.disabled || this.readOnly}
@click=${this.__decrement} @click=${this.__decrement}
tabindex="-1" tabindex="-1"
name="decrement"
type="button" type="button"
aria-label="decrement" aria-label="decrement"
> >
- ${this._decrementorSignTemplate()}
</button> </button>
`; `;
} }
/** /**
* Override suffix template for the decrement button and add after slot * Get the decrement button template
* @override * @returns {import('lit-element').TemplateResult}
*/ */
// eslint-disable-next-line class-methods-use-this _incrementorTemplate() {
_inputGroupSuffixTemplate() {
return html` return html`
<button <button
?disabled=${this.disabled || this.readOnly || this.__disableIncrementor} ?disabled=${this.disabled || this.readOnly}
@click=${this.__increment} @click=${this.__increment}
tabindex="-1" tabindex="-1"
name="increment"
type="button" type="button"
aria-label="increment" aria-label="increment"
> >
+ ${this._incrementorSignTemplate()}
</button> </button>
<slot name="after"></slot>
`; `;
} }
} }

View file

@ -24,7 +24,7 @@ describe('<lion-input-stepper>', () => {
it('should increment the value to 1 on + button click', async () => { it('should increment the value to 1 on + button click', async () => {
const el = await fixture(defaultInputStepper); const el = await fixture(defaultInputStepper);
expect(el.value).to.equal(''); expect(el.value).to.equal('');
const incrementButton = el.shadowRoot?.querySelector('[name=increment]'); const incrementButton = el.querySelector('[slot=suffix]');
incrementButton?.dispatchEvent(new Event('click')); incrementButton?.dispatchEvent(new Event('click'));
expect(el.value).to.equal('1'); expect(el.value).to.equal('1');
}); });
@ -32,8 +32,8 @@ describe('<lion-input-stepper>', () => {
it('should decrement the value to -1 on - button click', async () => { it('should decrement the value to -1 on - button click', async () => {
const el = await fixture(defaultInputStepper); const el = await fixture(defaultInputStepper);
expect(el.value).to.equal(''); expect(el.value).to.equal('');
const incrementButton = el.shadowRoot?.querySelector('[name=decrement]'); const decrementButton = el.querySelector('[slot=prefix]');
incrementButton?.dispatchEvent(new Event('click')); decrementButton?.dispatchEvent(new Event('click'));
expect(el.value).to.equal('-1'); expect(el.value).to.equal('-1');
}); });
@ -66,7 +66,7 @@ describe('<lion-input-stepper>', () => {
it('updates aria-valuenow when stepper is changed', async () => { it('updates aria-valuenow when stepper is changed', async () => {
const el = await fixture(inputStepperWithAttrs); const el = await fixture(inputStepperWithAttrs);
const incrementButton = el.shadowRoot?.querySelector('[name=increment]'); const incrementButton = el.querySelector('[slot=suffix]');
incrementButton?.dispatchEvent(new Event('click')); incrementButton?.dispatchEvent(new Event('click'));
expect(el).to.have.attribute('aria-valuenow', '1'); expect(el).to.have.attribute('aria-valuenow', '1');
}); });