UNPKG

@carbon/react

Version:

React components for the Carbon Design System

114 lines (112 loc) 4.08 kB
/** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ const require_runtime = require("../_virtual/_rolldown/runtime.js"); let react = require("react"); react = require_runtime.__toESM(react); require("react/jsx-runtime"); let react_fast_compare = require("react-fast-compare"); react_fast_compare = require_runtime.__toESM(react_fast_compare); //#region src/internal/Selection.tsx /** * Copyright IBM Corp. 2016, 2025 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ const callOnChangeHandler = ({ isControlled, isMounted, onChangeHandlerControlled, onChangeHandlerUncontrolled, selectedItems }) => { if (isControlled) { if (isMounted && onChangeHandlerControlled) setTimeout(() => { onChangeHandlerControlled({ selectedItems }); }, 0); } else onChangeHandlerUncontrolled(selectedItems); }; const useSelection = ({ disabled, onChange, initialSelectedItems = [], selectedItems: controlledItems, selectAll = false, filteredItems = [] }) => { const isMounted = (0, react.useRef)(false); const savedOnChange = (0, react.useRef)(onChange); const [uncontrolledItems, setUncontrolledItems] = (0, react.useState)(initialSelectedItems); const isControlled = !!controlledItems; const selectedItems = isControlled ? controlledItems : uncontrolledItems; const onItemChange = (0, react.useCallback)((item) => { if (disabled) return; const allSelectableItems = filteredItems.filter((item) => !item?.disabled && !item?.isSelectAll); const disabledItemCount = filteredItems.filter((item) => item?.disabled).length; let newSelectedItems; if (item?.isSelectAll && selectedItems.length > 0) newSelectedItems = []; else if (item?.isSelectAll && selectedItems.length === 0) newSelectedItems = allSelectableItems; else { const selectedIndex = selectedItems.findLastIndex((selectedItem) => (0, react_fast_compare.default)(selectedItem, item)); if (selectedIndex === -1) { newSelectedItems = selectedItems.concat(item); if (selectAll && filteredItems.length - 1 === newSelectedItems.length + disabledItemCount) newSelectedItems = allSelectableItems; } else { newSelectedItems = removeAtIndex(selectedItems, selectedIndex); newSelectedItems = newSelectedItems.filter((item) => !item?.isSelectAll); } } callOnChangeHandler({ isControlled, isMounted: isMounted.current, onChangeHandlerControlled: savedOnChange.current, onChangeHandlerUncontrolled: setUncontrolledItems, selectedItems: newSelectedItems }); }, [ disabled, selectedItems, filteredItems, selectAll, isControlled ]); const clearSelection = (0, react.useCallback)(() => { if (disabled) return; callOnChangeHandler({ isControlled, isMounted: isMounted.current, onChangeHandlerControlled: savedOnChange.current, onChangeHandlerUncontrolled: setUncontrolledItems, selectedItems: [] }); }, [disabled, isControlled]); const toggleAll = (0, react.useCallback)((items) => { callOnChangeHandler({ isControlled, isMounted: isMounted.current, onChangeHandlerControlled: savedOnChange.current, onChangeHandlerUncontrolled: setUncontrolledItems, selectedItems: items }); }, [isControlled]); (0, react.useEffect)(() => { savedOnChange.current = onChange; }, [onChange]); (0, react.useEffect)(() => { if (isMounted.current && savedOnChange.current && !isControlled) savedOnChange.current({ selectedItems }); }, [isControlled, selectedItems]); (0, react.useEffect)(() => { isMounted.current = true; return () => { isMounted.current = false; }; }, []); return { clearSelection, onItemChange, toggleAll, selectedItems }; }; /** * Generic utility for safely removing an element at a given index from an * array. */ const removeAtIndex = (array, index) => { const result = array.slice(); result.splice(index, 1); return result; }; //#endregion exports.useSelection = useSelection;