@xsolla/xui-date-picker 0.218.1 → 0.219.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/web/index.js CHANGED
@@ -107,6 +107,10 @@ var ADDITIONAL_BLOCKED_PROPS = /* @__PURE__ */ new Set([
107
107
  "fontWeight",
108
108
  "fontFamily",
109
109
  "textDecoration",
110
+ // `display` is a presentation attribute on SVG, so isPropValid lets it
111
+ // through — but Box consumes it purely as CSS. Without this it lands on the
112
+ // DOM node as a bogus `display="inline-flex"` attribute.
113
+ "display",
110
114
  // Cross-platform layout prop that Text consumes as CSS, never as an
111
115
  // attribute. Pinned explicitly because it is now spread into the styled
112
116
  // component rather than destructured away before it can reach the DOM.
@@ -141,7 +145,7 @@ function createFilteredElement(defaultTag) {
141
145
  var import_jsx_runtime = require("react/jsx-runtime");
142
146
  var FilteredDiv = createFilteredElement("div");
143
147
  var StyledBox = (0, import_styled_components.default)(FilteredDiv)`
144
- display: flex;
148
+ display: ${(props) => props.display || "flex"};
145
149
  box-sizing: border-box;
146
150
  background-color: ${(props) => props.backgroundColor || "transparent"};
147
151
  border-color: ${(props) => props.borderColor || "transparent"};
@@ -277,7 +281,7 @@ var Box = import_react2.default.forwardRef(
277
281
  onLoad,
278
282
  "data-testid": dataTestId || testID,
279
283
  style: {
280
- display: "block",
284
+ display: props.display || "block",
281
285
  objectFit: "cover",
282
286
  width: typeof props.width === "number" ? `${props.width}px` : props.width,
283
287
  height: typeof props.height === "number" ? `${props.height}px` : props.height,
@@ -677,6 +681,9 @@ var DatePicker = (0, import_react3.forwardRef)(
677
681
  overlayThemeProductContext,
678
682
  iconRight = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CalendarFieldIcon, {}),
679
683
  iconLeft,
684
+ label,
685
+ clearable = false,
686
+ onClear,
680
687
  error,
681
688
  errorMessage,
682
689
  readOnly,
@@ -698,6 +705,7 @@ var DatePicker = (0, import_react3.forwardRef)(
698
705
  () => isRange ? [datePartsFromDate(startDate), datePartsFromDate(endDate)] : [datePartsFromDate(selectedDate)],
699
706
  [isRange, startDate, endDate, selectedDate]
700
707
  );
708
+ const propKey = `${selectedDate?.getTime() ?? ""}|${startDate?.getTime() ?? ""}|${endDate?.getTime() ?? ""}|${isRange}`;
701
709
  const [open, setOpen] = (0, import_react3.useState)(false);
702
710
  const [groups, setGroups] = (0, import_react3.useState)(propGroups);
703
711
  const [edit, setEdit] = (0, import_react3.useState)(null);
@@ -713,6 +721,15 @@ var DatePicker = (0, import_react3.forwardRef)(
713
721
  const inputRef = (0, import_react3.useRef)(null);
714
722
  const chipSelectionRef = (0, import_react3.useRef)(false);
715
723
  const suppressReopenRef = (0, import_react3.useRef)(false);
724
+ const sessionRef = (0, import_react3.useRef)({
725
+ dirty: false,
726
+ cleared: false,
727
+ propKey
728
+ });
729
+ const markDirty = () => {
730
+ sessionRef.current.dirty = true;
731
+ sessionRef.current.cleared = false;
732
+ };
716
733
  const activeChipValue = activeChip !== void 0 ? activeChip : internalChip;
717
734
  const chipLabel = showChipLabel && activeChipValue && chips ? chips.find((c) => c.value === activeChipValue)?.label : void 0;
718
735
  const isWithinBounds = (date) => {
@@ -772,6 +789,7 @@ var DatePicker = (0, import_react3.forwardRef)(
772
789
  );
773
790
  const showMask = hasAnyFilled || focused && isWeb;
774
791
  const inputValue = chipLabel ?? (showMask ? composed.text : "");
792
+ const showClear = clearable && editable && (hasAnyFilled || !!chipLabel);
775
793
  const orderedSegments = () => composeField().segments;
776
794
  const firstSegmentKey = () => {
777
795
  const first = orderedSegments()[0];
@@ -814,6 +832,7 @@ var DatePicker = (0, import_react3.forwardRef)(
814
832
  if (start || end) applySelection([start, end], false);
815
833
  };
816
834
  const commitPart = (group, type, rawValue) => {
835
+ markDirty();
817
836
  const clamped = clampDatePart(type, rawValue, groups[group]);
818
837
  const next = groups.map((g, i) => {
819
838
  if (i !== group) return g;
@@ -862,6 +881,7 @@ var DatePicker = (0, import_react3.forwardRef)(
862
881
  setEdit(null);
863
882
  if (committed !== null) advance(active);
864
883
  } else {
884
+ markDirty();
865
885
  setEdit({ group: active.group, type: active.type, buffer });
866
886
  }
867
887
  };
@@ -899,6 +919,7 @@ var DatePicker = (0, import_react3.forwardRef)(
899
919
  e.preventDefault();
900
920
  const active = activeSegment ?? firstSegmentKey();
901
921
  if (!active) return;
922
+ markDirty();
902
923
  const sameActive = edit && edit.group === active.group && edit.type === active.type;
903
924
  if (sameActive && edit.buffer.length > 0) {
904
925
  const buffer = edit.buffer.slice(0, -1);
@@ -950,6 +971,11 @@ var DatePicker = (0, import_react3.forwardRef)(
950
971
  suppressReopenRef.current = false;
951
972
  return;
952
973
  }
974
+ sessionRef.current = {
975
+ dirty: false,
976
+ cleared: sessionRef.current.cleared,
977
+ propKey
978
+ };
953
979
  setFocused(true);
954
980
  setOpen(true);
955
981
  if (isWeb && editable) setActiveSegment(firstSegmentKey());
@@ -966,7 +992,19 @@ var DatePicker = (0, import_react3.forwardRef)(
966
992
  onBlurProp?.(e);
967
993
  setFocused(false);
968
994
  setActiveSegment(null);
995
+ if (sessionRef.current.propKey !== propKey && !sessionRef.current.dirty) {
996
+ sessionRef.current = { dirty: false, cleared: false, propKey };
997
+ setEdit(null);
998
+ setParseError(null);
999
+ setGroups(propGroups());
1000
+ return;
1001
+ }
969
1002
  if (!editable) return;
1003
+ if (sessionRef.current.cleared && !sessionRef.current.dirty) {
1004
+ setEdit(null);
1005
+ setParseError(null);
1006
+ return;
1007
+ }
970
1008
  let next = groups;
971
1009
  if (edit) {
972
1010
  const clamped = clampDatePart(
@@ -1023,6 +1061,7 @@ var DatePicker = (0, import_react3.forwardRef)(
1023
1061
  setParseError("Date must be within the allowed range");
1024
1062
  return;
1025
1063
  }
1064
+ markDirty();
1026
1065
  setParseError(null);
1027
1066
  setEdit(null);
1028
1067
  setGroups(next);
@@ -1033,13 +1072,29 @@ var DatePicker = (0, import_react3.forwardRef)(
1033
1072
  setInternalChip(value);
1034
1073
  onChipSelect?.(value);
1035
1074
  };
1075
+ const handleClear = () => {
1076
+ const next = isRange ? [datePartsFromDate(null), datePartsFromDate(null)] : [datePartsFromDate(null)];
1077
+ sessionRef.current.dirty = false;
1078
+ sessionRef.current.cleared = true;
1079
+ setGroups(next);
1080
+ setEdit(null);
1081
+ setParseError(null);
1082
+ setInternalChip(null);
1083
+ onChipSelect?.(null);
1084
+ if (isWeb && editable) setActiveSegment(firstSegmentKey());
1085
+ onClear?.();
1086
+ if (isRange) {
1087
+ const emptyRange = [null, null];
1088
+ onChange?.(emptyRange);
1089
+ }
1090
+ };
1036
1091
  const handleDateChange = (date) => applySelection(date, closeOnComplete);
1037
1092
  const closePanel = (0, import_react3.useCallback)(() => setOpen(false), []);
1038
1093
  const renderTopContent = topContent ? () => topContent({ close: closePanel }) : void 0;
1039
1094
  const renderBottomContent = bottomContent ? () => bottomContent({ close: closePanel }) : void 0;
1040
- const propKey = `${selectedDate?.getTime() ?? ""}|${startDate?.getTime() ?? ""}|${endDate?.getTime() ?? ""}|${isRange}`;
1041
1095
  (0, import_react3.useEffect)(() => {
1042
1096
  if (focused) return;
1097
+ sessionRef.current = { dirty: false, cleared: false, propKey };
1043
1098
  setGroups(propGroups());
1044
1099
  setEdit(null);
1045
1100
  setParseError(null);
@@ -1216,6 +1271,7 @@ var DatePicker = (0, import_react3.forwardRef)(
1216
1271
  ...rest,
1217
1272
  ref: inputRef,
1218
1273
  size,
1274
+ label,
1219
1275
  placeholder: placeholder || (isRange ? "Choose a date range" : "Choose a date"),
1220
1276
  value: inputValue,
1221
1277
  readOnly,
@@ -1226,6 +1282,8 @@ var DatePicker = (0, import_react3.forwardRef)(
1226
1282
  onPaste: handlePaste,
1227
1283
  iconRight,
1228
1284
  iconLeft,
1285
+ extraClear: showClear,
1286
+ onRemove: handleClear,
1229
1287
  error: error || !!parseError,
1230
1288
  errorMessage: parseError ?? errorMessage,
1231
1289
  backgroundColor,