UNPKG

@furystack/shades-common-components

Version:

Common UI components for FuryStack Shades

108 lines 5.57 kB
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