@rubenpazch/numeric-up-picker 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NumericUpPicker.d.ts.map +1 -1
- package/dist/index.cjs.js +49 -37
- package/dist/index.esm.js +49 -37
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumericUpPicker.d.ts","sourceRoot":"","sources":["../src/NumericUpPicker.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"NumericUpPicker.d.ts","sourceRoot":"","sources":["../src/NumericUpPicker.tsx"],"names":[],"mappings":"AAqBA,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EACtC,KAAK,EACL,KAAK,EACL,QAAQ,EACR,MAAM,EACN,OAAO,EACP,WAAW,EACX,GAAG,EACH,GAAG,EACH,IAAW,EACX,KAAK,EACL,IAAI,EACJ,OAAO,EACP,QAAgB,EAChB,SAAc,EACd,QAAgB,EAChB,eAAuB,EACvB,cAAsB,EACtB,WAAmB,EACnB,QAAgB,EAChB,aAAqB,EACrB,SAAiB,EACjB,OAAO,GACR,EAAE,oBAAoB,2CA6YtB"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -446,26 +446,33 @@ const hideSpinnersStyle = `
|
|
|
446
446
|
-moz-appearance: textfield;
|
|
447
447
|
}
|
|
448
448
|
`;
|
|
449
|
-
function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder, min, max, step = 0.01, error, hint, warning, disabled = false, className =
|
|
449
|
+
function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder, min, max, step = 0.01, error, hint, warning, disabled = false, className = "", required = false, useMinAsDefault = false, alwaysNegative = false, integerOnly = false, showSign = false, defaultToZero = false, clearable = false, onClear, }) {
|
|
450
450
|
// Track if the field has been touched (user has focused on it)
|
|
451
451
|
const [hasBeenTouched, setHasBeenTouched] = require$$0.useState(false);
|
|
452
|
-
const numValue = typeof value ===
|
|
452
|
+
const numValue = typeof value === "string" ? parseFloat(value) || 0 : value;
|
|
453
453
|
// Format display value with sign if showSign is true
|
|
454
454
|
const displayValue = require$$0.useMemo(() => {
|
|
455
|
-
if (!showSign ||
|
|
456
|
-
|
|
455
|
+
if (!showSign ||
|
|
456
|
+
value === "" ||
|
|
457
|
+
value === "-" ||
|
|
458
|
+
value === null ||
|
|
459
|
+
value === undefined)
|
|
460
|
+
return value || "";
|
|
457
461
|
const strValue = value.toString();
|
|
458
462
|
const numVal = parseFloat(strValue);
|
|
459
463
|
if (isNaN(numVal))
|
|
460
464
|
return value;
|
|
461
|
-
if (numVal > 0 && !strValue.startsWith(
|
|
465
|
+
if (numVal > 0 && !strValue.startsWith("+")) {
|
|
462
466
|
return `+${strValue}`;
|
|
463
467
|
}
|
|
464
468
|
return value;
|
|
465
469
|
}, [value, showSign]);
|
|
466
470
|
const handleIncrement = () => {
|
|
467
471
|
// If value is empty or invalid, start from 0 if defaultToZero, otherwise from min (or 0 if no min)
|
|
468
|
-
if (value ===
|
|
472
|
+
if (value === "" ||
|
|
473
|
+
value === "-" ||
|
|
474
|
+
value === null ||
|
|
475
|
+
value === undefined) {
|
|
469
476
|
const startValue = defaultToZero ? 0 : min !== undefined ? min : 0;
|
|
470
477
|
if (integerOnly) {
|
|
471
478
|
onChange(Math.round(startValue).toString());
|
|
@@ -483,13 +490,18 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
483
490
|
else {
|
|
484
491
|
const formattedValue = newValue.toFixed(2);
|
|
485
492
|
// If alwaysNegative, ensure the value has a negative sign
|
|
486
|
-
onChange(alwaysNegative && newValue > 0
|
|
493
|
+
onChange(alwaysNegative && newValue > 0
|
|
494
|
+
? `-${formattedValue}`
|
|
495
|
+
: formattedValue);
|
|
487
496
|
}
|
|
488
497
|
}
|
|
489
498
|
};
|
|
490
499
|
const handleDecrement = () => {
|
|
491
500
|
// If value is empty or invalid, start from 0 if defaultToZero, otherwise from max (or 0 if no max)
|
|
492
|
-
if (value ===
|
|
501
|
+
if (value === "" ||
|
|
502
|
+
value === "-" ||
|
|
503
|
+
value === null ||
|
|
504
|
+
value === undefined) {
|
|
493
505
|
const startValue = defaultToZero ? 0 : max !== undefined ? max : 0;
|
|
494
506
|
if (integerOnly) {
|
|
495
507
|
onChange(Math.round(startValue).toString());
|
|
@@ -516,11 +528,11 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
516
528
|
};
|
|
517
529
|
const handleKeyDown = (e) => {
|
|
518
530
|
// Handle arrow up/down keys for incrementing/decrementing
|
|
519
|
-
if (e.key ===
|
|
531
|
+
if (e.key === "ArrowUp") {
|
|
520
532
|
e.preventDefault(); // Prevent cursor movement
|
|
521
533
|
handleIncrement();
|
|
522
534
|
}
|
|
523
|
-
else if (e.key ===
|
|
535
|
+
else if (e.key === "ArrowDown") {
|
|
524
536
|
e.preventDefault(); // Prevent cursor movement
|
|
525
537
|
handleDecrement();
|
|
526
538
|
}
|
|
@@ -536,22 +548,22 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
536
548
|
let inputValue = e.target.value;
|
|
537
549
|
// For showSign, remove the plus sign before processing
|
|
538
550
|
if (showSign) {
|
|
539
|
-
inputValue = inputValue.replace(/^\+/,
|
|
551
|
+
inputValue = inputValue.replace(/^\+/, "");
|
|
540
552
|
}
|
|
541
553
|
// For alwaysNegative fields, ensure value always starts with minus sign
|
|
542
554
|
if (alwaysNegative) {
|
|
543
555
|
// Remove any existing minus signs
|
|
544
|
-
inputValue = inputValue.replace(/-/g,
|
|
556
|
+
inputValue = inputValue.replace(/-/g, "");
|
|
545
557
|
// Allow empty input
|
|
546
|
-
if (inputValue ===
|
|
547
|
-
onChange(
|
|
558
|
+
if (inputValue === "") {
|
|
559
|
+
onChange("-");
|
|
548
560
|
return;
|
|
549
561
|
}
|
|
550
562
|
// Add minus sign at the beginning
|
|
551
563
|
inputValue = `-${inputValue}`;
|
|
552
564
|
}
|
|
553
565
|
// Allow empty input (user deleted content)
|
|
554
|
-
if (inputValue ===
|
|
566
|
+
if (inputValue === "" || inputValue === "-") {
|
|
555
567
|
onChange(inputValue);
|
|
556
568
|
return;
|
|
557
569
|
}
|
|
@@ -559,16 +571,16 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
559
571
|
onChange(inputValue);
|
|
560
572
|
};
|
|
561
573
|
const handleClear = () => {
|
|
562
|
-
onChange(
|
|
574
|
+
onChange("");
|
|
563
575
|
onClear?.();
|
|
564
576
|
};
|
|
565
577
|
const handleBlurWithValidation = () => {
|
|
566
578
|
const inputValue = value.toString();
|
|
567
579
|
// If empty, handle based on required and useMinAsDefault flags
|
|
568
|
-
if (inputValue ===
|
|
580
|
+
if (inputValue === "" || inputValue === "-") {
|
|
569
581
|
// For optional fields (!required), allow empty values
|
|
570
582
|
if (!required) {
|
|
571
|
-
onChange(
|
|
583
|
+
onChange("");
|
|
572
584
|
onBlur?.();
|
|
573
585
|
return;
|
|
574
586
|
}
|
|
@@ -594,17 +606,17 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
594
606
|
}
|
|
595
607
|
else if (!hasBeenTouched) {
|
|
596
608
|
// If never touched, keep it empty
|
|
597
|
-
onChange(
|
|
609
|
+
onChange("");
|
|
598
610
|
}
|
|
599
611
|
else {
|
|
600
|
-
onChange(integerOnly ?
|
|
612
|
+
onChange(integerOnly ? "0" : alwaysNegative ? "-0.00" : "0.00");
|
|
601
613
|
}
|
|
602
614
|
onBlur?.();
|
|
603
615
|
return;
|
|
604
616
|
}
|
|
605
617
|
// Parse the input value (remove negative sign if present for alwaysNegative fields)
|
|
606
618
|
let numericValue = alwaysNegative
|
|
607
|
-
? parseFloat(inputValue.replace(/^-/,
|
|
619
|
+
? parseFloat(inputValue.replace(/^-/, ""))
|
|
608
620
|
: parseFloat(inputValue);
|
|
609
621
|
// If not a valid number, reset to min or 0
|
|
610
622
|
if (isNaN(numericValue)) {
|
|
@@ -627,7 +639,7 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
627
639
|
}
|
|
628
640
|
}
|
|
629
641
|
else {
|
|
630
|
-
onChange(integerOnly ?
|
|
642
|
+
onChange(integerOnly ? "0" : alwaysNegative ? "-0.00" : "0.00");
|
|
631
643
|
}
|
|
632
644
|
onBlur?.();
|
|
633
645
|
return;
|
|
@@ -672,7 +684,7 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
672
684
|
};
|
|
673
685
|
// Disable buttons only if value is not empty and at min/max
|
|
674
686
|
// When value is empty, allow both buttons (they will set to min/max)
|
|
675
|
-
const isEmpty = value ===
|
|
687
|
+
const isEmpty = value === "" || value === "-" || value === null || value === undefined;
|
|
676
688
|
// For alwaysNegative fields, we compare absolute values
|
|
677
689
|
const isAtMin = !isEmpty &&
|
|
678
690
|
(alwaysNegative
|
|
@@ -682,23 +694,23 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
682
694
|
(alwaysNegative
|
|
683
695
|
? max !== undefined && Math.abs(numValue) <= Math.abs(max)
|
|
684
696
|
: max !== undefined && numValue >= max);
|
|
685
|
-
return (jsxRuntimeExports.jsxs("div", { className: className, children: [jsxRuntimeExports.jsx("style", { children: hideSpinnersStyle }), label && (jsxRuntimeExports.jsxs("label", { className: `block text-sm font-medium mb-2 ${error ?
|
|
686
|
-
?
|
|
697
|
+
return (jsxRuntimeExports.jsxs("div", { className: className, children: [jsxRuntimeExports.jsx("style", { children: hideSpinnersStyle }), label && (jsxRuntimeExports.jsxs("label", { className: `block text-sm font-medium mb-2 ${error ? "text-red-700" : "text-gray-700"}`, children: [label, required && jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" })] })), jsxRuntimeExports.jsxs("div", { className: `flex items-center justify-between h-12 rounded-lg border-2 transition-all ${error
|
|
698
|
+
? "border-red-500 bg-red-50"
|
|
687
699
|
: disabled
|
|
688
|
-
?
|
|
689
|
-
:
|
|
690
|
-
?
|
|
700
|
+
? "border-gray-300 bg-gray-100 opacity-50 cursor-not-allowed"
|
|
701
|
+
: "border-gray-300 bg-gray-50"}`, children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: handleDecrement, disabled: disabled || isAtMin, className: `flex-shrink-0 w-12 h-full flex items-center justify-center border-r border-gray-300 transition-all ${error
|
|
702
|
+
? "text-red-500"
|
|
691
703
|
: disabled || isAtMin
|
|
692
|
-
?
|
|
693
|
-
:
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
?
|
|
704
|
+
? "opacity-40 cursor-not-allowed text-gray-400"
|
|
705
|
+
: "hover:bg-gray-100 active:bg-gray-200 text-gray-600"}`, title: "Decrease value", "aria-label": "Decrease", children: jsxRuntimeExports.jsx(R, { size: "md" }) }), jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center", children: jsxRuntimeExports.jsx("input", { type: "text", step: step, min: min, max: max, value: displayValue, onChange: handleDirectInput, onBlur: handleBlurWithValidation, onFocus: handleFocus, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, className: `text-center bg-transparent text-lg font-semibold placeholder-gray-400 focus:outline-none border-none ${error ? "text-red-700" : "text-gray-900"} w-full`, style: {
|
|
706
|
+
WebkitAppearance: "none",
|
|
707
|
+
MozAppearance: "textfield",
|
|
708
|
+
appearance: "none",
|
|
709
|
+
} }) }), clearable && !isEmpty && !disabled && (jsxRuntimeExports.jsx("button", { type: "button", onClick: handleClear, className: "flex-shrink-0 w-6 h-6 mr-2 flex items-center justify-center rounded-full transition-all hover:bg-gray-200 active:bg-gray-300 text-gray-500 hover:text-gray-700", title: "Clear value", "aria-label": "Clear", children: jsxRuntimeExports.jsx(g, { size: "sm" }) })), jsxRuntimeExports.jsx("button", { type: "button", onClick: handleIncrement, disabled: disabled || isAtMax, className: `flex-shrink-0 w-12 h-full flex items-center justify-center border-l border-gray-300 transition-all ${error
|
|
710
|
+
? "text-red-500"
|
|
699
711
|
: disabled || isAtMax
|
|
700
|
-
?
|
|
701
|
-
:
|
|
712
|
+
? "opacity-40 cursor-not-allowed text-gray-400"
|
|
713
|
+
: "hover:bg-gray-100 active:bg-gray-200 text-gray-600"}`, title: "Increase value", "aria-label": "Increase", children: jsxRuntimeExports.jsx(U, { size: "md" }) })] }), error && (jsxRuntimeExports.jsxs("div", { className: "mt-2 flex items-start gap-1.5", children: [jsxRuntimeExports.jsx(m, { size: "sm", className: "text-red-500 flex-shrink-0 mt-0.5" }), jsxRuntimeExports.jsx("p", { className: "text-sm text-red-600 font-medium", children: error })] })), warning && !error && (jsxRuntimeExports.jsxs("div", { className: "mt-2 flex items-start gap-1.5", children: [jsxRuntimeExports.jsx("div", { className: "w-4 h-4 text-amber-500 flex-shrink-0 mt-0.5 flex items-center justify-center", children: jsxRuntimeExports.jsx("span", { className: "text-xs font-bold", children: "!" }) }), jsxRuntimeExports.jsx("p", { className: "text-sm text-amber-700", children: warning })] })), hint && !error && !warning && (jsxRuntimeExports.jsx("p", { className: "mt-2 text-xs text-gray-500", children: hint }))] }));
|
|
702
714
|
}
|
|
703
715
|
|
|
704
716
|
module.exports = NumericUpPicker;
|
package/dist/index.esm.js
CHANGED
|
@@ -444,26 +444,33 @@ const hideSpinnersStyle = `
|
|
|
444
444
|
-moz-appearance: textfield;
|
|
445
445
|
}
|
|
446
446
|
`;
|
|
447
|
-
function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder, min, max, step = 0.01, error, hint, warning, disabled = false, className =
|
|
447
|
+
function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder, min, max, step = 0.01, error, hint, warning, disabled = false, className = "", required = false, useMinAsDefault = false, alwaysNegative = false, integerOnly = false, showSign = false, defaultToZero = false, clearable = false, onClear, }) {
|
|
448
448
|
// Track if the field has been touched (user has focused on it)
|
|
449
449
|
const [hasBeenTouched, setHasBeenTouched] = useState(false);
|
|
450
|
-
const numValue = typeof value ===
|
|
450
|
+
const numValue = typeof value === "string" ? parseFloat(value) || 0 : value;
|
|
451
451
|
// Format display value with sign if showSign is true
|
|
452
452
|
const displayValue = useMemo(() => {
|
|
453
|
-
if (!showSign ||
|
|
454
|
-
|
|
453
|
+
if (!showSign ||
|
|
454
|
+
value === "" ||
|
|
455
|
+
value === "-" ||
|
|
456
|
+
value === null ||
|
|
457
|
+
value === undefined)
|
|
458
|
+
return value || "";
|
|
455
459
|
const strValue = value.toString();
|
|
456
460
|
const numVal = parseFloat(strValue);
|
|
457
461
|
if (isNaN(numVal))
|
|
458
462
|
return value;
|
|
459
|
-
if (numVal > 0 && !strValue.startsWith(
|
|
463
|
+
if (numVal > 0 && !strValue.startsWith("+")) {
|
|
460
464
|
return `+${strValue}`;
|
|
461
465
|
}
|
|
462
466
|
return value;
|
|
463
467
|
}, [value, showSign]);
|
|
464
468
|
const handleIncrement = () => {
|
|
465
469
|
// If value is empty or invalid, start from 0 if defaultToZero, otherwise from min (or 0 if no min)
|
|
466
|
-
if (value ===
|
|
470
|
+
if (value === "" ||
|
|
471
|
+
value === "-" ||
|
|
472
|
+
value === null ||
|
|
473
|
+
value === undefined) {
|
|
467
474
|
const startValue = defaultToZero ? 0 : min !== undefined ? min : 0;
|
|
468
475
|
if (integerOnly) {
|
|
469
476
|
onChange(Math.round(startValue).toString());
|
|
@@ -481,13 +488,18 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
481
488
|
else {
|
|
482
489
|
const formattedValue = newValue.toFixed(2);
|
|
483
490
|
// If alwaysNegative, ensure the value has a negative sign
|
|
484
|
-
onChange(alwaysNegative && newValue > 0
|
|
491
|
+
onChange(alwaysNegative && newValue > 0
|
|
492
|
+
? `-${formattedValue}`
|
|
493
|
+
: formattedValue);
|
|
485
494
|
}
|
|
486
495
|
}
|
|
487
496
|
};
|
|
488
497
|
const handleDecrement = () => {
|
|
489
498
|
// If value is empty or invalid, start from 0 if defaultToZero, otherwise from max (or 0 if no max)
|
|
490
|
-
if (value ===
|
|
499
|
+
if (value === "" ||
|
|
500
|
+
value === "-" ||
|
|
501
|
+
value === null ||
|
|
502
|
+
value === undefined) {
|
|
491
503
|
const startValue = defaultToZero ? 0 : max !== undefined ? max : 0;
|
|
492
504
|
if (integerOnly) {
|
|
493
505
|
onChange(Math.round(startValue).toString());
|
|
@@ -514,11 +526,11 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
514
526
|
};
|
|
515
527
|
const handleKeyDown = (e) => {
|
|
516
528
|
// Handle arrow up/down keys for incrementing/decrementing
|
|
517
|
-
if (e.key ===
|
|
529
|
+
if (e.key === "ArrowUp") {
|
|
518
530
|
e.preventDefault(); // Prevent cursor movement
|
|
519
531
|
handleIncrement();
|
|
520
532
|
}
|
|
521
|
-
else if (e.key ===
|
|
533
|
+
else if (e.key === "ArrowDown") {
|
|
522
534
|
e.preventDefault(); // Prevent cursor movement
|
|
523
535
|
handleDecrement();
|
|
524
536
|
}
|
|
@@ -534,22 +546,22 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
534
546
|
let inputValue = e.target.value;
|
|
535
547
|
// For showSign, remove the plus sign before processing
|
|
536
548
|
if (showSign) {
|
|
537
|
-
inputValue = inputValue.replace(/^\+/,
|
|
549
|
+
inputValue = inputValue.replace(/^\+/, "");
|
|
538
550
|
}
|
|
539
551
|
// For alwaysNegative fields, ensure value always starts with minus sign
|
|
540
552
|
if (alwaysNegative) {
|
|
541
553
|
// Remove any existing minus signs
|
|
542
|
-
inputValue = inputValue.replace(/-/g,
|
|
554
|
+
inputValue = inputValue.replace(/-/g, "");
|
|
543
555
|
// Allow empty input
|
|
544
|
-
if (inputValue ===
|
|
545
|
-
onChange(
|
|
556
|
+
if (inputValue === "") {
|
|
557
|
+
onChange("-");
|
|
546
558
|
return;
|
|
547
559
|
}
|
|
548
560
|
// Add minus sign at the beginning
|
|
549
561
|
inputValue = `-${inputValue}`;
|
|
550
562
|
}
|
|
551
563
|
// Allow empty input (user deleted content)
|
|
552
|
-
if (inputValue ===
|
|
564
|
+
if (inputValue === "" || inputValue === "-") {
|
|
553
565
|
onChange(inputValue);
|
|
554
566
|
return;
|
|
555
567
|
}
|
|
@@ -557,16 +569,16 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
557
569
|
onChange(inputValue);
|
|
558
570
|
};
|
|
559
571
|
const handleClear = () => {
|
|
560
|
-
onChange(
|
|
572
|
+
onChange("");
|
|
561
573
|
onClear?.();
|
|
562
574
|
};
|
|
563
575
|
const handleBlurWithValidation = () => {
|
|
564
576
|
const inputValue = value.toString();
|
|
565
577
|
// If empty, handle based on required and useMinAsDefault flags
|
|
566
|
-
if (inputValue ===
|
|
578
|
+
if (inputValue === "" || inputValue === "-") {
|
|
567
579
|
// For optional fields (!required), allow empty values
|
|
568
580
|
if (!required) {
|
|
569
|
-
onChange(
|
|
581
|
+
onChange("");
|
|
570
582
|
onBlur?.();
|
|
571
583
|
return;
|
|
572
584
|
}
|
|
@@ -592,17 +604,17 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
592
604
|
}
|
|
593
605
|
else if (!hasBeenTouched) {
|
|
594
606
|
// If never touched, keep it empty
|
|
595
|
-
onChange(
|
|
607
|
+
onChange("");
|
|
596
608
|
}
|
|
597
609
|
else {
|
|
598
|
-
onChange(integerOnly ?
|
|
610
|
+
onChange(integerOnly ? "0" : alwaysNegative ? "-0.00" : "0.00");
|
|
599
611
|
}
|
|
600
612
|
onBlur?.();
|
|
601
613
|
return;
|
|
602
614
|
}
|
|
603
615
|
// Parse the input value (remove negative sign if present for alwaysNegative fields)
|
|
604
616
|
let numericValue = alwaysNegative
|
|
605
|
-
? parseFloat(inputValue.replace(/^-/,
|
|
617
|
+
? parseFloat(inputValue.replace(/^-/, ""))
|
|
606
618
|
: parseFloat(inputValue);
|
|
607
619
|
// If not a valid number, reset to min or 0
|
|
608
620
|
if (isNaN(numericValue)) {
|
|
@@ -625,7 +637,7 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
625
637
|
}
|
|
626
638
|
}
|
|
627
639
|
else {
|
|
628
|
-
onChange(integerOnly ?
|
|
640
|
+
onChange(integerOnly ? "0" : alwaysNegative ? "-0.00" : "0.00");
|
|
629
641
|
}
|
|
630
642
|
onBlur?.();
|
|
631
643
|
return;
|
|
@@ -670,7 +682,7 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
670
682
|
};
|
|
671
683
|
// Disable buttons only if value is not empty and at min/max
|
|
672
684
|
// When value is empty, allow both buttons (they will set to min/max)
|
|
673
|
-
const isEmpty = value ===
|
|
685
|
+
const isEmpty = value === "" || value === "-" || value === null || value === undefined;
|
|
674
686
|
// For alwaysNegative fields, we compare absolute values
|
|
675
687
|
const isAtMin = !isEmpty &&
|
|
676
688
|
(alwaysNegative
|
|
@@ -680,23 +692,23 @@ function NumericUpPicker({ label, value, onChange, onBlur, onFocus, placeholder,
|
|
|
680
692
|
(alwaysNegative
|
|
681
693
|
? max !== undefined && Math.abs(numValue) <= Math.abs(max)
|
|
682
694
|
: max !== undefined && numValue >= max);
|
|
683
|
-
return (jsxRuntimeExports.jsxs("div", { className: className, children: [jsxRuntimeExports.jsx("style", { children: hideSpinnersStyle }), label && (jsxRuntimeExports.jsxs("label", { className: `block text-sm font-medium mb-2 ${error ?
|
|
684
|
-
?
|
|
695
|
+
return (jsxRuntimeExports.jsxs("div", { className: className, children: [jsxRuntimeExports.jsx("style", { children: hideSpinnersStyle }), label && (jsxRuntimeExports.jsxs("label", { className: `block text-sm font-medium mb-2 ${error ? "text-red-700" : "text-gray-700"}`, children: [label, required && jsxRuntimeExports.jsx("span", { className: "text-red-500 ml-1", children: "*" })] })), jsxRuntimeExports.jsxs("div", { className: `flex items-center justify-between h-12 rounded-lg border-2 transition-all ${error
|
|
696
|
+
? "border-red-500 bg-red-50"
|
|
685
697
|
: disabled
|
|
686
|
-
?
|
|
687
|
-
:
|
|
688
|
-
?
|
|
698
|
+
? "border-gray-300 bg-gray-100 opacity-50 cursor-not-allowed"
|
|
699
|
+
: "border-gray-300 bg-gray-50"}`, children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: handleDecrement, disabled: disabled || isAtMin, className: `flex-shrink-0 w-12 h-full flex items-center justify-center border-r border-gray-300 transition-all ${error
|
|
700
|
+
? "text-red-500"
|
|
689
701
|
: disabled || isAtMin
|
|
690
|
-
?
|
|
691
|
-
:
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
?
|
|
702
|
+
? "opacity-40 cursor-not-allowed text-gray-400"
|
|
703
|
+
: "hover:bg-gray-100 active:bg-gray-200 text-gray-600"}`, title: "Decrease value", "aria-label": "Decrease", children: jsxRuntimeExports.jsx(R, { size: "md" }) }), jsxRuntimeExports.jsx("div", { className: "flex-1 flex items-center justify-center", children: jsxRuntimeExports.jsx("input", { type: "text", step: step, min: min, max: max, value: displayValue, onChange: handleDirectInput, onBlur: handleBlurWithValidation, onFocus: handleFocus, onKeyDown: handleKeyDown, placeholder: placeholder, disabled: disabled, className: `text-center bg-transparent text-lg font-semibold placeholder-gray-400 focus:outline-none border-none ${error ? "text-red-700" : "text-gray-900"} w-full`, style: {
|
|
704
|
+
WebkitAppearance: "none",
|
|
705
|
+
MozAppearance: "textfield",
|
|
706
|
+
appearance: "none",
|
|
707
|
+
} }) }), clearable && !isEmpty && !disabled && (jsxRuntimeExports.jsx("button", { type: "button", onClick: handleClear, className: "flex-shrink-0 w-6 h-6 mr-2 flex items-center justify-center rounded-full transition-all hover:bg-gray-200 active:bg-gray-300 text-gray-500 hover:text-gray-700", title: "Clear value", "aria-label": "Clear", children: jsxRuntimeExports.jsx(g, { size: "sm" }) })), jsxRuntimeExports.jsx("button", { type: "button", onClick: handleIncrement, disabled: disabled || isAtMax, className: `flex-shrink-0 w-12 h-full flex items-center justify-center border-l border-gray-300 transition-all ${error
|
|
708
|
+
? "text-red-500"
|
|
697
709
|
: disabled || isAtMax
|
|
698
|
-
?
|
|
699
|
-
:
|
|
710
|
+
? "opacity-40 cursor-not-allowed text-gray-400"
|
|
711
|
+
: "hover:bg-gray-100 active:bg-gray-200 text-gray-600"}`, title: "Increase value", "aria-label": "Increase", children: jsxRuntimeExports.jsx(U, { size: "md" }) })] }), error && (jsxRuntimeExports.jsxs("div", { className: "mt-2 flex items-start gap-1.5", children: [jsxRuntimeExports.jsx(m, { size: "sm", className: "text-red-500 flex-shrink-0 mt-0.5" }), jsxRuntimeExports.jsx("p", { className: "text-sm text-red-600 font-medium", children: error })] })), warning && !error && (jsxRuntimeExports.jsxs("div", { className: "mt-2 flex items-start gap-1.5", children: [jsxRuntimeExports.jsx("div", { className: "w-4 h-4 text-amber-500 flex-shrink-0 mt-0.5 flex items-center justify-center", children: jsxRuntimeExports.jsx("span", { className: "text-xs font-bold", children: "!" }) }), jsxRuntimeExports.jsx("p", { className: "text-sm text-amber-700", children: warning })] })), hint && !error && !warning && (jsxRuntimeExports.jsx("p", { className: "mt-2 text-xs text-gray-500", children: hint }))] }));
|
|
700
712
|
}
|
|
701
713
|
|
|
702
714
|
export { NumericUpPicker as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rubenpazch/numeric-up-picker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"repository": "https://github.com/rubenpazch/lbyte-ui-library.git",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
"react-dom": "^19.0.0"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@rubenpazch/icons": "
|
|
27
|
+
"@rubenpazch/icons": "3.0.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@rubenpazch/typescript-config": "
|
|
30
|
+
"@rubenpazch/typescript-config": "3.0.0"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "rollup -c",
|