@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
111 lines • 5.46 kB
JavaScript
import { createComponent, Shade } from '@furystack/shades';
import { SegmentedControl } from '../../button-group.js';
import { Button } from '../../button.js';
import { close as closeIcon, search as searchIcon } from '../../icons/icon-definitions.js';
import { Icon } from '../../icons/icon.js';
import { cssVariableTheme } from '../../../services/css-variable-theme.js';
import { filterBaseCss, filterInputCss } from './filter-styles.js';
export const DateFilter = Shade({
customElementName: 'data-grid-date-filter',
css: {
...filterBaseCss,
fontFamily: cssVariableTheme.typography.fontFamily,
'& input[type="datetime-local"]': filterInputCss,
},
render: ({ props, useState }) => {
const { findOptions } = props;
const currentFilter = findOptions.filter?.[props.field];
const detectMode = () => {
if (currentFilter?.$gte && currentFilter?.$lte)
return 'between';
if (currentFilter?.$lt)
return 'before';
if (currentFilter?.$gt)
return 'after';
return 'before';
};
const toLocalDateTimeString = (date) => {
if (!date)
return '';
const d = date instanceof Date ? date : new Date(date);
if (isNaN(d.getTime()))
return '';
const pad = (n) => n.toString().padStart(2, '0');
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
};
const getInitialValue = () => {
if (currentFilter?.$gte)
return toLocalDateTimeString(currentFilter.$gte);
if (currentFilter?.$lt)
return toLocalDateTimeString(currentFilter.$lt);
if (currentFilter?.$gt)
return toLocalDateTimeString(currentFilter.$gt);
return '';
};
const getInitialSecondValue = () => {
if (currentFilter?.$lte)
return toLocalDateTimeString(currentFilter.$lte);
return '';
};
const [selectedMode, setSelectedMode] = useState('selectedMode', detectMode());
let dateValue = getInitialValue();
let secondDateValue = getInitialSecondValue();
const applyFilter = () => {
const filter = { ...findOptions.filter };
if (!dateValue) {
delete filter[props.field];
props.onFindOptionsChange({ ...findOptions, filter, skip: 0 });
props.onClose();
return;
}
let filterValue;
switch (selectedMode) {
case 'before':
filterValue = { $lt: new Date(dateValue) };
break;
case 'after':
filterValue = { $gt: new Date(dateValue) };
break;
case 'between':
filterValue = {
$gte: new Date(dateValue),
...(secondDateValue ? { $lte: new Date(secondDateValue) } : {}),
};
break;
default:
throw new Error(`Invalid date mode: ${selectedMode}`);
}
filter[props.field] = filterValue;
props.onFindOptionsChange({ ...findOptions, filter, skip: 0 });
props.onClose();
};
const clearFilter = () => {
const filter = { ...findOptions.filter };
delete filter[props.field];
props.onFindOptionsChange({ ...findOptions, filter, skip: 0 });
props.onClose();
};
return (createComponent("form", { onsubmit: (ev) => {
ev.preventDefault();
applyFilter();
} },
createComponent("div", { className: "filter-row" },
createComponent(SegmentedControl, { size: "small", value: selectedMode, onValueChange: (v) => setSelectedMode(v), options: [
{ value: 'before', label: 'Before' },
{ value: 'after', label: 'After' },
{ value: 'between', label: 'Between' },
] })),
createComponent("div", { className: "filter-row" },
createComponent("input", { "data-testid": "date-filter-value", type: "datetime-local", value: dateValue, autofocus: true, oninput: (ev) => {
dateValue = ev.target.value;
} })),
createComponent("div", { className: "filter-row", style: { display: selectedMode === 'between' ? 'flex' : 'none' } },
createComponent("input", { "data-testid": "date-filter-value-end", type: "datetime-local", value: secondDateValue, oninput: (ev) => {
secondDateValue = ev.target.value;
} })),
createComponent("div", { className: "filter-actions" },
createComponent(Button, { type: "button", variant: "outlined", size: "small", onclick: clearFilter, startIcon: createComponent(Icon, { icon: closeIcon, size: 14 }) }, "Clear"),
createComponent(Button, { type: "submit", variant: "outlined", size: "small", color: "primary", startIcon: createComponent(Icon, { icon: searchIcon, size: 14 }) }, "Apply"))));
},
});
//# sourceMappingURL=date-filter.js.map