UNPKG

@furystack/shades-common-components

Version:

139 lines 6.97 kB
import { Shade, createComponent } from '@furystack/shades'; import { ObservableValue, sleepAsync } from '@furystack/utils'; import { collapse, expand } from '../animations.js'; import { Button } from '../button.js'; import { Form } from '../form.js'; import { Input } from '../inputs/input.js'; export const OrderButton = Shade({ shadowDomName: 'data-grid-order-button', render: ({ props, useObservable }) => { const [findOptions, onFindOptionsChange] = useObservable('findOptions', props.findOptions, {}); const currentOrder = Object.keys(findOptions.order || {})[0]; const currentOrderDirection = Object.values(findOptions.order || {})[0]; return (createComponent(Button, { title: "Change order", style: { padding: '4px', margin: '0', cursor: 'pointer', }, color: currentOrder === props.field ? 'info' : undefined, onclick: (ev) => { ev.stopPropagation(); let newDirection = 'ASC'; const newOrder = {}; if (currentOrder === props.field) { newDirection = currentOrderDirection === 'ASC' ? 'DESC' : 'ASC'; } newOrder[props.field] = newDirection; onFindOptionsChange({ ...findOptions, order: newOrder, }); } }, (currentOrder === props.field && (currentOrderDirection === 'ASC' ? '⬇' : '⬆')) || '↕')); }, }); const SearchButton = Shade({ shadowDomName: 'data-grid-search-button', render: ({ props, useObservable }) => { const [findOptions] = useObservable('currentValue', props.findOptions, { filter: (newValue) => { return !!newValue.filter?.[props.fieldName]; }, }); const filterValue = findOptions.filter?.[props.fieldName]?.$regex || ''; return (createComponent(Button, { type: "button", title: "Filter", style: { padding: '4px', margin: '0', cursor: 'pointer', }, onclick: props.onclick }, filterValue ? '🔍' : '🔎')); }, }); const SearchForm = Shade({ shadowDomName: 'data-grid-search-form', render: ({ props, useObservable }) => { const [findOptions] = useObservable('currentValue', props.findOptions, { filter: (newValue, lastValue) => { const newFilter = newValue.filter?.[props.fieldName]; const lastFilter = lastValue.filter?.[props.fieldName]; return newFilter?.$regex !== lastFilter?.$regex; }, }); const currentValue = findOptions.filter?.[props.fieldName]?.$regex || ''; return (createComponent(Form, { className: "search-form", style: { display: 'flex', width: '100%', overflow: 'hide', height: '0px', justifyContent: 'space-around', opacity: '0', }, validate: (data) => typeof data.searchValue?.length === 'number', onSubmit: ({ searchValue }) => { props.onSubmit(searchValue); } }, createComponent(Input, { style: { padding: '0px', paddingBottom: '0', margin: '0' }, placeholder: props.fieldName, autofocus: true, labelTitle: `${props.fieldName}`, name: "searchValue", value: typeof currentValue === 'string' ? currentValue : '', labelProps: { style: { padding: '0px 2em' }, } }), createComponent("div", { style: { display: 'flex', width: '64px', alignItems: 'center', justifyContent: 'center', gap: '8px' } }, createComponent(Button, { type: "reset", style: { padding: '4px', margin: '0' }, onclick: (ev) => { ev.preventDefault(); ev.stopPropagation(); props.onClear(); } }, "\u274C"), createComponent(Button, { style: { padding: '4px', margin: '0' }, type: "submit" }, "\uD83D\uDD0E")))); }, }); export const DataGridHeader = Shade({ shadowDomName: 'data-grid-header', render: ({ props, element, useObservable }) => { const [, setIsSearchOpened] = useObservable('isSearchOpened', new ObservableValue(false), { onChange: (newValue) => { const searchForm = element.querySelector('.search-form'); const headerContent = element.querySelector('.header-content'); if (!newValue) { void collapse(searchForm); void expand(headerContent); } else { searchForm.style.display = 'flex'; void expand(searchForm).then(async () => { await sleepAsync(100); searchForm.querySelector('input')?.focus(); }); void collapse(headerContent); } }, }); const [findOptions, setFindOptions] = useObservable('findOptions', props.findOptions); const updateSearchValue = (value) => { if (value) { const newSettings = { ...findOptions, filter: { ...findOptions.filter, [props.field]: { $regex: value }, }, }; setFindOptions(newSettings); } else { const { [props.field]: _, ...newFilter } = findOptions.filter || {}; setFindOptions({ ...findOptions, filter: newFilter }); } setIsSearchOpened(false); }; return (createComponent(createComponent, null, createComponent(SearchForm, { onSubmit: updateSearchValue, onClear: updateSearchValue, fieldName: props.field, findOptions: props.findOptions }), createComponent("div", { className: "header-content", style: { display: 'flex', width: '100%', height: '48px', justifyContent: 'space-between', alignItems: 'center', gap: '8px', overflow: 'hide', } }, createComponent("div", { style: { paddingLeft: '0.5em' } }, props.field), createComponent("div", { className: "header-controls", style: { display: 'flex', justifyContent: 'center', alignItems: 'center', paddingRight: '0.5em' } }, createComponent(SearchButton, { onclick: () => { setIsSearchOpened(true); }, findOptions: props.findOptions, fieldName: props.field }), createComponent(OrderButton, { field: props.field, findOptions: props.findOptions }))))); }, }); //# sourceMappingURL=header.js.map