@furystack/shades-common-components
Version:
Common UI components for FuryStack Shades
85 lines • 4.64 kB
JavaScript
import { createComponent, Shade } from '@furystack/shades';
import { cssVariableTheme } from '../../services/css-variable-theme.js';
import { DataGridBody } from './body.js';
import { DataGridFooter } from './footer.js';
import { DataGridHeader } from './header.js';
let nextDataGridId = 0;
export const DataGrid = Shade({
customElementName: 'shade-data-grid',
css: {
display: 'block',
fontFamily: cssVariableTheme.typography.fontFamily,
width: '100%',
height: '100%',
overflow: 'auto',
zIndex: '1',
'& table': {
width: '100%',
maxHeight: 'calc(100% - 4em)',
position: 'relative',
borderCollapse: 'collapse',
},
'& th': {
backdropFilter: 'blur(12px) saturate(180%)',
background: cssVariableTheme.action.activeBackground,
color: cssVariableTheme.text.secondary,
height: '36px',
padding: '0 0.6em',
alignItems: 'center',
top: '0',
position: 'sticky',
fontSize: '0.75rem',
fontWeight: cssVariableTheme.typography.fontWeight.semibold,
letterSpacing: '0.03em',
textAlign: 'left',
zIndex: '1',
borderBottom: `1px solid ${cssVariableTheme.action.subtleBorder}`,
borderRight: `1px solid ${cssVariableTheme.action.subtleBorder}`,
},
},
render: ({ props, useDisposable, useRef, useHostProps, useState }) => {
const wrapperRef = useRef('gridWrapper');
const [navSectionId] = useState('navSectionId', String(nextDataGridId++));
const headerFindOptions = props.findOptions;
const handleHeaderChange = props.onFindOptionsChange;
useDisposable('keydown-handler', () => {
const listener = (ev) => props.collectionService.handleKeyDown(ev);
window.addEventListener('keydown', listener, true);
return { [Symbol.dispose]: () => window.removeEventListener('keydown', listener, true) };
});
useDisposable('focus-coordination', () => {
const handleFocusOut = (ev) => {
const wrapper = wrapperRef.current;
if (wrapper && (!ev.relatedTarget || !wrapper.contains(ev.relatedTarget))) {
props.collectionService.hasFocus.setValue(false);
}
};
queueMicrotask(() => {
const wrapper = wrapperRef.current;
if (wrapper) {
wrapper.addEventListener('focusout', handleFocusOut);
}
});
return {
[Symbol.dispose]: () => {
const wrapper = wrapperRef.current;
if (wrapper) {
wrapper.removeEventListener('focusout', handleFocusOut);
}
},
};
});
if (props.styles?.wrapper) {
useHostProps({ style: props.styles.wrapper });
}
return (createComponent("div", { ref: wrapperRef, className: "shade-grid-wrapper", "data-nav-section": props.navSection ?? `data-grid-${navSectionId}`, ariaMultiSelectable: "true" },
createComponent("table", null,
createComponent("thead", null,
createComponent("tr", null, props.columns.map((column) => {
return (createComponent("th", { style: props.styles?.header }, props.headerComponents?.[column]?.(column) || props.headerComponents?.default?.(column) || (createComponent(DataGridHeader, { field: column, findOptions: headerFindOptions, onFindOptionsChange: handleHeaderChange, filterConfig: props.columnFilters?.[column] }))));
}))),
createComponent(DataGridBody, { columns: props.columns, service: props.collectionService, rowComponents: props.rowComponents, onRowClick: (entry, ev) => props.collectionService.handleRowClick(entry, ev), onRowDoubleClick: (entry) => props.collectionService.handleRowDoubleClick(entry), style: props.styles?.cell, focusedRowStyle: props.focusedRowStyle, selectedRowStyle: props.selectedRowStyle, unfocusedRowStyle: props.unfocusedRowStyle, unselectedRowStyle: props.unselectedRowStyle, emptyComponent: props.emptyComponent, loaderComponent: props.loaderComponent })),
createComponent(DataGridFooter, { service: props.collectionService, findOptions: props.findOptions, onFindOptionsChange: props.onFindOptionsChange, paginationOptions: props.paginationOptions })));
},
});
//# sourceMappingURL=data-grid.js.map