UNPKG

@navikt/ds-react

Version:

React components from the Norwegian Labour and Welfare Administration.

94 lines 4.3 kB
import React, { useCallback, useEffect, useMemo, useState } from "react"; import { createContext } from "../../../util/create-context.js"; import { usePrevious } from "../../../util/hooks/index.js"; import { useInputContext } from "../Input/Input.context.js"; import { isInList } from "../combobox-utils.js"; import { useComboboxCustomOptions } from "../customOptionsContext.js"; const [SelectedOptionsContextProvider, useSelectedOptionsContext] = createContext(); const SelectedOptionsProvider = ({ children, value, }) => { const { clearInput, focusInput, setHideCaret } = useInputContext(); const { customOptions, removeCustomOption, addCustomOption, setCustomOptions, } = useComboboxCustomOptions(); const { allowNewValues, isMultiSelect, selectedOptions: externalSelectedOptions, onToggleSelected, options, maxSelected, } = value; const [internalSelectedOptions, setSelectedOptions] = useState([]); const selectedOptions = useMemo(() => externalSelectedOptions !== null && externalSelectedOptions !== void 0 ? externalSelectedOptions : [...customOptions, ...internalSelectedOptions], [customOptions, externalSelectedOptions, internalSelectedOptions]); const addSelectedOption = useCallback((option) => { const isCustomOption = !isInList(option, options); if (isCustomOption) { allowNewValues && addCustomOption(option); !isMultiSelect && setSelectedOptions([]); } else if (isMultiSelect) { setSelectedOptions((oldSelectedOptions) => [ ...oldSelectedOptions, option, ]); } else { setSelectedOptions([option]); setCustomOptions([]); } onToggleSelected === null || onToggleSelected === void 0 ? void 0 : onToggleSelected(option.value, true, isCustomOption); }, [ addCustomOption, allowNewValues, isMultiSelect, onToggleSelected, options, setCustomOptions, ]); const removeSelectedOption = useCallback((option) => { const isCustomOption = isInList(option, customOptions); if (isCustomOption) { removeCustomOption(option); } else { setSelectedOptions((oldSelectedOptions) => oldSelectedOptions.filter((selectedOption) => selectedOption !== option)); } onToggleSelected === null || onToggleSelected === void 0 ? void 0 : onToggleSelected(option.value, false, isCustomOption); }, [customOptions, onToggleSelected, removeCustomOption]); const maxSelectedLimit = typeof maxSelected === "object" ? maxSelected.limit : maxSelected; const isLimitReached = !!maxSelectedLimit && selectedOptions.length >= maxSelectedLimit; const newHideCaret = isLimitReached || (!isMultiSelect && selectedOptions.length > 0); // biome-ignore lint/correctness/useExhaustiveDependencies: We explicitly want to run this effect when selectedOptions changes to match the view with the selected options. useEffect(() => { setHideCaret(newHideCaret); }, [newHideCaret, selectedOptions, setHideCaret]); const toggleOption = useCallback((option, event) => { if (isInList(option.value, selectedOptions)) { removeSelectedOption(option); } else if (isMultiSelect && isLimitReached) { return; } else { addSelectedOption(option); } clearInput(event); focusInput(); }, [ addSelectedOption, clearInput, focusInput, removeSelectedOption, selectedOptions, isLimitReached, isMultiSelect, ]); const prevSelectedOptions = usePrevious(selectedOptions); const selectedOptionsState = { addSelectedOption, isMultiSelect, removeSelectedOption, prevSelectedOptions, selectedOptions, setSelectedOptions, toggleOption, maxSelected: { limit: maxSelectedLimit, isLimitReached, }, }; return (React.createElement(SelectedOptionsContextProvider, Object.assign({}, selectedOptionsState), children)); }; export { SelectedOptionsProvider, useSelectedOptionsContext }; //# sourceMappingURL=selectedOptionsContext.js.map