@intility/bifrost-react-select
Version:
React select component for Intility's design system, Bifrost.
292 lines (291 loc) • 11.9 kB
JavaScript
/* 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;