@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
108 lines • 5.57 kB
JavaScript
import { Shade, createComponent } from '@furystack/shades';
import { ToggleButton } from '../button-group.js';
import { arrowDown, arrowUp, arrowUpDown, filter as filterIcon } from '../icons/icon-definitions.js';
import { Icon } from '../icons/icon.js';
import { cssVariableTheme } from '../../services/css-variable-theme.js';
import { BooleanFilter } from './filters/boolean-filter.js';
import { DateFilter } from './filters/date-filter.js';
import { EnumFilter } from './filters/enum-filter.js';
import { FilterDropdown } from './filters/filter-dropdown.js';
import { NumberFilter } from './filters/number-filter.js';
import { StringFilter } from './filters/string-filter.js';
export const OrderButton = Shade({
customElementName: 'data-grid-order-button',
css: {
display: 'inline-block',
},
render: ({ props }) => {
const { findOptions } = props;
const currentOrder = Object.keys(findOptions.order || {})[0];
const currentOrderDirection = Object.values(findOptions.order || {})[0];
return (createComponent(ToggleButton, { title: "Change order", pressed: currentOrder === props.field, size: "small", value: props.field, onclick: (ev) => {
ev.stopPropagation();
let newDirection = 'ASC';
const newOrder = {};
if (currentOrder === props.field) {
newDirection = currentOrderDirection === 'ASC' ? 'DESC' : 'ASC';
}
newOrder[props.field] = newDirection;
props.onFindOptionsChange({
...findOptions,
order: newOrder,
});
} }, (currentOrder === props.field &&
(currentOrderDirection === 'ASC' ? (createComponent(Icon, { icon: arrowDown, size: 14 })) : (createComponent(Icon, { icon: arrowUp, size: 14 })))) || createComponent(Icon, { icon: arrowUpDown, size: 14 })));
},
});
const FilterButton = Shade({
customElementName: 'data-grid-filter-button',
css: {
display: 'inline-block',
},
render: ({ props }) => {
const hasActiveFilter = !!props.findOptions.filter?.[props.field];
return (createComponent(ToggleButton, { type: "button", title: "Filter", size: "small", value: props.field, pressed: hasActiveFilter, onclick: (ev) => {
ev.stopPropagation();
props.onclick();
} },
createComponent(Icon, { icon: filterIcon, size: 14 })));
},
});
const renderFilterComponent = (filterConfig, field, findOptions, onFindOptionsChange, onClose) => {
switch (filterConfig.type) {
case 'number':
return (createComponent(NumberFilter, { field: field, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, onClose: onClose }));
case 'boolean':
return (createComponent(BooleanFilter, { field: field, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, onClose: onClose }));
case 'enum':
return (createComponent(EnumFilter, { field: field, values: filterConfig.values, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, onClose: onClose }));
case 'date':
return (createComponent(DateFilter, { field: field, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, onClose: onClose }));
case 'string':
return (createComponent(StringFilter, { field: field, findOptions: findOptions, onFindOptionsChange: onFindOptionsChange, onClose: onClose }));
default: {
const _exhaustive = filterConfig;
throw new Error(`Unknown filter type: ${_exhaustive.type}`);
}
}
};
export const DataGridHeader = Shade({
customElementName: 'data-grid-header',
css: {
display: 'block',
fontFamily: cssVariableTheme.typography.fontFamily,
position: 'relative',
'& .header-content': {
display: 'flex',
width: '100%',
height: '36px',
justifyContent: 'space-between',
alignItems: 'center',
gap: '8px',
overflow: 'hidden',
},
'& .header-field-name': {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
'& .header-controls': {
display: 'flex',
alignItems: 'center',
gap: '2px',
flexShrink: '0',
},
},
render: ({ props, useState }) => {
const [isFilterOpen, setIsFilterOpen] = useState('isFilterOpen', false);
const closeFilter = () => setIsFilterOpen(false);
return (createComponent(createComponent, null,
createComponent("div", { className: "header-content" },
createComponent("div", { className: "header-field-name" }, props.field),
createComponent("div", { className: "header-controls" },
props.filterConfig && (createComponent(FilterButton, { onclick: () => setIsFilterOpen(!isFilterOpen), findOptions: props.findOptions, field: props.field })),
createComponent(OrderButton, { field: props.field, findOptions: props.findOptions, onFindOptionsChange: props.onFindOptionsChange }))),
isFilterOpen && props.filterConfig && (createComponent(FilterDropdown, { onClose: closeFilter }, renderFilterComponent(props.filterConfig, props.field, props.findOptions, props.onFindOptionsChange, closeFilter)))));
},
});
//# sourceMappingURL=header.js.map