react-js-cron-mantine
Version:
Fork of [react-js-cron](https://github.com/xrutayisire/react-js-cron), made to work with [mantine](https://mantine.dev)
193 lines (179 loc) • 7.46 kB
JavaScript
const _excluded = ["value", "grid", "labelText", "optionsList", "setValue", "locale", "className", "humanizeLabels", "disabled", "readOnly", "leadingZero", "clockFormat", "period", "unit", "periodicityOnDoubleClick", "mode"];
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
import React, { useMemo, useCallback, useRef } from 'react';
import { MultiSelect } from '@mantine/core';
import { DEFAULT_LOCALE_EN } from '../locale';
import { classNames, sort } from '../utils';
import { parsePartArray, partToString, formatValue } from '../converter';
export default function CustomSelect(props) {
const {
value,
grid = true,
labelText,
optionsList,
setValue,
locale,
className,
humanizeLabels,
disabled,
readOnly,
leadingZero,
clockFormat,
period,
unit,
periodicityOnDoubleClick,
mode
} = props,
otherProps = _objectWithoutProperties(props, _excluded);
const stringValue = useMemo(() => {
if (value && Array.isArray(value)) {
return value.map(value => value.toString());
}
}, [value]);
const options = useMemo(() => {
if (optionsList) {
return optionsList.map((option, index) => {
const number = unit.min === 0 ? index : index + 1;
return {
value: number.toString(),
label: option
};
});
}
return [...Array(unit.total)].map((e, index) => {
const number = unit.min === 0 ? index : index + 1;
return {
value: number.toString(),
label: formatValue(number, unit, humanizeLabels, leadingZero, clockFormat)
};
});
}, [optionsList, leadingZero, humanizeLabels, clockFormat]);
const localeJSON = JSON.stringify(locale);
const renderTag = useCallback(props => {
const {
value: itemValue
} = props;
if (!value || value[0] !== Number(itemValue)) {
return React.createElement(React.Fragment, null);
}
const parsedArray = parsePartArray(value, unit);
const cronValue = partToString(parsedArray, unit, humanizeLabels, leadingZero, clockFormat);
const testEveryValue = cronValue.match(/^\*\/([0-9]+),?/) || [];
return React.createElement("div", null, testEveryValue[1] ? `${locale.everyText || DEFAULT_LOCALE_EN.everyText} ${testEveryValue[1]}` : cronValue);
}, [value, localeJSON, humanizeLabels, leadingZero, clockFormat]);
const simpleClick = useCallback(newValueOption => {
const newValueOptions = Array.isArray(newValueOption) ? sort(newValueOption) : [newValueOption];
let newValue = newValueOptions;
if (value) {
newValue = mode === 'single' ? [] : [...value];
newValueOptions.forEach(o => {
const newValueOptionNumber = Number(o);
if (value.some(v => v === newValueOptionNumber)) {
newValue = newValue.filter(v => v !== newValueOptionNumber);
} else {
newValue = sort([...newValue, newValueOptionNumber]);
}
});
}
if (newValue.length === unit.total) {
setValue([]);
} else {
setValue(newValue);
}
}, [setValue, value]);
const simpleClickMantine = useCallback(newValueOption => {
let newValue = newValueOption.map(Number);
newValue.sort((a, b) => a - b);
setValue(newValue);
}, [setValue, value]);
const doubleClick = useCallback(newValueOption => {
if (newValueOption !== 0 && newValueOption !== 1) {
const limit = unit.total + unit.min;
const newValue = [];
for (let i = unit.min; i < limit; i++) {
if (i % newValueOption === 0) {
newValue.push(i);
}
}
const oldValueEqualNewValue = value && newValue && value.length === newValue.length && value.every((v, i) => v === newValue[i]);
const allValuesSelected = newValue.length === options.length;
if (allValuesSelected) {
setValue([]);
} else if (oldValueEqualNewValue) {
setValue([]);
} else {
setValue(newValue);
}
} else {
setValue([]);
}
}, [value, options, setValue]);
const clicksRef = useRef([]);
const onOptionClick = useCallback(newValueOption => {
if (!readOnly) {
const doubleClickTimeout = 300;
const clicks = clicksRef.current;
clicks.push({
time: new Date().getTime(),
value: Number(newValueOption)
});
const id = window.setTimeout(() => {
if (periodicityOnDoubleClick && clicks.length > 1 && clicks[clicks.length - 1].time - clicks[clicks.length - 2].time < doubleClickTimeout) {
if (clicks[clicks.length - 1].value === clicks[clicks.length - 2].value) {
doubleClick(Number(newValueOption));
} else {
simpleClick([clicks[clicks.length - 2].value, clicks[clicks.length - 1].value]);
}
} else {
simpleClick(Number(newValueOption));
}
clicksRef.current = [];
}, doubleClickTimeout);
return () => {
window.clearTimeout(id);
};
}
}, [clicksRef, simpleClick, doubleClick, readOnly, periodicityOnDoubleClick]);
const onClear = useCallback(() => {
if (!readOnly) {
setValue([]);
}
}, [setValue, readOnly]);
const internalClassName = useMemo(() => classNames({
'react-js-cron-select': true,
'react-js-cron-custom-select': true,
[`${className}-select`]: !!className
}), [className]);
const dropdownClassNames = useMemo(() => classNames({
'react-js-cron-select-dropdown': true,
[`react-js-cron-select-dropdown-${unit.type}`]: true,
'react-js-cron-custom-select-dropdown': true,
[`react-js-cron-custom-select-dropdown-${unit.type}`]: true,
[`react-js-cron-custom-select-dropdown-minutes-large`]: unit.type === 'minutes' && period !== 'hour' && period !== 'day',
[`react-js-cron-custom-select-dropdown-minutes-medium`]: unit.type === 'minutes' && (period === 'day' || period === 'hour'),
'react-js-cron-custom-select-dropdown-hours-twelve-hour-clock': unit.type === 'hours' && clockFormat === '12-hour-clock',
'react-js-cron-custom-select-dropdown-grid': !!grid,
[`${className}-select-dropdown`]: !!className,
[`${className}-select-dropdown-${unit.type}`]: !!className
}), [className, grid, clockFormat, period]);
return React.createElement(React.Fragment, null, React.createElement(MultiSelect, {
withinPortal: true,
label: labelText,
data: options,
value: stringValue,
disabled: disabled,
sx: {
width: '100%'
},
styles: {
rightSection: {
pointerEvents: 'none'
}
},
rightSectionWidth: 40,
onChange: e => simpleClickMantine(e),
clearable: true,
placeholder: otherProps?.placeholder?.toString()
}));
}