@harvest-profit/npk
Version:
NPK UI Design System
207 lines • 12.5 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const BaseInput_1 = __importDefault(require("../BaseInput"));
const Group_1 = __importDefault(require("../Input/Group"));
const Calendar_1 = __importDefault(require("../Calendar"));
const Menu_1 = __importDefault(require("../Menu"));
const Button_1 = __importDefault(require("../Button"));
const regular_1 = require("@harvest-profit/npk/icons/regular");
const InputSegment_1 = __importDefault(require("./InputSegment"));
const utils_1 = require("../Calendar/utils");
const GranularityInclude = ({ children, active }) => active ? children : null;
const hourAndTODfromDate = (date) => {
if (!date)
return {};
const hours = date.getHours();
const tod = hours >= 12 ? 'PM' : 'AM';
const hour = hours % 12 || 12; // Convert to 12-hour format
return { hour, tod };
};
// Shifts focus to the next input segment
const useDateGroupFocus = () => {
const onMouseDown = (e) => {
if (document.activeElement === e.target)
return;
if (!e.target.ariaHidden && e.target.dataset.component === 'input-segment')
return;
const rootNode = e.target?.dataset?.component === 'input-group' ? e.target : e.target?.closest('[data-component="input-group"]');
if (rootNode && rootNode.contains(document.activeElement)) {
e.preventDefault();
return;
}
const focusNearest = (node) => {
if (!node)
return;
if (node.ariaHidden)
focusNearest(node.nextElementSibling);
if (node.dataset.component === 'input-group')
focusNearest(node.firstElementChild);
node.focus();
};
focusNearest(e.target);
};
return { onMouseDown };
};
// Simple hook to manage state and call a callback when the value changes
const useOnChangeState = (initialValue, cb) => {
const [state, setState] = (0, react_1.useState)(initialValue);
return [state, (newValue) => {
if (newValue === state)
return;
setState(newValue);
if (cb && newValue)
cb(newValue);
}];
};
// Controls the individual segments of the date input
const DateInputInternal = ({ onChange = (_value) => null, value, includeYear = true, monthAsName = false, granularity = 'day', excludeGroup = false, ...props }) => {
let updateValue = new Date(); // When updating a new date, we build off the current date and then set individual values
let segmentDateValue = value; // We then use a date segment and a time segment for the values of the segments
let segmentTimeValue = value; // If "value" is not a complete date, we do not fill out the input. Time will be null if the time is 00:00:00.000
if (value instanceof Date && !isNaN(value.getTime())) {
updateValue = value;
if (value.getHours() === 0 && value.getMinutes() === 0 && value.getMilliseconds() === 0) {
segmentTimeValue = null;
}
}
else {
segmentDateValue = null;
segmentTimeValue = null;
}
const toMonthValue = monthAsName ? utils_1.monthIndexToAbbrev : utils_1.monthIndexToHuman;
const fromMonthValue = monthAsName ? utils_1.monthAbbrevToIndex : utils_1.monthHumanToIndex;
// Specify the rules of getting and setting the values of the segments
const [monthValue, setMonthValue] = useOnChangeState(toMonthValue(segmentDateValue?.getMonth()), (month) => onChange(new Date(new Date(updateValue).setMonth(fromMonthValue(month)))));
const [dayValue, setDayValue] = useOnChangeState(segmentDateValue?.getDate(), (day => onChange(new Date(new Date(updateValue).setDate(day)))));
const [yearValue, setYearValue] = useOnChangeState(segmentDateValue?.getFullYear(), (year => onChange(new Date(new Date(updateValue).setFullYear(year)))));
const [minuteValue, setMinuteValue] = useOnChangeState(segmentTimeValue?.getMinutes(), (minutes => onChange(new Date(new Date(updateValue).setMinutes(minutes)))));
const [todValue, setTODValue] = useOnChangeState(hourAndTODfromDate(segmentTimeValue).tod, (tod) => {
const hours = new Date(updateValue).getHours();
if (tod === 'AM' && hours >= 12) {
onChange(new Date(new Date(updateValue).setHours(hours - 12)));
}
else if (tod === 'PM' && hours < 12) {
onChange(new Date(new Date(updateValue).setHours(hours + 12)));
}
});
const [hourValue, setHourValue] = useOnChangeState(hourAndTODfromDate(segmentTimeValue).hour, (hour) => {
const intHours = parseInt(hour);
if (todValue === 'AM' && intHours === 12) { // hours are tricky because of the 12-hour format. Native date objects are 24-hour format
onChange(new Date(new Date(updateValue).setHours(0)));
}
else if (todValue === 'PM' && intHours < 12) {
onChange(new Date(new Date(updateValue).setHours(intHours + 12)));
}
else {
onChange(new Date(new Date(updateValue).setHours(hour)));
}
});
const ref = (0, react_1.useRef)(null);
const [isInputSegmentInFocus, setInputSegmentFocused] = (0, react_1.useState)(false);
const [isFocused, setIsFocused] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
if (!isFocused) { // if the input is out of focus, we will accept updates from outside changes
setMonthValue(toMonthValue(segmentDateValue?.getMonth()));
setDayValue(segmentDateValue?.getDate());
setYearValue(segmentDateValue?.getFullYear());
setHourValue(hourAndTODfromDate(segmentTimeValue).hour);
setTODValue(hourAndTODfromDate(segmentTimeValue).tod);
setMinuteValue(segmentDateValue?.getMinutes());
}
}, [`${value}`]);
(0, react_1.useEffect)(() => {
setTimeout(() => {
if (ref.current) {
if (!isFocused && ref.current.contains(document.activeElement)) {
setIsFocused(true);
if (props.onFocus)
props.onFocus({ target: ref.current });
}
else if (isFocused && !ref.current.contains(document.activeElement)) {
setIsFocused(false);
if (props.onBlur)
props.onBlur({ target: ref.current });
}
}
}, 10);
}, [isInputSegmentInFocus]);
const dateParts = [];
if (['day', 'month', 'minute'].includes(granularity)) {
dateParts.push((0, jsx_runtime_1.jsx)(InputSegment_1.default, { segment: monthAsName ? 'monthName' : 'month', setIsFocused: setInputSegmentFocused, value: monthValue, onChange: setMonthValue }));
}
if (['day', 'minute'].includes(granularity)) {
dateParts.push((0, jsx_runtime_1.jsx)(InputSegment_1.default, { segment: "day", setIsFocused: setInputSegmentFocused, value: dayValue, onChange: setDayValue, onOldChange: (day => onChange(new Date(new Date(updateValue).setDate(day)))) }));
}
if (includeYear && ['day', 'month', 'year', 'minute'].includes(granularity)) {
dateParts.push((0, jsx_runtime_1.jsx)(InputSegment_1.default, { segment: "year", setIsFocused: setInputSegmentFocused, value: yearValue, onChange: setYearValue, onOldChange: (year => onChange(new Date(new Date(updateValue).setFullYear(year)))) }));
}
const contents = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [dateParts.map((part, index) => {
return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [index !== 0 && (0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", "data-component": "input-segment", children: monthAsName ? ' ' : '/' }), part] }, index));
}), (0, jsx_runtime_1.jsxs)(GranularityInclude, { active: ['minute'].includes(granularity), children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", "data-component": "input-segment", children: ", " }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", "data-component": "input-segment" })] }), (0, jsx_runtime_1.jsxs)(GranularityInclude, { active: ['minute', 'time'].includes(granularity), children: [(0, jsx_runtime_1.jsx)(InputSegment_1.default, { segment: "hour", setIsFocused: setInputSegmentFocused, value: hourValue, onChange: setHourValue }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", "data-component": "input-segment", children: ":" }), (0, jsx_runtime_1.jsx)(InputSegment_1.default, { segment: "minute", setIsFocused: setInputSegmentFocused, value: minuteValue, onChange: setMinuteValue }), (0, jsx_runtime_1.jsx)("span", { "aria-hidden": "true", "data-component": "input-segment" }), (0, jsx_runtime_1.jsx)(InputSegment_1.default, { segment: "TOD", setIsFocused: setInputSegmentFocused, value: todValue, onChange: setTODValue })] })] }));
const dateGroupProps = useDateGroupFocus();
if (excludeGroup) {
return ((0, jsx_runtime_1.jsx)(BaseInput_1.default, { containsSegments: true, contentsRef: ref, ...dateGroupProps, ...props, children: contents }));
}
return ((0, jsx_runtime_1.jsx)(Group_1.default, { containsSegments: true, contentsRef: ref, ...dateGroupProps, ...props, children: contents }));
};
const DateInput = ({ visibleMonths = 1, autoDismiss = true, presets = false, picker = false, output = 'ISO', includeYear = true, monthAsName = false, onChange: onExternalChange = (_value) => null, value: externalValue, granularity = 'day', excludeGroup, ...props }) => {
let value = externalValue;
let onChange = onExternalChange;
switch (output) {
case 'ISO':
value = (0, utils_1.fromISO)(value);
onChange = (newValue) => onExternalChange((0, utils_1.toISO)(newValue));
break;
case 'timestamp':
value = (0, utils_1.fromTimestamp)(value);
onChange = (newValue) => onExternalChange((0, utils_1.toTimestamp)(newValue));
break;
default:
break;
}
const extraProps = {};
if (picker) {
extraProps.trailingVisual = ((0, jsx_runtime_1.jsxs)(Menu_1.default, { arrow: true, placement: "bottom", autoDismiss: false, children: [(0, jsx_runtime_1.jsx)(Button_1.default, { invisible: true, icon: regular_1.CalendarIcon, "aria-label": "Pick a date", tabIndex: -1 }), (0, jsx_runtime_1.jsx)(Menu_1.default.Overlay, { children: (0, jsx_runtime_1.jsx)(Calendar_1.default, { visibleMonths: visibleMonths, presets: presets, value: value, onChange: onChange, output: "date", autoDismiss: autoDismiss }) })] }));
}
return ((0, jsx_runtime_1.jsx)(DateInputInternal, { onChange: onChange, value: value, granularity: granularity, excludeGroup: excludeGroup, includeYear: includeYear, monthAsName: monthAsName, ...props, ...extraProps }));
};
exports.default = DateInput;
//# sourceMappingURL=DateInput.js.map