@adaptabletools/adaptable-cjs
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
193 lines (192 loc) • 10.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderSelectionSection = void 0;
exports.ValueSelector = ValueSelector;
const tslib_1 = require("tslib");
const React = tslib_1.__importStar(require("react"));
const react_1 = require("react");
const dnd_1 = require("../../../components/dnd");
const CheckBox_1 = require("../../../components/CheckBox");
const icons_1 = require("../../../components/icons");
const Radio_1 = tslib_1.__importDefault(require("../../../components/Radio"));
const AdaptableFormControlTextClear_1 = require("../Forms/AdaptableFormControlTextClear");
const ArrayExtensions_1 = tslib_1.__importDefault(require("../../../Utilities/Extensions/ArrayExtensions"));
const Flex_1 = require("../../../components/Flex");
const clsx_1 = tslib_1.__importDefault(require("clsx"));
function useValuesMap({ options, value, toIdentifier, selectedMap, }) {
const optionsMap = (0, react_1.useMemo)(() => {
if (selectedMap) {
return;
}
const map = new Map([]);
options.forEach((option) => {
map.set(toIdentifier(option), option);
});
return map;
}, [options, selectedMap]);
const result = (0, react_1.useMemo)(() => {
if (selectedMap) {
return selectedMap;
}
const map = new Map([]);
value.forEach((id) => {
map.set(id, optionsMap.get(id) ?? null);
});
return map;
}, [optionsMap, selectedMap, value]);
return { selectedMap: result, optionsMap };
}
const baseClassName = 'ab-ValueSelector';
function ValueSelector(props) {
const { options, value, filter, onChange, allowReorder = true, singleSelect, toLabel, toListLabel, toIdentifier, showSelectedOnlyLabel, showFilterInput, onShowSelectedOnlyChange, isOptionDisabled, disabled, } = props;
const [searchInputValue, setSearchInputValue] = React.useState('');
const preparedToLabel = toListLabel ?? toLabel;
const [selectedOnly, doSetSelectedOnly] = (0, react_1.useState)(false);
const setSelectedOnly = (0, react_1.useCallback)((selectedOnly) => {
doSetSelectedOnly(selectedOnly);
onShowSelectedOnlyChange?.(selectedOnly);
}, [onShowSelectedOnlyChange]);
const { selectedMap } = useValuesMap({
options,
toIdentifier,
value,
});
const notifyChange = (0, react_1.useCallback)(() => {
const newSelection = [...selectedMap.keys()];
if (!newSelection.length && selectedOnly) {
setSelectedOnly(false);
}
onChange(newSelection, new Map(selectedMap));
}, [onChange, selectedOnly, selectedMap]);
const renderOption = (option, index) => {
const identifier = toIdentifier(option);
const label = !allowReorder ? preparedToLabel(option) : null;
const reorderable = typeof allowReorder === 'function' ? allowReorder(option) : allowReorder;
const renderNode = (props, dragHandleProps) => {
return (React.createElement(Flex_1.Flex, { alignItems: "center", key: identifier ?? index, "data-index": index, "data-id": identifier, "data-name": "option", ...props, className: (0, clsx_1.default)(`twa:bg-primary twa:text-text-on-primary twa:rounded-standard twa:p-2`, {
'twa:mt-1': index,
'twa:mt-0': !index,
}, props.className, `${baseClassName}__option`) },
React.createElement(Flex_1.Flex, { flexDirection: "row", alignItems: "center", className: "twa:flex-1" },
reorderable ? (React.createElement(Flex_1.Box, { ...dragHandleProps, className: (0, clsx_1.default)('twa:mr-3', dragHandleProps?.className) },
React.createElement(icons_1.Icon, { name: "drag", style: { cursor: 'grab' } }))) : null,
singleSelect ? (React.createElement(Radio_1.default, { checked: selectedMap.has(identifier), "data-name": identifier, onChange: (checked) => {
if (checked) {
selectedMap.clear();
selectedMap.set(identifier, option);
}
else {
selectedMap.delete(identifier);
}
notifyChange();
} }, label)) : (React.createElement(CheckBox_1.CheckBox, { "data-name": identifier, disabled: disabled || (isOptionDisabled ? isOptionDisabled(option) : false), onChange: (checked) => {
if (checked) {
selectedMap.set(identifier, option);
}
else {
selectedMap.delete(identifier);
}
notifyChange();
}, checked: selectedMap.has(identifier) }, label)),
React.createElement(Flex_1.Box, { className: "twa:ml-2 twa:flex-1" }, allowReorder ? preparedToLabel(option) : null))));
};
return (React.createElement(dnd_1.Draggable, { key: identifier, index: index, draggableId: `${identifier}`, isDragDisabled: !reorderable }, (draggableProvided) => {
return renderNode({
ref: draggableProvided.innerRef,
...draggableProvided.draggableProps,
style: draggableProvided.draggableProps.style,
}, draggableProvided.dragHandleProps);
}));
};
const showOnlySelectedCheckbox = (React.createElement(CheckBox_1.CheckBox, { disabled: !value.length, checked: selectedOnly, onChange: setSelectedOnly }, showSelectedOnlyLabel ?? 'Show Selected Only'));
const selectionSectionProps = {
...props,
showOnlySelectedCheckbox,
onSelectAll: () => {
options.forEach((option) => {
selectedMap.set(toIdentifier(option), option);
});
notifyChange();
},
onClearOption: (id) => {
selectedMap.delete(id);
notifyChange();
},
onClear: () => {
selectedMap.clear();
notifyChange();
},
};
return (React.createElement(Flex_1.Flex, { style: props.style, className: (0, clsx_1.default)('twa:flex-1', baseClassName), flexDirection: "column" },
React.createElement(Flex_1.Flex, { className: "twa:mb-1" }, showFilterInput && filter ? (React.createElement(AdaptableFormControlTextClear_1.AdaptableFormControlTextClear, { value: searchInputValue, OnTextChange: setSearchInputValue, placeholder: "Type to search", className: "twa:flex-1 twa:border-0 twa:m-[3px]" })) : (React.createElement(Flex_1.Box, { className: "twa:flex-1" }))),
(0, exports.renderSelectionSection)(selectionSectionProps),
React.createElement(dnd_1.DragDropContext, { onDragEnd: (result) => {
const { source, destination } = result;
const selection = [];
const extraKeys = [];
for (let [key, value] of selectedMap) {
if (value != null) {
selection.push(key);
}
else {
// null/non-existent keys have to be stored separately
extraKeys.push(key);
}
}
const clone = new Map(selectedMap);
const newSelection = ArrayExtensions_1.default.reorderArray(selection, source.index, destination.index);
// and then pushed back in the new order, at the end
newSelection.push(...extraKeys);
selectedMap.clear();
newSelection.forEach((key) => {
selectedMap.set(key, clone.get(key));
});
notifyChange();
} },
React.createElement(Flex_1.Flex, { className: `${baseClassName}__body twa:flex-1 twa:overflow-auto`, flexDirection: "column" },
React.createElement(dnd_1.Droppable, { droppableId: "droppable" }, (droppableProvided) => {
return (React.createElement("div", { ref: droppableProvided.innerRef, ...droppableProvided.droppableProps },
options
.filter((option) => {
let result = true;
if (filter) {
result = filter(option, searchInputValue);
}
result =
result && (selectedOnly ? selectedMap.has(toIdentifier(option)) : true);
return result;
})
.map(renderOption),
droppableProvided.placeholder));
})))));
}
const renderSelectionSection = (props) => {
const { value, options, disabled, singleSelect, toLabel, toIdentifier, } = props;
const selectionBox = (React.createElement(Flex_1.Box, { className: "twa:flex twa:flex-col twa:gap-2 twa:py-2" },
React.createElement(Flex_1.Box, { className: (0, clsx_1.default)('twa:flex twa:flex-row', 'twa:border-b twa:border-primarydark/30 twa:rounded-standard') },
singleSelect ? (React.createElement(Flex_1.Box, { className: "twa:flex twa:flex-row twa:text-3 twa:font-normal" },
"(",
value.length,
" of ",
options.length,
" selected)")) : (React.createElement(CheckBox_1.CheckBox, { className: "twa:ml-0.5 twa:font-bold", checked: !value.length ? false : value.length === options.length ? true : null, onChange: (checked) => {
if (checked) {
props.onSelectAll();
}
else {
props.onClear();
}
} },
React.createElement(Flex_1.Box, { className: "twa:flex twa:flex-row twa:items-center twa:gap-3" },
"Select All",
React.createElement(Flex_1.Box, { className: "twa:text-2 twa:font-normal" },
"(",
value.length,
" of ",
options.length,
" selected)")))),
React.createElement("div", { className: "twa:flex-1" }),
React.createElement(Flex_1.Box, { className: "twa:mr-2 twa:text-2 twa:font-normal" }, props.showOnlySelectedCheckbox))));
return React.createElement(Flex_1.Box, { className: (0, clsx_1.default)(`${baseClassName}__header `) }, selectionBox);
};
exports.renderSelectionSection = renderSelectionSection;