@crossed/ui
Version:
A universal & performant styling library for React Native, Next.js & React
132 lines (131 loc) • 3.96 kB
JavaScript
import { useUncontrolled } from "@crossed/core";
import { useCallback, useEffect, useMemo, useRef } from "react";
import { getOrderWithFormat, getSeparator } from "./utils";
import { match } from "ts-pattern";
import { isWeb } from "@crossed/styled";
const useDateInput = ({
value: valueProps,
onChange: onChangeProps,
defaultValue,
locale = "en",
format = "yyyy-mm-dd",
placeholder = {}
}) => {
const order = getOrderWithFormat(locale, format);
const separator = getSeparator(locale);
const inputRef = useRef([]);
useEffect(() => {
if (isWeb) {
inputRef.current = [];
return () => {
inputRef.current = [];
};
}
return () => {
};
}, [locale]);
const [value, setValue] = useUncontrolled({
value: valueProps,
defaultValue,
onChange: onChangeProps
});
const add = useCallback((name, r) => {
if (r) {
const index = inputRef.current.findIndex(({ name: n }) => n === name);
if (index >= 0) {
inputRef.current[index] = { ref: r, name };
} else {
inputRef.current.push({ ref: r, name });
}
}
}, []);
const onChange = useCallback(
(name, v) => {
var _a;
const valueNumber = Number(v);
if (isNaN(valueNumber)) {
setValue({
...value,
[name === "dd" ? "day" : name === "mm" ? "month" : "year"]: ""
});
return;
}
if (name === "dd" && `${valueNumber}`.length <= 2) {
setValue({ ...value, day: valueNumber });
} else if (name === "mm" && `${valueNumber}`.length <= 2) {
setValue({ ...value, month: valueNumber });
} else if (name === "yyyy" && `${valueNumber}`.length <= 4) {
setValue({ ...value, year: valueNumber });
}
const index = inputRef.current.findIndex(({ name: n }) => n === name);
if (index >= 0 && index < 2) {
const shouldNext = ["dd", "mm"].includes(name) ? `${v}`.length >= 2 : `${v}`.length >= 4;
shouldNext && ((_a = inputRef.current[index + 1]) == null ? void 0 : _a.ref.focus());
}
},
[setValue, value]
);
const setWithDate = useCallback(
(date) => {
if (date)
setValue({
day: date.getDate(),
month: date.getMonth() + 1,
year: date.getFullYear()
});
},
[setValue]
);
const inputs = useMemo(() => {
return order.map((e) => ({
key: e,
ref: (ref) => add(e, ref),
onChangeText: (v) => onChange(e, v),
...match(e).with("dd", (r) => {
var _a, _b;
return {
value: (_a = value == null ? void 0 : value.day) == null ? void 0 : _a.toString().padStart(2, "0"),
placeholder: placeholder.day ?? r,
label: (_b = value == null ? void 0 : value.day) == null ? void 0 : _b.toLocaleString(locale, {
minimumIntegerDigits: 2
})
};
}).with("mm", (r) => {
var _a, _b;
return {
value: (_a = value == null ? void 0 : value.month) == null ? void 0 : _a.toString().padStart(2, "0"),
placeholder: placeholder.month ?? r,
label: (_b = value == null ? void 0 : value.month) == null ? void 0 : _b.toLocaleString(locale, {
minimumIntegerDigits: 2
})
};
}).with("yyyy", (r) => {
var _a;
return {
placeholder: placeholder.year ?? r,
value: (_a = value == null ? void 0 : value.year) == null ? void 0 : _a.toString().padStart(4, "0")
};
}).exhaustive()
}));
}, [value, order, add, onChange, placeholder, locale]);
const containerProps = useMemo(() => {
return {
onPress: () => {
var _a;
(_a = inputRef.current[0]) == null ? void 0 : _a.ref.focus();
}
};
}, []);
return {
containerProps,
value,
onChange,
inputs,
separator,
setWithDate
};
};
export {
useDateInput
};
//# sourceMappingURL=useDateInput.js.map