diff --git a/ember-amount-input/src/components/amount-input.hbs b/ember-amount-input/src/components/amount-input.hbs index a2c43572..1616a44f 100644 --- a/ember-amount-input/src/components/amount-input.hbs +++ b/ember-amount-input/src/components/amount-input.hbs @@ -16,6 +16,7 @@ readonly={{@readonly}} {{on 'keydown' this.onKeyDown}} {{on 'input' this.onInput}} + {{on 'paste' this.onPaste}} {{on 'focusout' this.onFocusOut}} /> \ No newline at end of file diff --git a/ember-amount-input/src/components/amount-input.ts b/ember-amount-input/src/components/amount-input.ts index 976161ff..5349f343 100644 --- a/ember-amount-input/src/components/amount-input.ts +++ b/ember-amount-input/src/components/amount-input.ts @@ -154,6 +154,18 @@ export default class AmountInput extends Component { return true; } + @action + onPaste(event: ClipboardEvent): boolean { + const pastedValue = event.clipboardData?.getData('text'); + const parsedValue = parseFloat(pastedValue?.replace(/\s/g, '') ?? ''); + + if (!isNaN(parsedValue)) { + this.args.update(parsedValue.toFixed(this.numberOfDecimal)); + } + + return true; + } + @action onFocusOut(event: FocusEvent): boolean { if (event.target instanceof HTMLInputElement) { diff --git a/test-app/tests/integration/components/amount-input/component-test.ts b/test-app/tests/integration/components/amount-input/component-test.ts index 878c69e9..9a8485d1 100644 --- a/test-app/tests/integration/components/amount-input/component-test.ts +++ b/test-app/tests/integration/components/amount-input/component-test.ts @@ -3,6 +3,7 @@ import { setupRenderingTest } from 'ember-qunit'; import { blur, fillIn, render, typeIn } from '@ember/test-helpers'; import { hbs } from 'ember-cli-htmlbars'; import type { TestContext as TestContextBase } from '@ember/test-helpers'; +import { simulateUserPasteValue } from './helpers/paste-value'; interface TestContext extends TestContextBase { value: number | string; @@ -105,7 +106,7 @@ module('Integration | Component | amount-input', function (hooks) { await render(hbs` `); @@ -185,4 +186,40 @@ module('Integration | Component | amount-input', function (hooks) { assert.dom('input').hasValue('61'); }); + + module('when user pastes a value with spaces', function () { + module('and the value contains spaces', function () { + test('calls update with the formatted value on blur without the spaces', async function (assert) { + await render(hbs` + + `); + + await simulateUserPasteValue('input', '1 061,00'); + + assert.dom('input').hasValue('1061.00'); + + await simulateUserPasteValue('input', ' 1 061'); + + assert.dom('input').hasValue('1061.00'); + }); + }); + + module('and the value is not a valid amount', function () { + test('calls update with an empty string value', async function (assert) { + await render(hbs` + + `); + + await simulateUserPasteValue('input', 'foo'); + + assert.dom('input').hasValue(''); + }); + }); + }); }); diff --git a/test-app/tests/integration/components/amount-input/helpers/paste-value.ts b/test-app/tests/integration/components/amount-input/helpers/paste-value.ts new file mode 100644 index 00000000..e9566019 --- /dev/null +++ b/test-app/tests/integration/components/amount-input/helpers/paste-value.ts @@ -0,0 +1,21 @@ +import { triggerEvent } from '@ember/test-helpers'; +import type { Target } from '@ember/test-helpers'; + +/** + * Simulates a user pasting a value into a target element. + * + * @param {Target} target - The target element to paste the value into + * @param {string} value - The value to paste + * @return {Promise} A Promise that resolves when the paste event is triggered + */ +export function simulateUserPasteValue( + target: Target, + value: string, +): Promise { + const getData = (): string => value; + return triggerEvent(target, 'paste', { + clipboardData: { + getData, + }, + }); +}