@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
138 lines (137 loc) • 5.51 kB
JavaScript
import * as React from 'react';
import { forwardRef, useImperativeHandle } from 'react';
import { renderWithAdaptableContext } from '../View/renderWithAdaptableContext';
import { AdaptableFloatingFilter } from '../View/Components/ColumnFilter/AdaptableFloatingFilter';
import { getAgGridFilterNotifyModelFn } from './getAgGridFilterNotifyModelFn';
const filterContainerStyle = {
overflow: 'hidden',
minWidth: '0',
height: '100%',
display: 'flex',
alignItems: 'stretch',
position: 'relative',
flex: '1 1 auto',
};
export const FloatingFilterWrapperFactory = (adaptable) => {
const adaptableApi = adaptable.api;
function getContainerId(colId) {
return `floatingFilter_${colId}_${adaptable.adaptableOptions.adaptableId}`;
}
function getFilterProps(colId) {
const column = adaptableApi.columnApi.getColumnWithColumnId(colId);
const columnFilterProps = {
Column: column,
Adaptable: adaptable,
ShowCloseButton: false,
};
return columnFilterProps;
}
function getNotifyModel(colId, onModelChange) {
return getAgGridFilterNotifyModelFn(adaptableApi, colId, onModelChange);
}
function findParentWithClass(element, className, stopClasses, applyToAll) {
let current = element.parentElement;
while (current) {
// Stop traversing if we hit any of the stop classes
if (stopClasses.some((stopClass) => current.classList.contains(stopClass))) {
return null;
}
if (current.classList.contains(className)) {
return current;
}
applyToAll?.(current);
current = current.parentElement;
}
return null;
}
function patchParentElement(filterContainer) {
if (!filterContainer) {
return;
}
const stopClasses = ['ag-header-row', 'ag-header-row-column-filter'];
// Find and update floating filter body
const filterBody = findParentWithClass(filterContainer, 'ag-floating-filter-full-body', stopClasses, (currentElem) => {
currentElem.style.height = '100%';
});
if (filterBody) {
filterBody.style.overflow = 'visible';
}
// Find and update header cell
const headerCell = findParentWithClass(filterContainer, 'ag-header-cell', stopClasses);
if (headerCell?.classList.contains('ag-floating-filter')) {
headerCell.style.padding = 'var(--ab-space-1)';
}
}
if (adaptable.isAgGridInitialising) {
if (adaptable.variant === 'react') {
return () => React.createElement(React.Fragment, null);
}
return class FloatingFilterStub {
init(params) {
this.filterContainer = document.createElement('div');
}
getGui() {
return this.filterContainer;
}
destroy() {
this.unmountReactRoot?.();
this.filterContainer = null;
}
onParentModelChanged() {
// nothing yet
}
};
}
if (adaptable.variant === 'react') {
return forwardRef(function ReactFloatingFilterWrapper(props, ref) {
const colId = props.column.getId();
const { onModelChange } = props;
const column = adaptableApi.columnApi.getColumnWithColumnId(colId);
useImperativeHandle(ref, () => {
return {
onParentModelChanged() { },
};
});
const notifyModel = getNotifyModel(colId, onModelChange);
if (!column) {
return null;
}
return renderWithAdaptableContext(React.createElement("div", { ref: patchParentElement, id: getContainerId(colId), style: filterContainerStyle },
React.createElement(AdaptableFloatingFilter, { ...getFilterProps(colId), onChange: notifyModel, onClear: notifyModel })), adaptable);
});
}
return class FloatingFilterWrapper {
onParentModelChanged(parentModel, filterChangedEvent) {
// todo?
}
afterGuiAttached() {
patchParentElement(this.filterContainer);
}
init(params) {
const colId = params.column.getColId();
this.filterContainer = document.createElement('div');
this.filterContainer.id = getContainerId(colId);
Object.keys(filterContainerStyle).forEach((key) => {
//@ts-ignore
this.filterContainer.style[key] = filterContainerStyle[key];
});
const notifyModel = getNotifyModel(colId, params.filterParams.filterChangedCallback);
const column = adaptableApi.columnApi.getColumnWithColumnId(colId);
if (column) {
const filterProps = getFilterProps(colId);
this.unmountReactRoot = adaptable.renderReactRoot(renderWithAdaptableContext(React.createElement(AdaptableFloatingFilter, {
...filterProps,
onChange: notifyModel,
onClear: notifyModel,
}), adaptable), this.filterContainer);
}
}
getGui() {
return this.filterContainer;
}
destroy() {
this.unmountReactRoot?.();
this.filterContainer = null;
}
};
};