fix(input-stepper): add parseNumber and formatNumber to format the va… (#2312)

* fix(input-stepper): add parseNumber and formatNumber to format the value based on locale

* Update packages/ui/components/input-stepper/test/lion-input-stepper.test.js

* Update packages/ui/components/input-stepper/test/lion-input-stepper.test.js
This commit is contained in:
gerjanvangeest 2024-08-07 10:29:02 +02:00 committed by GitHub
parent 58796deb0e
commit cdf0a9e8f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 100 additions and 8 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
[input-stepper] add parseNumber and formatNumber to format the value based on locale

View file

@ -48,3 +48,24 @@ Use `min` and `max` attribute to specify a range.
value="200"
></lion-input-stepper>
```
### Formatting
Just like with the `input-amount` you can add the `formatOptions` to format the numbers to your preferences, to a different locale or adjust the amount of fractions.
```js preview-story
export const formatting = () => {
const format = { locale: 'nl-NL' };
return html`
<lion-input-stepper
label="Amount of oranges"
min="0"
max="5000"
step="100"
name="value"
.formatOptions="${format}"
.modelValue="${1200}"
></lion-input-stepper>
`;
};
```

View file

@ -1,5 +1,5 @@
import { html, css, render } from 'lit';
import { LocalizeMixin } from '@lion/ui/localize-no-side-effects.js';
import { formatNumber, LocalizeMixin, parseNumber } from '@lion/ui/localize-no-side-effects.js';
import { LionInput } from '@lion/ui/input.js';
import { IsNumber, MinNumber, MaxNumber } from '@lion/ui/form-core.js';
import { localizeNamespaceLoader } from './localizeNamespaceLoader.js';
@ -52,7 +52,7 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
* @returns {number}
*/
get currentValue() {
return parseFloat(this.value) || 0;
return this.modelValue || 0;
}
get _inputNode() {
@ -62,7 +62,8 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
constructor() {
super();
/** @param {string} modelValue */
this.parser = modelValue => parseFloat(modelValue);
this.parser = parseNumber;
this.formatter = formatNumber;
this.min = Infinity;
this.max = Infinity;
this.step = 1;
@ -229,7 +230,7 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
const { step, min, max } = this.values;
const newValue = this.currentValue + step;
if (newValue <= max || max === Infinity) {
this.value = newValue < min && min !== Infinity ? `${min}` : `${newValue}`;
this.modelValue = newValue < min && min !== Infinity ? `${min}` : `${newValue}`;
this.__toggleSpinnerButtonsState();
this._proxyInputEvent();
}
@ -243,7 +244,7 @@ export class LionInputStepper extends LocalizeMixin(LionInput) {
const { step, min, max } = this.values;
const newValue = this.currentValue - step;
if (newValue >= min || min === Infinity) {
this.value = newValue > max && max !== Infinity ? `${max}` : `${newValue}`;
this.modelValue = newValue > max && max !== Infinity ? `${max}` : `${newValue}`;
this.__toggleSpinnerButtonsState();
this._proxyInputEvent();
}

View file

@ -0,0 +1,20 @@
import {
runInteractionStateMixinSuite,
runFormatMixinSuite,
} from '@lion/ui/form-core-test-suites.js';
import '@lion/ui/define/lion-input-stepper.js';
const tagString = 'lion-input-stepper';
describe('<lion-input-stepper> integrations', () => {
runInteractionStateMixinSuite({
tagString,
allowedModelValueTypes: [Number],
});
runFormatMixinSuite({
tagString,
modelValueType: Number,
});
});

View file

@ -1,6 +1,7 @@
import { expect, fixture as _fixture, nextFrame } from '@open-wc/testing';
import { html } from 'lit/static-html.js';
import sinon from 'sinon';
import { formatNumber } from '@lion/ui/localize-no-side-effects.js';
import '@lion/ui/define/lion-input-stepper.js';
/**
@ -49,6 +50,50 @@ describe('<lion-input-stepper>', () => {
});
});
describe('Formatter', () => {
it('uses formatNumber for formatting', async () => {
const el = await fixture(defaultInputStepper);
expect(el.formatter).to.equal(formatNumber);
});
it('formatNumber uses locale provided in formatOptions', async () => {
let el = await fixture(html`
<lion-input-stepper
.formatOptions="${{ locale: 'en-GB' }}"
.modelValue="${1234.56}"
></lion-input-stepper>
`);
expect(el.formattedValue).to.equal('1,234.56');
el = await fixture(html`
<lion-input-stepper
.formatOptions="${{ locale: 'nl-NL' }}"
.modelValue="${1234.56}"
></lion-input-stepper>
`);
expect(el.formattedValue).to.equal('1.234,56');
});
it('supports overriding decimalSeparator in formatOptions', async () => {
const el = await fixture(
html`<lion-input-stepper
.formatOptions="${{ locale: 'nl-NL', decimalSeparator: '.' }}"
.modelValue="${12.34}"
></lion-input-stepper>`,
);
expect(el.formattedValue).to.equal('12.34');
});
it('supports overriding groupSeparator in formatOptions', async () => {
const el = await fixture(
html`<lion-input-stepper
.formatOptions="${{ locale: 'nl-NL', groupSeparator: ',', decimalSeparator: '.' }}"
.modelValue="${1234.56}"
></lion-input-stepper>`,
);
expect(el.formattedValue).to.equal('1,234.56');
});
});
describe('User interaction', () => {
it('should increment the value to 1 on [ArrowUp]', async () => {
const el = await fixture(defaultInputStepper);
@ -71,7 +116,7 @@ describe('<lion-input-stepper>', () => {
expect(el.value).to.equal('');
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }));
await el.updateComplete;
expect(el.value).to.equal('-1');
expect(el.value).to.equal('1');
});
it('should increment the value to minValue on [ArrowDown] if value is below min', async () => {
@ -95,7 +140,7 @@ describe('<lion-input-stepper>', () => {
expect(el.value).to.equal('');
const decrementButton = el.querySelector('[slot=prefix]');
decrementButton?.dispatchEvent(new Event('click'));
expect(el.value).to.equal('-1');
expect(el.value).to.equal('1');
});
it('fires one "user-input-changed" event on + button click', async () => {
@ -143,7 +188,7 @@ describe('<lion-input-stepper>', () => {
decrementButton?.dispatchEvent(new Event('focus'));
decrementButton?.dispatchEvent(new Event('click'));
decrementButton?.dispatchEvent(new Event('blur'));
expect(el.value).to.equal('-1');
expect(el.value).to.equal('1');
expect(blurSpy.calledOnce).to.be.true;
expect(el.touched).to.be.true;