sapo-components-ui-rn 1.1.37 → 1.1.39

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/index.esm.js CHANGED
@@ -636,7 +636,6 @@ Dimensions.get("window").height;
636
636
  Dimensions.get("window").width;
637
637
  var BUTTON_HEIGHT = 48;
638
638
  var BUTTON_HEIGHT_SMALL = 40;
639
- var SPACE_2 = 2;
640
639
  var SPACE_4 = 4;
641
640
  var SPACE_6 = 6;
642
641
  var SPACE_8 = 8;
@@ -1898,7 +1897,7 @@ function getTextColor(_a) {
1898
1897
  }
1899
1898
 
1900
1899
  var MAXIMIZED_LABEL_FONT_SIZE = 15;
1901
- var MINIMIZED_LABEL_FONT_SIZE = 12;
1900
+ var MINIMIZED_LABEL_FONT_SIZE = 13;
1902
1901
  var LABEL_WIGGLE_X_OFFSET = 4;
1903
1902
  var ADORNMENT_SIZE = 24;
1904
1903
  var MIN_WIDTH = 100;
@@ -4828,7 +4827,7 @@ var Text = function (props) {
4828
4827
  var Text$1 = memoDeepEqual(Text);
4829
4828
 
4830
4829
  var InputLabel = function (props) {
4831
- var labeled = props.labeled, wiggle = props.wiggle, error = props.error, focused = props.focused, opacity = props.opacity, labelLayoutWidth = props.labelLayoutWidth, labelLayoutHeight = props.labelLayoutHeight, labelBackground = props.labelBackground, label = props.label, labelError = props.labelError, onLayoutAnimatedText = props.onLayoutAnimatedText, onLabelTextLayout = props.onLabelTextLayout, hasActiveOutline = props.hasActiveOutline, activeColor = props.activeColor, placeholderStyle = props.placeholderStyle, baseLabelTranslateX = props.baseLabelTranslateX, baseLabelTranslateY = props.baseLabelTranslateY, font = props.font, fontSize = props.fontSize, lineHeight = props.lineHeight, fontWeight = props.fontWeight, placeholderOpacity = props.placeholderOpacity, wiggleOffsetX = props.wiggleOffsetX, labelScale = props.labelScale, topPosition = props.topPosition, paddingLeft = props.paddingLeft, paddingRight = props.paddingRight, backgroundColor = props.backgroundColor, roundness = props.roundness, placeholderColor = props.placeholderColor, errorColor = props.errorColor, labelTranslationXOffset = props.labelTranslationXOffset, maxFontSizeMultiplier = props.maxFontSizeMultiplier, testID = props.testID, inputContainerLayout = props.inputContainerLayout, scaledLabel = props.scaledLabel, required = props.required;
4830
+ var labeled = props.labeled, wiggle = props.wiggle, error = props.error, focused = props.focused, opacity = props.opacity, labelLayoutWidth = props.labelLayoutWidth, labelLayoutHeight = props.labelLayoutHeight, labelBackground = props.labelBackground, label = props.label, labelError = props.labelError, onLayoutAnimatedText = props.onLayoutAnimatedText, onLabelTextLayout = props.onLabelTextLayout, hasActiveOutline = props.hasActiveOutline, activeColor = props.activeColor, placeholderStyle = props.placeholderStyle, baseLabelTranslateX = props.baseLabelTranslateX, baseLabelTranslateY = props.baseLabelTranslateY, font = props.font, fontSize = props.fontSize, lineHeight = props.lineHeight, fontWeight = props.fontWeight, placeholderOpacity = props.placeholderOpacity, wiggleOffsetX = props.wiggleOffsetX, labelScale = props.labelScale, topPosition = props.topPosition, paddingLeft = props.paddingLeft, paddingRight = props.paddingRight, backgroundColor = props.backgroundColor, roundness = props.roundness, placeholderColor = props.placeholderColor, errorColor = props.errorColor, labelTranslationXOffset = props.labelTranslationXOffset, maxFontSizeMultiplier = props.maxFontSizeMultiplier, testID = props.testID, inputContainerLayout = props.inputContainerLayout, scaledLabel = props.scaledLabel, required = props.required, inputValue = props.inputValue;
4832
4831
  var INPUT_PADDING_HORIZONTAL = getConstants().INPUT_PADDING_HORIZONTAL;
4833
4832
  var width = useWindowDimensions().width;
4834
4833
  var paddingOffset = paddingLeft && paddingRight ? { paddingLeft: paddingLeft, paddingRight: paddingRight } : {};
@@ -4880,7 +4879,7 @@ var InputLabel = function (props) {
4880
4879
  var commonStyles = [
4881
4880
  placeholderStyle,
4882
4881
  {
4883
- top: topPosition - (Platform.OS === "android" ? 3 : 2),
4882
+ top: topPosition - (Platform.OS === "android" ? 2 : inputValue ? 0 : 2),
4884
4883
  },
4885
4884
  {
4886
4885
  maxWidth: labelWidth,
@@ -5285,7 +5284,7 @@ var TextInputFlat = function (_a) {
5285
5284
  flex: 1,
5286
5285
  },
5287
5286
  ] },
5288
- label ? (React$3.createElement(InputLabel$1, __assign({ labeled: parentState.labeled, error: parentState.error, focused: parentState.focused, scaledLabel: scaledLabel, wiggle: Boolean(parentState.value && labelProps.labelError), labelLayoutMeasured: parentState.labelLayout.measured, labelLayoutWidth: parentState.labelLayout.width, labelLayoutHeight: parentState.labelLayout.height, required: required }, labelProps))) : null,
5287
+ label ? (React$3.createElement(InputLabel$1, __assign({ inputValue: inputValue, labeled: parentState.labeled, error: parentState.error, focused: parentState.focused, scaledLabel: scaledLabel, wiggle: Boolean(parentState.value && labelProps.labelError), labelLayoutMeasured: parentState.labelLayout.measured, labelLayoutWidth: parentState.labelLayout.width, labelLayoutHeight: parentState.labelLayout.height, required: required }, labelProps))) : null,
5289
5288
  React$3.createElement(View$1, { style: { flexDirection: "row", alignItems: "flex-end" } },
5290
5289
  !multiline &&
5291
5290
  prefix &&
@@ -5293,11 +5292,11 @@ var TextInputFlat = function (_a) {
5293
5292
  renderPrefix(), render === null || render === void 0 ? void 0 :
5294
5293
  render(__assign(__assign({}, rest), { ref: innerRef, onChangeText: handleChangeText, value: inputValue, placeholder: rest.placeholder, editable: !disabled && editable, selectionColor: selectionColor, cursorColor: typeof cursorColor === "undefined" ? activeColor : cursorColor, placeholderTextColor: placeholderTextColorBasedOnState, onFocus: onFocus, onBlur: onBlur, underlineColorAndroid: "transparent", multiline: multiline, style: [
5295
5294
  styles$e.input,
5296
- __assign(__assign({ paddingLeft: paddingLeft, paddingRight: paddingRight, paddingTop: parentState.focused || parentState.value ? SPACE_12 : 0 }, font), { fontSize: fontSize, lineHeight: lineHeight, fontWeight: fontWeight, color: inputTextColor, textAlignVertical: multiline ? "top" : "center", marginTop: Platform.OS === "android" ? SPACE_8 : SPACE_2 }),
5295
+ __assign(__assign({ paddingLeft: paddingLeft, paddingRight: paddingRight, paddingTop: parentState.focused || parentState.value ? SPACE_12 : 0 }, font), { fontSize: fontSize, lineHeight: lineHeight, fontWeight: fontWeight, color: inputTextColor, textAlignVertical: multiline ? "top" : "center", marginTop: Platform.OS === "android" ? SPACE_8 : SPACE_4 }),
5297
5296
  contentStyle,
5298
5297
  ] })),
5299
5298
  renderSuffix())),
5300
- parentState.focused && !disabled && clearButton && inputValue ? (React$3.createElement(TouchableOpacity, { onPress: handleClear, style: styles$e.clearButton },
5299
+ !disabled && clearButton && inputValue ? (React$3.createElement(TouchableOpacity, { onPress: handleClear, style: styles$e.clearButton },
5301
5300
  React$3.createElement(SvgIcon, { name: "IconClearText", width: 24, height: 24 }))) : (React$3.createElement(Spacer, { width: SPACE_12 })),
5302
5301
  checkLineRightAction() && (React$3.createElement(Spacer, { width: 1, height: 24, backgroundColor: theme.colors.borderPrimaryDefault, style: {
5303
5302
  marginRight: SPACE_8,
@@ -5420,7 +5419,7 @@ var TextInputDefault = function (_a) {
5420
5419
  }
5421
5420
  };
5422
5421
  var renderLabel = function () {
5423
- var _a;
5422
+ var _a, _b;
5424
5423
  if (parentState.focused ||
5425
5424
  (parentState.value !== undefined && ((_a = parentState.value) === null || _a === void 0 ? void 0 : _a.toString()) !== "")) {
5426
5425
  return (React$3.createElement(View, { paddingTop: CONSTANTS.SPACE_6 },
@@ -5428,6 +5427,14 @@ var TextInputDefault = function (_a) {
5428
5427
  label,
5429
5428
  required && React$3.createElement(Text$1, { color: theme.colors.textErrorDefault }, " *"))));
5430
5429
  }
5430
+ else if (((_b = parentState.value) === null || _b === void 0 ? void 0 : _b.toString()) == "") {
5431
+ return (React$3.createElement(View, { paddingTop: CONSTANTS.SPACE_12 },
5432
+ React$3.createElement(Text$1, { color: getLabelColor(), style: [contentStyle] },
5433
+ label,
5434
+ required && (React$3.createElement(Text$1, { style: [contentStyle], color: theme.colors.textErrorDefault },
5435
+ " ",
5436
+ "*")))));
5437
+ }
5431
5438
  return React$3.createElement(View, null);
5432
5439
  };
5433
5440
  var getPaddingTopValue = function () {
@@ -5519,7 +5526,7 @@ var TextInputDefault = function (_a) {
5519
5526
  multiline ? (render === null || render === void 0 ? void 0 : render(__assign(__assign({}, rest), { ref: innerRef, onChangeText: handleChangeText, value: inputValue, placeholder: ((_b = parentState.value) === null || _b === void 0 ? void 0 : _b.toString()) == ""
5520
5527
  ? parentState.focused
5521
5528
  ? rest.placeholder
5522
- : label
5529
+ : ""
5523
5530
  : rest.placeholder, editable: !disabled && editable, selectionColor: selectionColor, cursorColor: typeof cursorColor === "undefined" ? activeColor : cursorColor, placeholderTextColor: placeholderTextColorBasedOnState, onFocus: onFocus, onBlur: onBlur, underlineColorAndroid: "transparent", multiline: multiline, style: [
5524
5531
  styles$d.input,
5525
5532
  __assign(__assign({}, font), { fontSize: fontSize, lineHeight: lineHeight, fontWeight: fontWeight, color: inputTextColor, textAlignVertical: multiline ? "top" : "center", textAlign: textAlign
@@ -5547,7 +5554,7 @@ var TextInputDefault = function (_a) {
5547
5554
  contentStyle,
5548
5555
  ] })),
5549
5556
  !multiline && renderSuffix()))),
5550
- parentState.focused && !disabled && clearButton && inputValue ? (React$3.createElement(TouchableOpacity, { onPress: handleClear, style: multiline ? styles$d.clearButtonMultiline : styles$d.clearButton },
5557
+ !disabled && clearButton && inputValue ? (React$3.createElement(TouchableOpacity, { onPress: handleClear, style: multiline ? styles$d.clearButtonMultiline : styles$d.clearButton },
5551
5558
  React$3.createElement(SvgIcon, { name: "IconClearText", width: 24, height: 24 }))) : (React$3.createElement(Spacer, { width: CONSTANTS.SPACE_12 })),
5552
5559
  checkLineRightAction() && (React$3.createElement(Spacer, { width: 1, height: 24, backgroundColor: colors.borderPrimaryDefault, style: {
5553
5560
  marginRight: CONSTANTS.SPACE_8,
@@ -5575,6 +5582,7 @@ var styles$d = StyleSheet.create({
5575
5582
  clearButton: {
5576
5583
  justifyContent: "center",
5577
5584
  paddingHorizontal: CONSTANTS.SPACE_8,
5585
+ // alignItems: "center",
5578
5586
  },
5579
5587
  vError: {
5580
5588
  paddingTop: CONSTANTS.SPACE_4,
@@ -5631,10 +5639,37 @@ var TextInputNumber = function (_a) {
5631
5639
  useEffect(function () {
5632
5640
  var currentValue = Number(inputValue);
5633
5641
  var minValueNumber = Number(minValue);
5634
- setCanSave(!isNaN(currentValue) &&
5642
+ var maxValueNumber = Number(maxValue);
5643
+ // Kiểm tra canSave với logic mới để hỗ trợ số âm
5644
+ // Ví dụ: value=-100, maxValue=999999999999, minValue=0
5645
+ // -100 < 0 (minValue) nhưng |-100| = 100 <= 999999999999 (maxValue) → canSave = true
5646
+ var isValid = false;
5647
+ if (!isNaN(currentValue) &&
5635
5648
  !isNaN(minValueNumber) &&
5636
- currentValue >= minValueNumber);
5637
- }, [inputValue, minValue]);
5649
+ !isNaN(maxValueNumber)) {
5650
+ if (currentValue < 0) {
5651
+ // Với số âm, kiểm tra giá trị tuyệt đối không vượt quá maxValue
5652
+ // và giá trị không nhỏ hơn minValue (nếu minValue cũng là số âm)
5653
+ var absCurrent = Math.abs(currentValue);
5654
+ var absMaxValue = Math.abs(maxValueNumber);
5655
+ if (minValueNumber < 0) {
5656
+ // Nếu minValue cũng là số âm, kiểm tra currentValue >= minValue
5657
+ isValid = currentValue >= minValueNumber && absCurrent <= absMaxValue;
5658
+ }
5659
+ else {
5660
+ // Nếu minValue là số dương hoặc 0, chỉ kiểm tra giá trị tuyệt đối
5661
+ // Điều này cho phép số âm luôn được lưu nếu không vượt quá maxValue
5662
+ isValid = absCurrent <= absMaxValue;
5663
+ }
5664
+ }
5665
+ else {
5666
+ // Với số dương, kiểm tra bình thường
5667
+ isValid =
5668
+ currentValue >= minValueNumber && currentValue <= maxValueNumber;
5669
+ }
5670
+ }
5671
+ setCanSave(isValid);
5672
+ }, [inputValue, minValue, maxValue]);
5638
5673
  var getColorValue = useMemo(function () {
5639
5674
  if (disabled) {
5640
5675
  return colors.textPlaceholder;
@@ -5653,9 +5688,54 @@ var TextInputNumber = function (_a) {
5653
5688
  }
5654
5689
  else if (key === "000") {
5655
5690
  if (type === "integer") {
5691
+ // Xử lý trường hợp nhập "000" để tạo số lớn hơn
5692
+ // Ví dụ: "1" + "000" = "1000", "10" + "000" = "10000"
5693
+ // Nếu vượt quá maxValue, sẽ tự động cắt bớt số 0
5694
+ // Logic này đảm bảo người dùng có thể tiếp tục nhập số đã được khởi tạo
5695
+ // Ví dụ: value=999, người dùng có thể nhập "000" để tạo "999000"
5656
5696
  var newInputValue = inputValue + "000";
5657
5697
  var newValue = Number(newInputValue);
5658
5698
  var maxValueNumber = Number(maxValue);
5699
+ // Kiểm tra nếu giá trị vượt quá maxValue, cắt bớt số 0
5700
+ if (!isNaN(newValue) &&
5701
+ !isNaN(maxValueNumber) &&
5702
+ newValue > maxValueNumber) {
5703
+ // Tìm số 0 tối đa có thể thêm vào mà không vượt quá maxValue
5704
+ var tempValue = inputValue;
5705
+ var tempNewValue = Number(tempValue + "000");
5706
+ // Giảm dần số 0 cho đến khi không vượt quá maxValue
5707
+ while (tempNewValue > maxValueNumber && tempValue.endsWith("0")) {
5708
+ tempValue = tempValue.slice(0, -1);
5709
+ tempNewValue = Number(tempValue + "000");
5710
+ }
5711
+ // Nếu vẫn vượt quá, chỉ thêm số 0 có thể
5712
+ if (tempNewValue > maxValueNumber) {
5713
+ // Tìm số 0 tối đa có thể thêm
5714
+ var maxZeros = 0;
5715
+ for (var i = 1; i <= 3; i++) {
5716
+ var testValue = Number(inputValue + "0".repeat(i));
5717
+ if (testValue <= maxValueNumber) {
5718
+ maxZeros = i;
5719
+ }
5720
+ else {
5721
+ break;
5722
+ }
5723
+ }
5724
+ if (maxZeros > 0) {
5725
+ newInputValue = inputValue + "0".repeat(maxZeros);
5726
+ newValue = Number(newInputValue);
5727
+ }
5728
+ else {
5729
+ // Không thể thêm số 0 nào
5730
+ return;
5731
+ }
5732
+ }
5733
+ else {
5734
+ newInputValue = tempValue + "000";
5735
+ newValue = Number(newInputValue);
5736
+ }
5737
+ }
5738
+ // Kiểm tra xem có thể nhập được không sau khi xử lý "000"
5659
5739
  if (!isNaN(newValue) &&
5660
5740
  !isNaN(maxValueNumber) &&
5661
5741
  newValue <= maxValueNumber) {
@@ -5671,7 +5751,12 @@ var TextInputNumber = function (_a) {
5671
5751
  if (inputValue === "0" || inputValue === "") {
5672
5752
  setInputValue("0.");
5673
5753
  }
5754
+ else if (inputValue === "-") {
5755
+ // Nếu chỉ có dấu trừ, thêm "0."
5756
+ setInputValue("-0.");
5757
+ }
5674
5758
  else {
5759
+ // Nếu đã có giá trị, thêm dấu "." vào cuối
5675
5760
  setInputValue(function (prev) { return prev + key; });
5676
5761
  }
5677
5762
  setIsFirstInput(false);
@@ -5683,8 +5768,48 @@ var TextInputNumber = function (_a) {
5683
5768
  if (type === "float" && (key === "0" || key === "000")) {
5684
5769
  return;
5685
5770
  }
5686
- setInputValue(key);
5687
- setIsFirstInput(false);
5771
+ // Kiểm tra xem có thể nhập được không khi là lần đầu
5772
+ var newValue = Number(key);
5773
+ var maxValueNumber = Number(maxValue);
5774
+ if (!isNaN(newValue) && !isNaN(maxValueNumber)) {
5775
+ var canInput = false;
5776
+ if (newValue < 0) {
5777
+ // Với số âm, kiểm tra giá trị tuyệt đối không vượt quá maxValue
5778
+ var absNewValue = Math.abs(newValue);
5779
+ var absMaxValue = Math.abs(maxValueNumber);
5780
+ canInput = absNewValue <= absMaxValue;
5781
+ }
5782
+ else {
5783
+ // Với số dương, kiểm tra bình thường
5784
+ canInput = newValue <= maxValueNumber;
5785
+ }
5786
+ if (canInput) {
5787
+ // Nếu inputValue rỗng hoặc chỉ có dấu trừ, thay thế hoàn toàn
5788
+ if (inputValue === "" || inputValue === "-") {
5789
+ setInputValue(key);
5790
+ }
5791
+ else {
5792
+ // Nếu đã có giá trị, thêm vào cuối
5793
+ setInputValue(inputValue + key);
5794
+ }
5795
+ setIsFirstInput(false);
5796
+ }
5797
+ else {
5798
+ // Nếu vượt quá maxValue ngay từ đầu, không cho phép nhập
5799
+ return;
5800
+ }
5801
+ }
5802
+ else {
5803
+ // Nếu inputValue rỗng hoặc chỉ có dấu trừ, thay thế hoàn toàn
5804
+ if (inputValue === "" || inputValue === "-") {
5805
+ setInputValue(key);
5806
+ }
5807
+ else {
5808
+ // Nếu đã có giá trị, thêm vào cuối
5809
+ setInputValue(inputValue + key);
5810
+ }
5811
+ setIsFirstInput(false);
5812
+ }
5688
5813
  }
5689
5814
  else {
5690
5815
  // Kiểm tra nếu input bắt đầu bằng 0 và không có dấu chấm
@@ -5704,10 +5829,65 @@ var TextInputNumber = function (_a) {
5704
5829
  var newInputValue = inputValue + key;
5705
5830
  var newValue = Number(newInputValue);
5706
5831
  var maxValueNumber = Number(maxValue);
5707
- if (!isNaN(newValue) &&
5708
- !isNaN(maxValueNumber) &&
5709
- newValue <= maxValueNumber) {
5832
+ // Kiểm tra xem có thể nhập được không
5833
+ var canInput = false;
5834
+ var shouldCheckLength = true;
5835
+ if (!isNaN(newValue) && !isNaN(maxValueNumber)) {
5836
+ if (newValue < 0) {
5837
+ // Với số âm, kiểm tra giá trị tuyệt đối không vượt quá maxValue
5838
+ var absNewValue = Math.abs(newValue);
5839
+ var absMaxValue = Math.abs(maxValueNumber);
5840
+ if (absNewValue <= absMaxValue) {
5841
+ canInput = true;
5842
+ }
5843
+ else {
5844
+ // Nếu vượt quá maxValue, kiểm tra xem có thể nhập được không
5845
+ var maxValueStr = absMaxValue.toString();
5846
+ inputValue.length;
5847
+ var newLength = newInputValue.length;
5848
+ // Nếu độ dài mới lớn hơn độ dài của maxValue, không cho phép nhập
5849
+ if (newLength > maxValueStr.length) {
5850
+ return;
5851
+ }
5852
+ // Nếu độ dài bằng nhau, kiểm tra giá trị
5853
+ if (newLength === maxValueStr.length &&
5854
+ absNewValue > absMaxValue) {
5855
+ return;
5856
+ }
5857
+ // Nếu độ dài nhỏ hơn, có thể nhập được (sẽ kiểm tra khi nhập tiếp)
5858
+ canInput = true;
5859
+ shouldCheckLength = false;
5860
+ }
5861
+ }
5862
+ else {
5863
+ // Với số dương, kiểm tra bình thường
5864
+ if (newValue <= maxValueNumber) {
5865
+ canInput = true;
5866
+ }
5867
+ else {
5868
+ // Nếu vượt quá maxValue, kiểm tra xem có thể nhập được không
5869
+ var maxValueStr = maxValueNumber.toString();
5870
+ inputValue.length;
5871
+ var newLength = newInputValue.length;
5872
+ // Nếu độ dài mới lớn hơn độ dài của maxValue, không cho phép nhập
5873
+ if (newLength > maxValueStr.length) {
5874
+ return;
5875
+ }
5876
+ // Nếu độ dài bằng nhau, kiểm tra giá trị
5877
+ if (newLength === maxValueStr.length &&
5878
+ newValue > maxValueNumber) {
5879
+ return;
5880
+ }
5881
+ // Nếu độ dài nhỏ hơn, có thể nhập được (sẽ kiểm tra khi nhập tiếp)
5882
+ // Ví dụ: maxValue = 999, inputValue = "99", nhập "9" → "999" (OK)
5883
+ canInput = true;
5884
+ shouldCheckLength = false;
5885
+ }
5886
+ }
5887
+ }
5888
+ if (canInput) {
5710
5889
  if (inputValue.includes(".")) {
5890
+ // Xử lý số thập phân
5711
5891
  var _a = inputValue.split("."); _a[0]; var _b = _a[1], decimalPart = _b === void 0 ? "" : _b;
5712
5892
  if (newInputValue.length <= 12 && decimalPart.length === 0) {
5713
5893
  setInputValue(function (prev) { return prev + key; });
@@ -5717,7 +5897,12 @@ var TextInputNumber = function (_a) {
5717
5897
  }
5718
5898
  }
5719
5899
  else {
5720
- if (newInputValue.length <= 12) {
5900
+ // Xử số nguyên
5901
+ if (shouldCheckLength && newInputValue.length <= 12) {
5902
+ setInputValue(function (prev) { return prev + key; });
5903
+ }
5904
+ else if (!shouldCheckLength) {
5905
+ // Nếu không cần kiểm tra độ dài (đã kiểm tra maxValue ở trên)
5721
5906
  setInputValue(function (prev) { return prev + key; });
5722
5907
  }
5723
5908
  }
@@ -5762,7 +5947,16 @@ var TextInputNumber = function (_a) {
5762
5947
  };
5763
5948
  var onShowModalKeyboard = function () {
5764
5949
  setIsShowModalKeyboard(true);
5765
- setIsFirstInput(true);
5950
+ // Logic mới: Không reset về trạng thái nhập mới khi đã có giá trị
5951
+ // Chỉ set isFirstInput = true khi inputValue rỗng hoặc chỉ có dấu trừ
5952
+ // Điều này cho phép người dùng tiếp tục nhập từ giá trị hiện tại
5953
+ // Ví dụ: value=999, người dùng có thể nhập "000" để tạo "999000"
5954
+ if (inputValue === "" || inputValue === "-") {
5955
+ setIsFirstInput(true);
5956
+ }
5957
+ else {
5958
+ setIsFirstInput(false);
5959
+ }
5766
5960
  Keyboard.dismiss();
5767
5961
  };
5768
5962
  var onCloseModalKeyboard = function () {
@@ -5786,6 +5980,9 @@ var TextInputNumber = function (_a) {
5786
5980
  : colors.borderPrimaryDefault,
5787
5981
  },
5788
5982
  ],
5983
+ checkValueEmpty() && {
5984
+ alignItems: "center",
5985
+ },
5789
5986
  textError.length > 0 && [
5790
5987
  {
5791
5988
  borderColor: colors.borderErrorDefault,
@@ -5804,28 +6001,32 @@ var TextInputNumber = function (_a) {
5804
6001
  React__default.createElement(Spacer, { width: SPACE_12 }),
5805
6002
  left && (React__default.createElement(View, { center: true, paddingRight: SPACE_8, height: "100%" }, left)),
5806
6003
  React__default.createElement(View, { full: true, paddingRight: SPACE_4 },
5807
- !checkValueEmpty() && !checkLabelEmpty() && (React__default.createElement(Text$1, { size: 12, color: colors.textSecondary, style: [
5808
- disabled && {
5809
- color: colors.textPlaceholder,
5810
- },
5811
- textError.length > 0 && {
5812
- color: colors.textErrorDefault,
5813
- },
5814
- ] },
5815
- label,
5816
- required && React__default.createElement(Text$1, { color: colors.textErrorDefault }, " *"))),
6004
+ !checkValueEmpty() && !checkLabelEmpty() && (React__default.createElement(View, null,
6005
+ React__default.createElement(Text$1, { size: 12, color: colors.textSecondary, style: [
6006
+ disabled && {
6007
+ color: colors.textPlaceholder,
6008
+ },
6009
+ textError.length > 0 && {
6010
+ color: colors.textErrorDefault,
6011
+ },
6012
+ ] },
6013
+ label,
6014
+ required && React__default.createElement(Text$1, { color: colors.textErrorDefault }, " *")))),
5817
6015
  React__default.createElement(View, { row: true, alignCenter: true },
5818
6016
  !checkValueEmpty() && prefix.toString() !== "" && (React__default.createElement(Text$1, { numberOfLines: 1, color: colors.textSecondary, style: [disabled && disabledTextStyle] },
5819
6017
  prefix, " ")),
5820
6018
  React__default.createElement(View, { full: true },
5821
- React__default.createElement(Text$1, { numberOfLines: 1, color: getColorValue, style: [disabled && disabledTextStyle] },
6019
+ React__default.createElement(Text$1, { numberOfLines: 1, color: getColorValue, style: [styles$c.text14, disabled && disabledTextStyle] },
5822
6020
  checkValueEmpty()
5823
6021
  ? label
5824
6022
  : formatNumberInput$1(numberValue, formatDecimal),
5825
6023
  checkValueEmpty() && required && (React__default.createElement(Text$1, { color: colors.textErrorDefault }, " *")))),
5826
6024
  !checkValueEmpty() && suffix.toString() !== "" && (React__default.createElement(Text$1, { numberOfLines: 1, color: colors.textSecondary, style: [disabled && disabledTextStyle] }, " ",
5827
6025
  suffix)))),
5828
- clearButton && !checkValueEmpty() && (React__default.createElement(TouchableOpacity, { activeOpacity: 0.8, onPress: handleClearInput },
6026
+ clearButton && !checkValueEmpty() && (React__default.createElement(TouchableOpacity, { style: {
6027
+ alignContent: "center",
6028
+ paddingTop: Platform.OS === "ios" ? 4 : 8,
6029
+ }, activeOpacity: 0.8, onPress: handleClearInput },
5829
6030
  React__default.createElement(SvgIcon, { name: "IconClearText", width: 24, height: 24 }))),
5830
6031
  right && numberValue && (React__default.createElement(Spacer, { width: 1, height: 24, backgroundColor: theme.colors.borderPrimaryDefault, style: {
5831
6032
  marginLeft: SPACE_4,
@@ -5882,9 +6083,8 @@ var TextInputNumber = function (_a) {
5882
6083
  var styles$c = StyleSheet.create(__assign(__assign({}, containerStyles), { disabled: { opacity: 0.6 }, container: {
5883
6084
  height: 48,
5884
6085
  flexDirection: "row",
5885
- alignItems: "center",
5886
6086
  justifyContent: "space-between",
5887
- paddingVertical: SPACE_6,
6087
+ paddingVertical: Platform.OS === "android" ? 3 : SPACE_6,
5888
6088
  }, border: {
5889
6089
  borderWidth: BORDER_WIDTH_1,
5890
6090
  }, small: {
@@ -7235,10 +7435,14 @@ var styles$1 = StyleSheet.create(__assign({}, containerStyles));
7235
7435
  var formatNumberInput = function (value, formatDecimal) {
7236
7436
  if (!value)
7237
7437
  return "0";
7438
+ if (value === "")
7439
+ return "0";
7440
+ // Xử lý số âm
7238
7441
  var isNegative = value.startsWith("-");
7239
7442
  var _a = value.replace(/[^0-9.]/g, "").split("."), intPart = _a[0], decimalPart = _a[1];
7240
- intPart = intPart.replace(/^0+(?=\d)/, "");
7443
+ // Format phần nguyên
7241
7444
  intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
7445
+ // Giới hạn phần thập phân
7242
7446
  if (decimalPart)
7243
7447
  decimalPart = decimalPart.slice(0, formatDecimal);
7244
7448
  var result = intPart;
@@ -7258,16 +7462,50 @@ var NumberKeyboard = function (_a) {
7258
7462
  useEffect(function () {
7259
7463
  if (visible) {
7260
7464
  setInputValue((value === null || value === void 0 ? void 0 : value.toString()) || "");
7261
- setIsFirstInput(true);
7465
+ // Logic mới: Không reset về trạng thái nhập mới khi đã có giá trị
7466
+ // Chỉ set isFirstInput = true khi inputValue rỗng hoặc chỉ có dấu trừ
7467
+ if (inputValue === "" || inputValue === "-") {
7468
+ setIsFirstInput(true);
7469
+ }
7470
+ else {
7471
+ setIsFirstInput(false);
7472
+ }
7262
7473
  }
7263
- }, [visible, value]);
7474
+ }, [visible, value, inputValue]);
7264
7475
  useEffect(function () {
7265
7476
  var currentValue = Number(inputValue);
7266
7477
  var minValueNumber = Number(minValue);
7267
- setCanSave(!isNaN(currentValue) &&
7478
+ var maxValueNumber = Number(maxValue);
7479
+ // Kiểm tra canSave với logic mới để hỗ trợ số âm
7480
+ // Ví dụ: value=-100, maxValue=999999999999, minValue=0
7481
+ // -100 < 0 (minValue) nhưng |-100| = 100 <= 999999999999 (maxValue) → canSave = true
7482
+ var isValid = false;
7483
+ if (!isNaN(currentValue) &&
7268
7484
  !isNaN(minValueNumber) &&
7269
- currentValue >= minValueNumber);
7270
- }, [inputValue, minValue]);
7485
+ !isNaN(maxValueNumber)) {
7486
+ if (currentValue < 0) {
7487
+ // Với số âm, kiểm tra giá trị tuyệt đối không vượt quá maxValue
7488
+ // và giá trị không nhỏ hơn minValue (nếu minValue cũng là số âm)
7489
+ var absCurrent = Math.abs(currentValue);
7490
+ var absMaxValue = Math.abs(maxValueNumber);
7491
+ if (minValueNumber < 0) {
7492
+ // Nếu minValue cũng là số âm, kiểm tra currentValue >= minValue
7493
+ isValid = currentValue >= minValueNumber && absCurrent <= absMaxValue;
7494
+ }
7495
+ else {
7496
+ // Nếu minValue là số dương hoặc 0, chỉ kiểm tra giá trị tuyệt đối
7497
+ // Điều này cho phép số âm luôn được lưu nếu không vượt quá maxValue
7498
+ isValid = absCurrent <= absMaxValue;
7499
+ }
7500
+ }
7501
+ else {
7502
+ // Với số dương, kiểm tra bình thường
7503
+ isValid =
7504
+ currentValue >= minValueNumber && currentValue <= maxValueNumber;
7505
+ }
7506
+ }
7507
+ setCanSave(isValid);
7508
+ }, [inputValue, minValue, maxValue]);
7271
7509
  var handleKeyPress = useCallback(function (key) {
7272
7510
  if (key === "del") {
7273
7511
  setInputValue(function (prev) { return prev.slice(0, -1); });
@@ -7276,9 +7514,52 @@ var NumberKeyboard = function (_a) {
7276
7514
  }
7277
7515
  if (key === "000") {
7278
7516
  if (type === "integer" && inputValue.length > 0) {
7517
+ // Xử lý trường hợp nhập "000" để tạo số lớn hơn
7518
+ // Ví dụ: "1" + "000" = "1000", "10" + "000" = "10000"
7519
+ // Nếu vượt quá maxValue, sẽ tự động cắt bớt số 0
7279
7520
  var newInputValue_1 = inputValue + "000";
7280
7521
  var newValue_1 = Number(newInputValue_1);
7281
7522
  var maxValueNumber_1 = Number(maxValue);
7523
+ // Kiểm tra nếu giá trị vượt quá maxValue, cắt bớt số 0
7524
+ if (!isNaN(newValue_1) &&
7525
+ !isNaN(maxValueNumber_1) &&
7526
+ newValue_1 > maxValueNumber_1) {
7527
+ // Tìm số 0 tối đa có thể thêm vào mà không vượt quá maxValue
7528
+ var tempValue = inputValue;
7529
+ var tempNewValue = Number(tempValue + "000");
7530
+ // Giảm dần số 0 cho đến khi không vượt quá maxValue
7531
+ while (tempNewValue > maxValueNumber_1 && tempValue.endsWith("0")) {
7532
+ tempValue = tempValue.slice(0, -1);
7533
+ tempNewValue = Number(tempValue + "000");
7534
+ }
7535
+ // Nếu vẫn vượt quá, chỉ thêm số 0 có thể
7536
+ if (tempNewValue > maxValueNumber_1) {
7537
+ // Tìm số 0 tối đa có thể thêm
7538
+ var maxZeros = 0;
7539
+ for (var i = 1; i <= 3; i++) {
7540
+ var testValue = Number(inputValue + "0".repeat(i));
7541
+ if (testValue <= maxValueNumber_1) {
7542
+ maxZeros = i;
7543
+ }
7544
+ else {
7545
+ break;
7546
+ }
7547
+ }
7548
+ if (maxZeros > 0) {
7549
+ newInputValue_1 = inputValue + "0".repeat(maxZeros);
7550
+ newValue_1 = Number(newInputValue_1);
7551
+ }
7552
+ else {
7553
+ // Không thể thêm số 0 nào
7554
+ return;
7555
+ }
7556
+ }
7557
+ else {
7558
+ newInputValue_1 = tempValue + "000";
7559
+ newValue_1 = Number(newInputValue_1);
7560
+ }
7561
+ }
7562
+ // Kiểm tra xem có thể nhập được không sau khi xử lý "000"
7282
7563
  if (!isNaN(newValue_1) &&
7283
7564
  !isNaN(maxValueNumber_1) &&
7284
7565
  newValue_1 <= maxValueNumber_1) {
@@ -7293,6 +7574,10 @@ var NumberKeyboard = function (_a) {
7293
7574
  if (inputValue === "0" || inputValue === "") {
7294
7575
  setInputValue("0.");
7295
7576
  }
7577
+ else if (inputValue === "-") {
7578
+ // Nếu chỉ có dấu trừ, thêm "0."
7579
+ setInputValue("-0.");
7580
+ }
7296
7581
  else {
7297
7582
  setInputValue(function (prev) { return prev + key; });
7298
7583
  }
@@ -7301,8 +7586,52 @@ var NumberKeyboard = function (_a) {
7301
7586
  return;
7302
7587
  }
7303
7588
  if (isFirstInput) {
7304
- setInputValue(key);
7305
- setIsFirstInput(false);
7589
+ // Nếu type là float và key là "0", không cho phép nhập số 0 đầu tiên
7590
+ if (type === "float" && (key === "0" || key === "000")) {
7591
+ return;
7592
+ }
7593
+ // Kiểm tra xem có thể nhập được không khi là lần đầu
7594
+ var newValue_2 = Number(key);
7595
+ var maxValueNumber_2 = Number(maxValue);
7596
+ if (!isNaN(newValue_2) && !isNaN(maxValueNumber_2)) {
7597
+ var canInput_1 = false;
7598
+ if (newValue_2 < 0) {
7599
+ // Với số âm, kiểm tra giá trị tuyệt đối không vượt quá maxValue
7600
+ var absNewValue = Math.abs(newValue_2);
7601
+ var absMaxValue = Math.abs(maxValueNumber_2);
7602
+ canInput_1 = absNewValue <= absMaxValue;
7603
+ }
7604
+ else {
7605
+ // Với số dương, kiểm tra bình thường
7606
+ canInput_1 = newValue_2 <= maxValueNumber_2;
7607
+ }
7608
+ if (canInput_1) {
7609
+ // Nếu inputValue rỗng hoặc chỉ có dấu trừ, thay thế hoàn toàn
7610
+ if (inputValue === "" || inputValue === "-") {
7611
+ setInputValue(key);
7612
+ }
7613
+ else {
7614
+ // Nếu đã có giá trị, thêm vào cuối
7615
+ setInputValue(inputValue + key);
7616
+ }
7617
+ setIsFirstInput(false);
7618
+ }
7619
+ else {
7620
+ // Nếu vượt quá maxValue ngay từ đầu, không cho phép nhập
7621
+ return;
7622
+ }
7623
+ }
7624
+ else {
7625
+ // Nếu inputValue rỗng hoặc chỉ có dấu trừ, thay thế hoàn toàn
7626
+ if (inputValue === "" || inputValue === "-") {
7627
+ setInputValue(key);
7628
+ }
7629
+ else {
7630
+ // Nếu đã có giá trị, thêm vào cuối
7631
+ setInputValue(inputValue + key);
7632
+ }
7633
+ setIsFirstInput(false);
7634
+ }
7306
7635
  return;
7307
7636
  }
7308
7637
  // Kiểm tra nếu input bắt đầu bằng 0 và không có dấu chấm
@@ -7322,20 +7651,79 @@ var NumberKeyboard = function (_a) {
7322
7651
  var newInputValue = inputValue + key;
7323
7652
  var newValue = Number(newInputValue);
7324
7653
  var maxValueNumber = Number(maxValue);
7325
- if (!isNaN(newValue) &&
7326
- !isNaN(maxValueNumber) &&
7327
- newValue <= maxValueNumber) {
7654
+ // Kiểm tra xem có thể nhập được không
7655
+ var canInput = false;
7656
+ var shouldCheckLength = true;
7657
+ if (!isNaN(newValue) && !isNaN(maxValueNumber)) {
7658
+ if (newValue < 0) {
7659
+ // Với số âm, kiểm tra giá trị tuyệt đối không vượt quá maxValue
7660
+ var absNewValue = Math.abs(newValue);
7661
+ var absMaxValue = Math.abs(maxValueNumber);
7662
+ if (absNewValue <= absMaxValue) {
7663
+ canInput = true;
7664
+ }
7665
+ else {
7666
+ // Nếu vượt quá maxValue, kiểm tra xem có thể nhập được không
7667
+ var maxValueStr = absMaxValue.toString();
7668
+ inputValue.length;
7669
+ var newLength = newInputValue.length;
7670
+ // Nếu độ dài mới lớn hơn độ dài của maxValue, không cho phép nhập
7671
+ if (newLength > maxValueStr.length) {
7672
+ return;
7673
+ }
7674
+ // Nếu độ dài bằng nhau, kiểm tra giá trị
7675
+ if (newLength === maxValueStr.length && absNewValue > absMaxValue) {
7676
+ return;
7677
+ }
7678
+ // Nếu độ dài nhỏ hơn, có thể nhập được (sẽ kiểm tra khi nhập tiếp)
7679
+ canInput = true;
7680
+ shouldCheckLength = false;
7681
+ }
7682
+ }
7683
+ else {
7684
+ // Với số dương, kiểm tra bình thường
7685
+ if (newValue <= maxValueNumber) {
7686
+ canInput = true;
7687
+ }
7688
+ else {
7689
+ // Nếu vượt quá maxValue, kiểm tra xem có thể nhập được không
7690
+ var maxValueStr = maxValueNumber.toString();
7691
+ inputValue.length;
7692
+ var newLength = newInputValue.length;
7693
+ // Nếu độ dài mới lớn hơn độ dài của maxValue, không cho phép nhập
7694
+ if (newLength > maxValueStr.length) {
7695
+ return;
7696
+ }
7697
+ // Nếu độ dài bằng nhau, kiểm tra giá trị
7698
+ if (newLength === maxValueStr.length && newValue > maxValueNumber) {
7699
+ return;
7700
+ }
7701
+ // Nếu độ dài nhỏ hơn, có thể nhập được (sẽ kiểm tra khi nhập tiếp)
7702
+ // Ví dụ: maxValue = 999, inputValue = "99", nhập "9" → "999" (OK)
7703
+ canInput = true;
7704
+ shouldCheckLength = false;
7705
+ }
7706
+ }
7707
+ }
7708
+ if (canInput) {
7328
7709
  if (inputValue.includes(".")) {
7329
- var _a = inputValue.split("."), intPart = _a[0], _b = _a[1], decimalPart = _b === void 0 ? "" : _b;
7330
- if (intPart.length < 12 && decimalPart.length === 0) {
7710
+ // Xử số thập phân
7711
+ var _a = inputValue.split("."); _a[0]; var _b = _a[1], decimalPart = _b === void 0 ? "" : _b;
7712
+ if (newInputValue.length <= 12 && decimalPart.length === 0) {
7331
7713
  setInputValue(function (prev) { return prev + key; });
7332
7714
  }
7333
- else if (decimalPart.length < formatDecimal) {
7715
+ else if (newInputValue.length <= 12 &&
7716
+ decimalPart.length < formatDecimal) {
7334
7717
  setInputValue(function (prev) { return prev + key; });
7335
7718
  }
7336
7719
  }
7337
7720
  else {
7338
- if (inputValue.length < 12) {
7721
+ // Xử số nguyên
7722
+ if (shouldCheckLength && newInputValue.length <= 12) {
7723
+ setInputValue(function (prev) { return prev + key; });
7724
+ }
7725
+ else if (!shouldCheckLength) {
7726
+ // Nếu không cần kiểm tra độ dài (đã kiểm tra maxValue ở trên)
7339
7727
  setInputValue(function (prev) { return prev + key; });
7340
7728
  }
7341
7729
  }
@@ -7394,11 +7782,12 @@ var NumberKeyboard = function (_a) {
7394
7782
  React__default.createElement(TouchableOpacity, { activeOpacity: 0.8, style: styles.actionButton, onPress: handleClose },
7395
7783
  React__default.createElement(Text$1, { style: [styles.actionText, styles.text16] }, "\u0110\u00F3ng")),
7396
7784
  React__default.createElement(Spacer, { style: { height: "100%" }, width: 1, backgroundColor: colors.borderPrimaryDefault }),
7397
- React__default.createElement(TouchableOpacity, { activeOpacity: 0.8, style: styles.actionButton, onPress: handleSave },
7785
+ React__default.createElement(TouchableOpacity, { activeOpacity: 0.8, style: [styles.actionButton, !canSave && { opacity: 0.5 }], onPress: handleSave, disabled: !canSave },
7398
7786
  React__default.createElement(Text$1, { style: [
7399
7787
  styles.actionText,
7400
7788
  styles.text16,
7401
7789
  { color: colors.textBrandDefault },
7790
+ !canSave && { color: colors.textSecondary },
7402
7791
  ] }, "L\u01B0u")))))));
7403
7792
  };
7404
7793
  var styles = StyleSheet.create(__assign(__assign({}, containerStyles), { modalOverlay: {