Typing the cents first
The card-terminal keypad: every digit shifts in from the right. Beside it, the same field typed normally — and a counter for how often the caret ended up somewhere you did not put it.
<div class="demo demo--wide">
<div class="pair">
<div class="side">
<p class="demo-hint">Cents first, like a terminal</p>
<input class="demo-input" id="cents" inputmode="numeric">
<p class="demo-hint">Press 1, 2, 3, 4</p>
</div>
<div class="side">
<p class="demo-hint">Typed normally</p>
<input class="demo-input" id="free" inputmode="decimal">
<p class="demo-hint">Type into the middle of it</p>
</div>
</div>
<dl class="demo-kv" id="out"></dl>
<p class="demo-hint">react-number-format #366 and react-input-mask #120 both ask for the left-hand
one. Neither ships it.</p>
</div>
import { createAmountInput } from 'https://www.devix.pk/cdn/oss/amount-input@1.0.0/index.js';
const out = document.getElementById('out');
const freeField = document.getElementById('free');
let jumps = 0;
let caretWas = 0;
const cents = createAmountInput(document.getElementById('cents'), {
currency: 'AED',
locale: 'en-AE',
typing: 'cents',
onChange: () => show(),
});
const free = createAmountInput(freeField, {
currency: 'AED',
locale: 'en-AE',
onChange: () => show(),
});
function show() {
out.innerHTML = `
<div><dt>cents first</dt><dd>${cents.getValue() || '—'}</dd></div>
<div><dt>its minor units</dt><dd>${cents.getMinor() || '—'}</dd></div>
<div><dt>typed normally</dt><dd>${free.getValue() || '—'}</dd></div>
<div><dt>caret surprises</dt><dd>${jumps}</dd></div>`;
}
// Measure the caret rather than claiming it stays put.
freeField.addEventListener('keydown', () => { caretWas = freeField.selectionStart; });
freeField.addEventListener('keyup', (event) => {
if (event.key.length !== 1) return;
const now = freeField.selectionStart;
// One forward for the character, one more if a separator appeared with it.
if (now !== caretWas + 1 && now !== caretWas + 2) jumps += 1;
show();
});
free.setValue('234.00');
show();
@import url('https://www.devix.pk/cdn/oss/amount-input@1.0.0/amount-input.min.css');
.pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.side {
display: flex;
flex-direction: column;
gap: 8px;
padding: 12px;
border: 1px solid var(--demo-line);
border-radius: 12px;
background: var(--demo-surface);
}
.side .demo-input { font-size: 17px; }
.demo-kv dd { font-variant-numeric: tabular-nums; }
@media (max-width: 420px) { .pair { grid-template-columns: 1fr; } }