UNPKG

@intility/bifrost-react-select

Version:

React select component for Intility's design system, Bifrost.

292 lines (291 loc) 11.9 kB
/* eslint-disable @typescript-eslint/ban-ts-comment */ "use client"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { forwardRef, useState } from "react"; import ReactSelectDefaultExport, { components as originalComponents } from "react-select"; import AsyncReactSelect from "react-select/async"; import CreatableReactSelect from "react-select/creatable"; import AsyncCreatableReactSelect from "react-select/async-creatable"; import classNames from "classnames"; import Description from "@intility/bifrost-react/Description"; import Feedback from "@intility/bifrost-react/Feedback"; import Label from "@intility/bifrost-react/Label"; import useUniqueId from "@intility/bifrost-react/hooks/useUniqueId"; import useLocale from "@intility/bifrost-react/hooks/useLocale"; import DropdownIndicator from "./overrides/DropdownIndicator.internal.js"; import CustomMenuList from "./overrides/CustomMenuList.internal.js"; import ClearIndicator from "./overrides/ClearIndicator.internal.js"; import CustomOption from "./overrides/CustomOption.internal.js"; import LoadingIndicator from "./overrides/LoadingIndicator.internal.js"; import Menu, { SelectRefCtx } from "./overrides/Menu.internal.js"; const ReactSelect = ReactSelectDefaultExport.default ?? ReactSelectDefaultExport; export const selectStyles = { container: (provided)=>({ ...provided, ".bf-label-description + &, .bf-label + &": { marginTop: "var(--bfs4)" } }), control: (provided, state)=>({ ...provided, "&:hover": { borderColor: "var(--bfc-base-c-inverted)", // Change color of dropdown icon when hover on Select ".bf-select__dropdown-indicator": { color: "var(--bfc-base-c)" } }, ".bf-select-small &": { minHeight: "var(--rem32)" }, ".bf-select-alert &": { borderColor: state.isFocused ? "var(--bfc-base-c-inverted)" : state.isDisabled ? "transparent" : "var(--bfc-base-c-alert)" }, ".bf-select-alert &:hover": { borderColor: state.isFocused ? undefined : state.isDisabled ? "transparent" : "var(--bfc-alert-2)" }, ".bf-fieldgroup &": { borderRadius: 0 }, ".bf-fieldgroup > :first-of-type &": { borderTopLeftRadius: "var(--bf-radius-s)", borderBottomLeftRadius: "var(--bf-radius-s)" }, ".bf-fieldgroup > :last-child &": { borderTopRightRadius: "var(--bf-radius-s)", borderBottomRightRadius: "var(--bf-radius-s)" }, backgroundColor: state.isDisabled ? "var(--bfc-base)" : "var(--bfc-base-3)", borderWidth: 1, borderStyle: "solid", borderColor: state.isFocused ? "var(--bfc-base-c-inverted)" : state.isDisabled ? "var(--bfc-base-c-dimmed)" : "var(--bfc-base-c-wcag)", boxShadow: state.isFocused ? "inset 0 0 0 1px var(--bfc-base-c-inverted)" : "none", borderRadius: "var(--bf-radius-s)", minHeight: "var(--rem40)", cursor: "text" }), indicatorSeparator: ()=>({ display: "none" }), indicatorsContainer: (provided)=>({ ...provided, ".bf-select-small &": { paddingBlock: "0.2187rem" }, padding: "0.469rem 0", alignItems: "flex-start" }), clearIndicator: (provided)=>({ ...provided, "&:hover": { color: "var(--bfc-base-c)" }, color: "var(--bfc-base-c-2)", cursor: "pointer", padding: 4, margin: "1px 4px 0px 0px" }), dropdownIndicator: (provided, state)=>({ ...provided, ".bf-select-small &": { marginRight: 4 }, color: state.isDisabled ? "var(--bfc-base-c-disabled)" : state.isFocused ? "var(--bfc-base-c)" : "var(--bfc-base-c-2)", cursor: "pointer", padding: 4, marginRight: 8 }), input: (provided)=>({ ...provided, color: "var(--bfc-base-c)", fontFamily: "inherit", fontSize: "var(--bf-font-size-l)", margin: 0, padding: 0 }), menu: (provided)=>({ ...provided, position: "static", margin: 0, backgroundColor: "transparent", boxShadow: "none", borderRadius: "none" }), menuList: (provided)=>({ ...provided, backgroundColor: "var(--bfc-base-3)", padding: 0, border: "1px solid var(--bfc-base-c-wcag)", borderRadius: "var(--bf-radius-s)" }), placeholder: (provided, state)=>({ ...provided, color: state.isDisabled ? "var(--bfc-base-c-disabled)" : "var(--bfc-base-c-2)", fontSize: "var(--bf-font-size-l)" }), valueContainer: (provided)=>({ ...provided, ".bf-select-small &": { padding: "0 8px" }, padding: "var(--rem2) 12px" }), singleValue: (provided, state)=>({ ...provided, color: state.selectProps.menuIsOpen ? "var(--bfc-base-c-2)" : state.isDisabled ? "var(--bfc-base-c-disabled)" : "var(--bfc-base-c)", fontSize: "var(--bf-font-size-l)" }), option: (provided, state)=>({ ...provided, display: "flex", justifyContent: !state.isMulti ? "space-between" : "normal", alignItems: "baseline", padding: "7px 12px", backgroundColor: state.isDisabled ? "var(--bfc-base-dimmed)" : state.isFocused ? "var(--bfc-base)" : "var(--bfc-base-3)", color: state.isDisabled ? "var(--bfc-base-c-2)" : "var(--bfc-base-c)", "& .bf-select-selected-icon": { color: "var(--bfc-base-c)", marginLeft: 4 }, "&:hover": { backgroundColor: state.isDisabled ? "var(--bfc-base-dimmed)" : "var(--bfc-base)", cursor: state.isDisabled ? "default" : "pointer" }, fontSize: "var(--bf-font-size-l)", fontWeight: state.isSelected ? 600 : 400, wordBreak: "break-word", whiteSpace: "normal" }), multiValue: (provided, state)=>({ ...provided, backgroundColor: "var(--bfc-base)", borderRadius: "var(--bf-radius-xs)", border: state.isDisabled ? "1px solid var(--bfc-base-c-disabled)" : "var(--bf-border)", opacity: state.isDisabled ? 0.5 : 1, maxWidth: "calc(100% - 10px)" }), multiValueLabel: (provided)=>({ ...provided, fontSize: "var(--bf-font-size-m)", padding: "1.5px 4px 1.5px 8px", color: "inherit" }), multiValueRemove: (provided, state)=>({ ...provided, color: "var(--bfc-base-c-2)", paddingLeft: 5, paddingRight: 5, background: state.isFocused ? "var(--bfc-theme-2)" : undefined, "&:hover": { color: "var(--bfc-base-c)", cursor: "pointer", background: "var(--bfc-base-2)" }, "&:active": { background: "var(--bfc-base-3)" }, svg: { marginTop: 1 } }), group: (provided)=>({ ...provided, padding: "6px 0", "&:first-of-type": { marginTop: 4 } }), groupHeading: (provided)=>({ ...provided, textTransform: "capitalize", color: "var(--bfc-base-c-2)", fontSize: "var(--bf-font-size-s)", marginBottom: 2 }) }; export const selectComponents = { ...originalComponents, DropdownIndicator, MenuList: CustomMenuList, // @ts-ignore Menu, ClearIndicator, Option: CustomOption, LoadingIndicator }; /** * Select HOC */ const SelectHOC = (Selector)=>{ // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-explicit-any, react/display-name const GeneratedSelect = /*#__PURE__*/ forwardRef(({ label, hideLabel = false, isDisabled = false, state, feedback, required = false, description, requiredNoLabel = false, optional = false, inputId, className, style, loading = false, components, small = false, ...props }, ref)=>{ const selectId = useUniqueId(inputId); const locale = useLocale(); const [controlElement, setControlElement] = useState(null); return /*#__PURE__*/ _jsx(SelectRefCtx.Provider, { value: controlElement, children: /*#__PURE__*/ _jsxs("div", { className: classNames(className, "bf-select-container", "bf-open-sans", { "bf-select-disabled": isDisabled, "bf-select-alert": !isDisabled && state === "alert", "bf-select-small": small }), style: style, "data-testid": "bf-select-container", children: [ !hideLabel && /*#__PURE__*/ _jsx(Label, { htmlFor: selectId, required: !isDisabled && required && !requiredNoLabel, optional: optional, disabled: isDisabled, children: label }), /*#__PURE__*/ _jsx(Description, { children: description }), /*#__PURE__*/ _jsx(Selector, { ref: (r)=>{ setControlElement(r?.controlRef ?? null); if (typeof ref === "function") { ref(r); } else if (ref != null) { ref.current = r; } }, inputId: selectId, placeholder: "", components: { ...selectComponents, ...components }, styles: selectStyles, isDisabled: isDisabled, classNamePrefix: "bf-select", required: !isDisabled && (required || requiredNoLabel), "aria-label": label, hideSelectedOptions: false, closeMenuOnSelect: props.isMulti ? false : true, isLoading: loading ?? props.isLoading, loadingMessage: ()=>locale.loading + "...", ...props }), /*#__PURE__*/ _jsx(Feedback, { children: feedback }) ] }) }); }); return GeneratedSelect; }; /** * Select component - dropdown list */ export const Select = SelectHOC(ReactSelect); Select.displayName = "Select"; const AsyncSelect = SelectHOC(AsyncReactSelect); AsyncSelect.displayName = "AsyncSelect"; const CreatableSelect = SelectHOC(CreatableReactSelect); CreatableSelect.displayName = "CreatableSelect"; const AsyncCreatableSelect = SelectHOC(AsyncCreatableReactSelect); AsyncCreatableSelect.displayName = "AsyncCreatableSelect"; export { AsyncSelect, CreatableSelect, AsyncCreatableSelect }; export default Select;