UNPKG

@mskcc/carbon-react

Version:

Carbon react components for the MSKCC DSM

199 lines (194 loc) 5.34 kB
/** * MSKCC 2021, 2024 */ import { defineProperty as _defineProperty } from '../_virtual/_rollupPluginBabelHelpers.js'; import React__default, { useRef, useState, useCallback, useEffect } from 'react'; import PropTypes from 'prop-types'; import isEqual from 'lodash.isequal'; function callOnChangeHandler(_ref) { let { isControlled, isMounted, onChangeHandlerControlled, onChangeHandlerUncontrolled, selectedItems } = _ref; if (isControlled) { if (isMounted && onChangeHandlerControlled) { onChangeHandlerControlled({ selectedItems }); } } else { onChangeHandlerUncontrolled(selectedItems); } } function useSelection(_ref2) { let { disabled, onChange, initialSelectedItems = [], selectedItems: controlledItems } = _ref2; const isMounted = useRef(false); const savedOnChange = useRef(onChange); const [uncontrolledItems, setUncontrolledItems] = useState(initialSelectedItems); const isControlled = !!controlledItems; const selectedItems = isControlled ? controlledItems : uncontrolledItems; const onItemChange = useCallback(item => { if (disabled) { return; } let selectedIndex; selectedItems.forEach((selectedItem, index) => { if (isEqual(selectedItem, item)) { selectedIndex = index; } }); let newSelectedItems; if (selectedIndex === undefined) { newSelectedItems = selectedItems.concat(item); callOnChangeHandler({ isControlled, isMounted: isMounted.current, onChangeHandlerControlled: savedOnChange.current, onChangeHandlerUncontrolled: setUncontrolledItems, selectedItems: newSelectedItems }); return; } newSelectedItems = removeAtIndex(selectedItems, selectedIndex); callOnChangeHandler({ isControlled, isMounted: isMounted.current, onChangeHandlerControlled: savedOnChange.current, onChangeHandlerUncontrolled: setUncontrolledItems, selectedItems: newSelectedItems }); }, [disabled, isControlled, selectedItems]); const clearSelection = useCallback(() => { if (disabled) { return; } callOnChangeHandler({ isControlled, isMounted: isMounted.current, onChangeHandlerControlled: savedOnChange.current, onChangeHandlerUncontrolled: setUncontrolledItems, selectedItems: [] }); }, [disabled, isControlled]); useEffect(() => { savedOnChange.current = onChange; }, [onChange]); useEffect(() => { if (isMounted.current && savedOnChange.current && !isControlled) { savedOnChange.current({ selectedItems }); } }, [isControlled, selectedItems]); useEffect(() => { isMounted.current = true; return () => { isMounted.current = false; }; }, []); return { selectedItems, onItemChange, clearSelection }; } class Selection extends React__default.Component { constructor(props) { super(props); _defineProperty(this, "internalSetState", (stateToSet, callback) => this.setState(stateToSet, () => { if (callback) { callback(); } if (this.props.onChange) { this.props.onChange(this.state); } })); _defineProperty(this, "handleClearSelection", () => { if (this.props.disabled) { return; } this.internalSetState({ selectedItems: [] }); }); _defineProperty(this, "handleSelectItem", item => { this.internalSetState(state => ({ selectedItems: state.selectedItems.concat(item) })); }); _defineProperty(this, "handleRemoveItem", index => { this.internalSetState(state => ({ selectedItems: removeAtIndex(state.selectedItems, index) })); }); _defineProperty(this, "handleOnItemChange", item => { if (this.props.disabled) { return; } const { selectedItems } = this.state; let selectedIndex; selectedItems.forEach((selectedItem, index) => { if (isEqual(selectedItem, item)) { selectedIndex = index; } }); if (selectedIndex === undefined) { this.handleSelectItem(item); return; } this.handleRemoveItem(selectedIndex); }); this.state = { selectedItems: props.initialSelectedItems }; } render() { const { children, render } = this.props; const { selectedItems } = this.state; const renderProps = { selectedItems, onItemChange: this.handleOnItemChange, clearSelection: this.handleClearSelection }; if (render !== undefined) { return render(renderProps); } if (children !== undefined) { return children(renderProps); } return null; } } // Generic utility for safely removing an element at a given index from an // array. _defineProperty(Selection, "propTypes", { children: PropTypes.func, disabled: PropTypes.bool, initialSelectedItems: PropTypes.array.isRequired, onChange: PropTypes.func, render: PropTypes.func }); _defineProperty(Selection, "defaultProps", { initialSelectedItems: [] }); const removeAtIndex = (array, index) => { const result = array.slice(); result.splice(index, 1); return result; }; export { Selection as default, useSelection };