@xsolla/xui-date-picker 0.225.0 → 0.226.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/README.md +6 -0
- package/native/index.js +83 -33
- package/native/index.js.map +1 -1
- package/native/index.mjs +83 -33
- package/native/index.mjs.map +1 -1
- package/package.json +6 -6
- package/web/index.js +83 -33
- package/web/index.js.map +1 -1
- package/web/index.mjs +83 -33
- package/web/index.mjs.map +1 -1
package/native/index.mjs
CHANGED
|
@@ -588,6 +588,7 @@ var getFixedPlacementStyle = (side, align, container, panel, viewport, offset) =
|
|
|
588
588
|
const vertical = align === "center" ? { top: (container.top + container.bottom) / 2 - panel.height / 2 } : align === "end" ? { bottom: viewport.height - container.bottom } : { top: container.top };
|
|
589
589
|
return { position: "fixed", ...horizontal, ...vertical };
|
|
590
590
|
};
|
|
591
|
+
var isSegmentKey = (key) => /^[0-9]$/.test(key) || key === "Backspace" || key === "ArrowUp" || key === "ArrowDown" || key === "ArrowLeft" || key === "ArrowRight";
|
|
591
592
|
var DatePicker = forwardRef(
|
|
592
593
|
({
|
|
593
594
|
onChange,
|
|
@@ -652,6 +653,7 @@ var DatePicker = forwardRef(
|
|
|
652
653
|
const [activeSegment, setActiveSegment] = useState(null);
|
|
653
654
|
const [internalChip, setInternalChip] = useState(null);
|
|
654
655
|
const [parseError, setParseError] = useState(null);
|
|
656
|
+
const [rawText, setRawText] = useState(null);
|
|
655
657
|
const [fixedPosition, setFixedPosition] = useState(
|
|
656
658
|
null
|
|
657
659
|
);
|
|
@@ -728,7 +730,7 @@ var DatePicker = forwardRef(
|
|
|
728
730
|
(g) => g.day != null || g.month != null || g.year != null
|
|
729
731
|
);
|
|
730
732
|
const showMask = hasAnyFilled || focused && isWeb;
|
|
731
|
-
const inputValue = chipLabel ?? (showMask ? composed.text : "");
|
|
733
|
+
const inputValue = rawText ?? chipLabel ?? (showMask ? composed.text : "");
|
|
732
734
|
const showClear = clearable && editable && (hasAnyFilled || !!chipLabel);
|
|
733
735
|
const orderedSegments = () => composeField().segments;
|
|
734
736
|
const firstSegmentKey = () => {
|
|
@@ -797,6 +799,60 @@ var DatePicker = forwardRef(
|
|
|
797
799
|
commitPart(edit.group, edit.type, Number(edit.buffer));
|
|
798
800
|
setEdit(null);
|
|
799
801
|
};
|
|
802
|
+
const parseOne = (token) => {
|
|
803
|
+
const trimmed = token.trim();
|
|
804
|
+
if (!trimmed) return null;
|
|
805
|
+
const parsed = parse(trimmed, resolvedFormat, /* @__PURE__ */ new Date());
|
|
806
|
+
return isValid(parsed) ? parsed : null;
|
|
807
|
+
};
|
|
808
|
+
const parseFieldText = (text) => {
|
|
809
|
+
if (isRange) {
|
|
810
|
+
const [startText, endText] = text.split(RANGE_SEPARATOR);
|
|
811
|
+
const start = parseOne(startText ?? "");
|
|
812
|
+
const end = parseOne(endText ?? "");
|
|
813
|
+
if (!start || endText?.trim() && !end) {
|
|
814
|
+
return {
|
|
815
|
+
error: `Enter a valid date range (${resolvedFormat} - ${resolvedFormat})`
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
return { parts: [datePartsFromDate(start), datePartsFromDate(end)] };
|
|
819
|
+
}
|
|
820
|
+
const date = parseOne(text);
|
|
821
|
+
if (!date) return { error: `Enter a valid date (${resolvedFormat})` };
|
|
822
|
+
return { parts: [datePartsFromDate(date)] };
|
|
823
|
+
};
|
|
824
|
+
const isOutOfBounds = (parts) => parts.map(datePartsToDate).some((d) => d instanceof Date && !isWithinBounds(d));
|
|
825
|
+
const commitRawText = (text) => {
|
|
826
|
+
setEdit(null);
|
|
827
|
+
if (!text.trim()) {
|
|
828
|
+
setRawText(null);
|
|
829
|
+
setParseError(null);
|
|
830
|
+
setGroups(propGroups());
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
const result = parseFieldText(text);
|
|
834
|
+
if ("error" in result) {
|
|
835
|
+
setParseError(result.error);
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
if (isOutOfBounds(result.parts)) {
|
|
839
|
+
setParseError("Date must be within the allowed range");
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
842
|
+
setRawText(null);
|
|
843
|
+
setParseError(null);
|
|
844
|
+
setGroups(result.parts);
|
|
845
|
+
emit(result.parts);
|
|
846
|
+
};
|
|
847
|
+
const handleChangeText = (text) => {
|
|
848
|
+
rest.onChangeText?.(text);
|
|
849
|
+
if (!editable) return;
|
|
850
|
+
markDirty();
|
|
851
|
+
setEdit(null);
|
|
852
|
+
setParseError(null);
|
|
853
|
+
setActiveSegment(null);
|
|
854
|
+
setRawText(text);
|
|
855
|
+
};
|
|
800
856
|
const defaultPart = (type) => {
|
|
801
857
|
const now = /* @__PURE__ */ new Date();
|
|
802
858
|
if (type === "day") return now.getDate();
|
|
@@ -889,10 +945,12 @@ var DatePicker = forwardRef(
|
|
|
889
945
|
}
|
|
890
946
|
if (!isWeb || !editable) return;
|
|
891
947
|
if (e.key === "Enter") {
|
|
892
|
-
|
|
948
|
+
if (rawText !== null) commitRawText(rawText);
|
|
949
|
+
else commitBuffer();
|
|
893
950
|
setOpen(false);
|
|
894
951
|
return;
|
|
895
952
|
}
|
|
953
|
+
if (rawText !== null && isSegmentKey(e.key)) setRawText(null);
|
|
896
954
|
if (e.key === "ArrowUp") return handleArrowStep(e, 1);
|
|
897
955
|
if (e.key === "ArrowDown") return handleArrowStep(e, -1);
|
|
898
956
|
if (e.key === "ArrowLeft") return handleArrowMove(e, -1);
|
|
@@ -945,30 +1003,33 @@ var DatePicker = forwardRef(
|
|
|
945
1003
|
setParseError(null);
|
|
946
1004
|
return;
|
|
947
1005
|
}
|
|
1006
|
+
if (rawText !== null) {
|
|
1007
|
+
commitRawText(rawText);
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
948
1010
|
let next = groups;
|
|
1011
|
+
let rejected = false;
|
|
949
1012
|
if (edit) {
|
|
950
1013
|
const clamped = clampDatePart(
|
|
951
1014
|
edit.type,
|
|
952
1015
|
Number(edit.buffer),
|
|
953
1016
|
groups[edit.group]
|
|
954
1017
|
);
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
)
|
|
1018
|
+
const edited = { ...groups[edit.group], [edit.type]: clamped };
|
|
1019
|
+
const assembled = datePartsToDate(edited);
|
|
1020
|
+
if (assembled && !isWithinBounds(assembled)) {
|
|
1021
|
+
rejected = true;
|
|
1022
|
+
} else {
|
|
1023
|
+
next = groups.map((g, i) => i === edit.group ? edited : g);
|
|
1024
|
+
}
|
|
958
1025
|
}
|
|
959
1026
|
const props = propGroups();
|
|
960
1027
|
next = next.map((g, i) => isDatePartsComplete(g) ? g : props[i]);
|
|
961
1028
|
setEdit(null);
|
|
962
|
-
setParseError(null);
|
|
1029
|
+
setParseError(rejected ? "Date must be within the allowed range" : null);
|
|
963
1030
|
setGroups(next);
|
|
964
1031
|
emit(next);
|
|
965
1032
|
};
|
|
966
|
-
const parseOne = (token) => {
|
|
967
|
-
const trimmed = token.trim();
|
|
968
|
-
if (!trimmed) return null;
|
|
969
|
-
const parsed = parse(trimmed, resolvedFormat, /* @__PURE__ */ new Date());
|
|
970
|
-
return isValid(parsed) ? parsed : null;
|
|
971
|
-
};
|
|
972
1033
|
const handlePaste = (e) => {
|
|
973
1034
|
onPasteProp?.(e);
|
|
974
1035
|
if (e.defaultPrevented) return;
|
|
@@ -976,34 +1037,20 @@ var DatePicker = forwardRef(
|
|
|
976
1037
|
const text = e.clipboardData?.getData("text") ?? "";
|
|
977
1038
|
if (!text.trim()) return;
|
|
978
1039
|
e.preventDefault();
|
|
979
|
-
|
|
980
|
-
if (
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
const end = parseOne(endText ?? "");
|
|
984
|
-
if (!start) {
|
|
985
|
-
setParseError(
|
|
986
|
-
`Enter a valid date range (${resolvedFormat} - ${resolvedFormat})`
|
|
987
|
-
);
|
|
988
|
-
return;
|
|
989
|
-
}
|
|
990
|
-
next = [datePartsFromDate(start), datePartsFromDate(end)];
|
|
991
|
-
} else {
|
|
992
|
-
const date = parseOne(text);
|
|
993
|
-
if (!date) {
|
|
994
|
-
setParseError(`Enter a valid date (${resolvedFormat})`);
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
next = [datePartsFromDate(date)];
|
|
1040
|
+
const result = parseFieldText(text);
|
|
1041
|
+
if ("error" in result) {
|
|
1042
|
+
setParseError(result.error);
|
|
1043
|
+
return;
|
|
998
1044
|
}
|
|
999
|
-
const
|
|
1000
|
-
if (
|
|
1045
|
+
const next = result.parts;
|
|
1046
|
+
if (isOutOfBounds(next)) {
|
|
1001
1047
|
setParseError("Date must be within the allowed range");
|
|
1002
1048
|
return;
|
|
1003
1049
|
}
|
|
1004
1050
|
markDirty();
|
|
1005
1051
|
setParseError(null);
|
|
1006
1052
|
setEdit(null);
|
|
1053
|
+
setRawText(null);
|
|
1007
1054
|
setGroups(next);
|
|
1008
1055
|
emit(next);
|
|
1009
1056
|
};
|
|
@@ -1018,6 +1065,7 @@ var DatePicker = forwardRef(
|
|
|
1018
1065
|
sessionRef.current.cleared = true;
|
|
1019
1066
|
setGroups(next);
|
|
1020
1067
|
setEdit(null);
|
|
1068
|
+
setRawText(null);
|
|
1021
1069
|
setParseError(null);
|
|
1022
1070
|
setInternalChip(null);
|
|
1023
1071
|
onChipSelect?.(null);
|
|
@@ -1037,6 +1085,7 @@ var DatePicker = forwardRef(
|
|
|
1037
1085
|
sessionRef.current = { dirty: false, cleared: false, propKey };
|
|
1038
1086
|
setGroups(propGroups());
|
|
1039
1087
|
setEdit(null);
|
|
1088
|
+
setRawText(null);
|
|
1040
1089
|
setParseError(null);
|
|
1041
1090
|
}, [propKey]);
|
|
1042
1091
|
useEffect(() => {
|
|
@@ -1234,6 +1283,7 @@ var DatePicker = forwardRef(
|
|
|
1234
1283
|
onKeyDown: handleKeyDown,
|
|
1235
1284
|
onClick: handleFieldClick,
|
|
1236
1285
|
onPaste: handlePaste,
|
|
1286
|
+
onChangeText: handleChangeText,
|
|
1237
1287
|
iconRight,
|
|
1238
1288
|
iconLeft,
|
|
1239
1289
|
extraClear: showClear,
|