diff --git a/v2/pink-sb/src/lib/input/Number.svelte b/v2/pink-sb/src/lib/input/Number.svelte
index 254a417e3c..c84b066d8b 100644
--- a/v2/pink-sb/src/lib/input/Number.svelte
+++ b/v2/pink-sb/src/lib/input/Number.svelte
@@ -44,12 +44,15 @@
let bigintMode = false;
let minAttr: NativeNumber = undefined;
let maxAttr: NativeNumber = undefined;
+ let inputValue = '';
let input: HTMLInputElement;
const dispatch = createEventDispatcher();
- $: if (typeof value === 'bigint' || typeof value === 'number') {
- bigintMode = typeof value === 'bigint';
+ $: bigintMode = typeof value === 'bigint';
+
+ function valueToDisplayString(v: ExtendedNumber): string {
+ return v === null || v === undefined ? '' : v.toString();
}
function toNumberInputBound(raw: ExtendedNumber): NativeNumber {
@@ -80,66 +83,64 @@
$: maxAttr = bigintMode ? undefined : toNumberInputBound(max);
function fireOnChangeDispatch(next: ExtendedNumber) {
- let current = next;
-
if (bigintMode) {
- const parsed = parseBigIntValue(current);
- value = parsed ?? current;
+ const parsed = parseBigIntValue(next);
+ value = parsed ?? value;
+ inputValue = valueToDisplayString(value);
dispatch('change', parsed ?? undefined);
return;
}
- const num = Number(current);
- value = Number.isNaN(num) ? current : num;
+ const num = Number(next);
+ value = Number.isNaN(num) ? next : num;
dispatch('change', Number.isNaN(num) ? undefined : num);
}
- function increment(): void {
- if (bigintMode) {
- const stepValue = parseBigIntStep(step);
- const current = parseBigIntValue(value) ?? 0n;
- const minValue = parseBigIntBound(min);
- const maxValue = parseBigIntBound(max);
- let next = current + stepValue;
-
- if (minValue !== null && next < minValue) {
- next = minValue;
- }
+ function clampBigInt(val: bigint, minVal: bigint | null, maxVal: bigint | null): bigint {
+ let result = val;
+ if (minVal !== null && result < minVal) result = minVal;
+ if (maxVal !== null && result > maxVal) result = maxVal;
+ return result;
+ }
- if (maxValue !== null && next > maxValue) {
- next = maxValue;
- }
+ function stepBigInt(direction: 1 | -1): void {
+ const stepValue = parseBigIntStep(step);
+ const current = parseBigIntValue(value) ?? 0n;
+ const bounds = { min: parseBigIntBound(min), max: parseBigIntBound(max) };
+ const next = clampBigInt(
+ current + (direction === 1 ? stepValue : -stepValue),
+ bounds.min,
+ bounds.max
+ );
+ fireOnChangeDispatch(next);
+ }
- fireOnChangeDispatch(next);
+ function increment(): void {
+ if (bigintMode) {
+ stepBigInt(1);
return;
}
-
input.stepUp();
fireOnChangeDispatch(input.value);
}
function decrement(): void {
if (bigintMode) {
- const stepValue = parseBigIntStep(step);
- const current = parseBigIntValue(value) ?? 0n;
- const minValue = parseBigIntBound(min);
- const maxValue = parseBigIntBound(max);
- let next = current - stepValue;
-
- if (minValue !== null && next < minValue) {
- next = minValue;
- }
-
- if (maxValue !== null && next > maxValue) {
- next = maxValue;
- }
-
- fireOnChangeDispatch(next);
+ stepBigInt(-1);
return;
}
-
input.stepDown();
fireOnChangeDispatch(input.value);
}
+
+ function handleBigIntInput(e: Event & { currentTarget: EventTarget & HTMLInputElement }) {
+ const raw = e.currentTarget.value;
+ fireOnChangeDispatch(raw);
+ inputValue = raw;
+ }
+
+ $: if (bigintMode) {
+ inputValue = valueToDisplayString(value);
+ }
@@ -161,7 +162,8 @@
on:invalid
on:change={() => fireOnChangeDispatch(input.value)}
bind:this={input}
- bind:value
+ value={inputValue}
+ on:input={handleBigIntInput}
type="text"
inputmode="numeric"
{disabled}
@@ -206,7 +208,7 @@