UNPKG

@furystack/shades-common-components

Version:

Common UI components for FuryStack Shades

111 lines 5.46 kB
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