@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
168 lines (167 loc) • 7.46 kB
JavaScript
import * as React from 'react';
import { cloneElement, useRef } from 'react';
import join from '../utils/join';
import SimpleButton from '../SimpleButton';
import useExpanded from './useExpanded';
import renderItem from './renderItem';
import OverlayTrigger from '../OverlayTrigger';
export const DROPDOWN_ICON = (React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24" },
React.createElement("path", { d: "M7 10l5 5 5-5H7z" })));
const spacer = React.createElement("div", { style: { flex: 1 } });
const baseClassName = 'ab-DropdownButton';
const defaultListItemStyle = {
padding: 'var(--ab-cmp-dropdownbutton-list-item__padding)',
};
const DropdownButton = React.forwardRef((props, theRef) => {
let { columns, overlayProps, listOffset = 10, collapseOnItemClick = true, focusOnClear = true, idProperty = 'id', isItemDisabled, items, children, listMinWidth = 100, listStyle, listItemStyle, listItemClassName, constrainTo, showClearButton = false, onClear, clearButtonProps, onExpand, onCollapse, showToggleIcon = true, ...domProps } = props;
isItemDisabled = isItemDisabled || ((item) => item.disabled);
if (!columns) {
columns = ['icon', 'label'];
}
let content;
if (Array.isArray(items)) {
content = items.map((item, index) => {
if (item.separator) {
return (React.createElement("tr", { className: `${baseClassName}__separator`, key: index },
React.createElement("td", { colSpan: 2 })));
}
if (typeof listItemStyle === 'function') {
listItemStyle = listItemStyle(item, index);
}
const disabled = isItemDisabled(item);
const itemStyle = { ...defaultListItemStyle, ...listItemStyle };
const itemClassName = join(`${baseClassName}__list-item`, item.clickable === false || disabled
? `${baseClassName}__list-item--not-clickable`
: `${baseClassName}__list-item--clickable`, disabled ? `${baseClassName}__list-item--disabled` : '', listItemClassName);
const getItemHandler = (eventName) => {
return (e) => {
if (!disabled) {
if (item[eventName]) {
item[eventName](e, item);
}
}
if (collapseOnItemClick) {
if (!disabled) {
setExpanded(false);
}
buttonRef.current?.focus();
}
else {
e.nativeEvent.preventCollapse = true;
}
};
};
const domProps = {};
if (item.onChange) {
domProps.onChange = getItemHandler('onChange');
}
const itemDataName = item['dataName'] || (typeof item['label'] === 'string' ? item['label'] : undefined);
if (itemDataName) {
domProps['data-name'] = itemDataName;
}
return renderItem({
index,
idProperty,
onItemClick: getItemHandler('onClick'),
domProps,
className: itemClassName,
style: itemStyle,
item,
columns: columns,
});
});
content = (React.createElement("table", { className: `${baseClassName}__content` },
React.createElement("tbody", null, content)));
}
const dropdownButtonClassName = props.className;
const className = join(props.className, baseClassName);
const positionerRef = useRef(null);
const { expanded, toggle, setExpanded, positionInfo } = useExpanded(props, positionerRef);
const { maxHeight: maxListHeight, maxWidth: maxListWidth } = positionInfo;
listStyle = {
minWidth: typeof maxListWidth === 'number' ? Math.min(listMinWidth, maxListWidth) : listMinWidth,
maxHeight: maxListHeight,
maxWidth: maxListWidth,
...listStyle,
};
let icon = expanded
? cloneElement(DROPDOWN_ICON, {
style: {
...DROPDOWN_ICON.props.style,
transform: 'rotate(180deg) translate3d(0px, -2px, 0px)',
},
})
: DROPDOWN_ICON;
const hasClearButton = onClear || showClearButton;
const clearButton = hasClearButton ? (React.createElement(SimpleButton, { disabled: domProps.disabled, as: "div", onClick: (event) => {
event.stopPropagation();
if (onClear) {
onClear();
}
buttonRef.current?.focus();
}, ml: 2, padding: 0, variant: 'text', icon: "close", ...clearButtonProps, style: {
...clearButtonProps?.style,
visibility: showClearButton ? 'visible' : 'hidden',
} })) : null;
icon = (React.createElement(React.Fragment, null,
spacer,
hasClearButton ? clearButton : null,
icon));
const buttonRef = useRef(null);
return (React.createElement(OverlayTrigger, { visible: expanded, targetOffset: listOffset, render: () => {
return (React.createElement("div", { "data-name": `${dropdownButtonClassName}`, style: listStyle, className: `${baseClassName}__list`, onMouseDownCapture: (e) => {
/**
* This stops popups register clicks inside the dropdown
* This is needed for column filter dropdows when redenred
* inside ag-grid column filter
*/
if (props.stopPropagationOnOverlay) {
e.stopPropagation();
}
} }, content));
}, ...overlayProps },
React.createElement(SimpleButton, { iconPosition: "end", ...(showToggleIcon && { icon, paddingRight: 0 }), ...domProps, ref: (btn) => {
buttonRef.current = btn;
if (!theRef) {
return;
}
if (typeof theRef === 'function') {
theRef(btn);
}
else {
theRef.current = btn;
}
}, style: domProps.style, className: className, onClick: (e) => {
if (domProps.onClick) {
domProps.onClick(e);
}
if (e.nativeEvent.preventCollapse && expanded) {
return;
}
toggle();
}, onKeyDown: (e) => {
if (domProps.onKeyDown) {
domProps.onKeyDown(e);
}
if (expanded && e.key === 'Escape') {
toggle();
}
}, onBlur: (e) => {
if (domProps.onBlur) {
domProps.onBlur(e);
}
setExpanded(false);
} },
React.createElement("div", { ref: positionerRef, tabIndex: -1, style: {
position: 'absolute',
height: '100%',
width: '100%',
zIndex: -1,
pointerEvents: 'none',
opacity: 0,
top: 0,
left: 0,
} }),
children)));
});
export default DropdownButton;