@furystack/shades-common-components
Version:
139 lines • 6.97 kB
JavaScript
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