@availity/select
Version:
Wrapper for react-select to work with formik
1,092 lines (1,084 loc) • 52.4 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/index.js
var index_exports = {};
__export(index_exports, {
AvCodeSelect: () => AvCodeSelect,
AvNavigationSelect: () => AvNavigationSelect,
AvOrganizationSelect: () => AvOrganizationSelect_default,
AvPayerSelect: () => AvPayerSelect_default,
AvPermissionSelect: () => AvPermissionSelect,
AvProviderSelect: () => AvProviderSelect,
AvRegionSelect: () => AvRegionSelect_default,
AvUserSelect: () => AvUserSelect,
ResourceSelect: () => ResourceSelect_default,
SelectField: () => SelectField_default,
default: () => Select_default,
selectStyles: () => selectStyles
});
module.exports = __toCommonJS(index_exports);
// src/Select.js
var import_react = __toESM(require("react"));
var import_prop_types = __toESM(require("prop-types"));
var import_classnames = __toESM(require("classnames"));
var import_formik = require("formik");
var import_react_select = __toESM(require("react-select"));
var import_creatable = __toESM(require("react-select/creatable"));
var import_react_select_async_paginate = require("react-select-async-paginate");
var import_get = __toESM(require("lodash/get"));
var import_has = __toESM(require("lodash/has"));
var import_isFunction = __toESM(require("lodash/isFunction"));
var import_isEqual = __toESM(require("lodash/isEqual"));
var import_jsx_runtime = require("react/jsx-runtime");
var { DownChevron, DropdownIndicator, Input, Option, MultiValueRemove } = import_react_select.components;
var CreatableAsyncPaginate = (0, import_react_select_async_paginate.withAsyncPaginate)(import_creatable.default);
var components = {
DropdownIndicator: (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DropdownIndicator, __spreadProps(__spreadValues({}, props), { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DownChevron, {}),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: "Toggle Select Options" })
] })),
ClearIndicator: () => null,
Input: (props) => {
const { "aria-required": required } = props.selectProps;
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, __spreadProps(__spreadValues({ "aria-controls": "" }, props), { "aria-required": required }));
},
Option: (props) => {
const innerProps = __spreadProps(__spreadValues({}, props.innerProps), {
role: "option",
"aria-selected": props.isSelected,
name: props.innerProps.id
});
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Option, __spreadProps(__spreadValues({}, props), { innerProps }));
},
MultiValueRemove: (props) => {
const innerProps = __spreadProps(__spreadValues({}, props.innerProps), {
"aria-hidden": false
});
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MultiValueRemove, __spreadProps(__spreadValues({}, props), { innerProps }));
}
};
var createOption = (label, labelKey = "label", valueKey = "value") => ({
[labelKey]: label,
[valueKey]: label.toLowerCase().replaceAll(/\W/g, "")
});
var areValueAndOptionValueEqual = (value, optionValue) => (0, import_isEqual.default)(value, optionValue);
var selectAllOption = {
label: "Select all",
value: "*"
};
var validateSelectAllOptions = (options) => {
const filtered = options.filter((option) => option.value === selectAllOption.value);
if (filtered.length > 0) {
console.warn(
`An option contains the value: ${selectAllOption.value}. This value is used by the Select All option.`
);
}
};
var wrapperStyle = { display: "flex" };
var selectStyles = (showError, styles) => ({
styles: __spreadProps(__spreadValues({}, styles), {
container: (provided) => __spreadProps(__spreadValues({}, provided), {
// firefox fix for grids https://github.com/JedWatson/react-select/issues/5170
display: "grid",
gridTemplateColumns: "minmax(0, 1fr)",
width: "100%"
}),
placeholder: (provided, state) => {
if (state.isDisabled) {
return __spreadProps(__spreadValues({}, provided), {
borderColor: "#ced4da",
color: "#495057"
});
}
const showErrors = showError && !state.focused;
return __spreadProps(__spreadValues({}, provided), {
color: showErrors ? "#3D3D3D" : "#666",
maxWidth: "99%"
});
},
valueContainer: (provided) => __spreadProps(__spreadValues({}, provided), {
width: "90%"
}),
singleValue: (provided) => __spreadProps(__spreadValues({}, provided), {
color: "#495057"
}),
control: (provided, state) => {
if (state.isDisabled) {
return __spreadProps(__spreadValues({}, provided), {
flexGrow: "1",
borderRadius: "0.25em",
borderColor: "inherit",
backgroundColor: "#e9ecef"
});
}
return __spreadProps(__spreadValues({}, provided), {
flexGrow: "1",
borderRadius: "0.25em",
backgroundColor: "white",
borderColor: showError ? "#dc3545" : "#555",
":hover": {
borderColor: showError ? "#dc3545" : "#555",
cursor: "text"
},
":focus-within": {
borderColor: showError ? "#dc3545" : "#2261b5",
boxShadow: showError ? "0 0 0 0.2rem rgba(220 53 69 / 25%)" : "0 0 0 0.2rem #2261b5"
},
zIndex: state.focused && "3"
});
},
menu: (provided) => __spreadProps(__spreadValues({}, provided), { borderRadius: ".25em" }),
multiValue: (provided) => __spreadProps(__spreadValues({}, provided), {
borderRadius: "0.25em",
width: "auto"
}),
input: (provided) => __spreadProps(__spreadValues({}, provided), {
maxWidth: "99%"
}),
dropdownIndicator: (provided, state) => {
if (state.isDisabled) {
return provided;
}
const showErrors = showError && !state.focused;
return __spreadProps(__spreadValues({}, provided), {
pointerEvents: "none",
color: showErrors ? "#dc3545" : "#555"
});
},
option: (provided) => __spreadValues({}, provided)
}),
theme: (theme) => __spreadProps(__spreadValues({}, theme), {
borderRadius: 0,
boxShadow: 0,
colors: __spreadProps(__spreadValues({}, theme.colors), {
primary25: "#b8d4fb",
primary: "#3262af"
})
})
});
var Select = (_a) => {
var _b = _a, {
name,
validate,
className,
options,
selectRef,
styles,
maxLength,
onChange: onChangeCallback,
autofill,
creatable,
allowSelectAll,
waitUntilFocused,
helpMessage,
feedback,
placeholder,
components: componentOverrides,
required,
clearButtonClassName,
clearButtonText = "clear",
clearButtonProps = {},
defaultToOnlyOption,
defaultToFirstOption
} = _b, attributes = __objRest(_b, [
"name",
"validate",
"className",
"options",
"selectRef",
"styles",
"maxLength",
"onChange",
"autofill",
"creatable",
"allowSelectAll",
"waitUntilFocused",
"helpMessage",
"feedback",
"placeholder",
"components",
"required",
"clearButtonClassName",
"clearButtonText",
"clearButtonProps",
"defaultToOnlyOption",
"defaultToFirstOption"
]);
const [_a2, ..._b2] = (0, import_formik.useField)({
name,
validate
}), _c = _a2, { onChange, value: fieldValue } = _c, field = __objRest(_c, ["onChange", "value"]), [{ touched, error: fieldError }] = _b2;
const { values, setFieldValue, initialValues } = (0, import_formik.useFormikContext)();
const [newOptions, setNewOptions] = (0, import_react.useState)([]);
const errorShown = touched && fieldError;
let _cacheUniq = attributes.cacheUniq;
if (!Array.isArray(_cacheUniq)) {
_cacheUniq = [_cacheUniq];
}
placeholder = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
placeholder || "Select...",
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "sr-only", children: [
errorShown || null,
" ",
helpMessage || null
] })
] });
const getOptionLabel = (option) => {
if (option.__isNew__) {
return option.label;
}
return option[(0, import_get.default)(attributes, "labelKey", "label")];
};
const getValueKey = (attrs = attributes) => (0, import_get.default)(attrs, "valueKey", "value");
const getOptionValue = (option) => attributes.raw && !attributes.valueKey ? option : (0, import_get.default)(option, getValueKey(attributes), option);
const prepValue = (value, digIfMulti = true) => {
if (attributes.isMulti && digIfMulti && Array.isArray(value)) {
return value.map((val) => prepValue(val));
}
if (attributes.raw || attributes.loadOptions && !attributes.valueKey) {
return value;
}
const valueKey = getValueKey();
return (0, import_get.default)(value, valueKey, value);
};
const findOptionFromValue = (value, options2) => {
var _a3;
options2 = options2 || ((_a3 = selectRef == null ? void 0 : selectRef.current) == null ? void 0 : _a3.commonProps.options);
if (Array.isArray(options2)) {
const flattened = [...options2, ...newOptions].reduce((prev, current) => {
if (current.type === "group") {
return prev.concat(current.options);
}
return prev.concat(current);
}, []);
return flattened.filter((o) => areValueAndOptionValueEqual(value, getOptionValue(o)))[0];
}
return null;
};
const getViewValue = () => {
if (attributes.raw || attributes.loadOptions && !attributes.labelKey && !attributes.getOptionLabel || !attributes.loadOptions && !options) {
return fieldValue;
}
if (attributes.isMulti && Array.isArray(fieldValue)) {
return fieldValue.map((value) => findOptionFromValue(value, options) || value);
}
return findOptionFromValue(fieldValue, options) || fieldValue;
};
let Tag = attributes.loadOptions ? import_react_select_async_paginate.AsyncPaginate : import_react_select.default;
if (creatable) {
Tag = attributes.loadOptions ? CreatableAsyncPaginate : import_creatable.default;
}
if (!attributes.inputId) {
attributes.inputId = name;
}
const onChangeHandler = (newValue) => __async(void 0, null, function* () {
if (newValue && newValue.length > 0 && newValue.at(-1).value === selectAllOption.value) {
newValue = options;
}
const newVal = prepValue(newValue);
const isOverMax = maxLength && attributes.isMulti && newValue && newValue.length > maxLength;
if (isOverMax) return;
const valuesToSet = { [name]: true };
yield setFieldValue(name, newVal);
const shouldAutofill = autofill && !attributes.isMulti && newValue && typeof newVal === "object";
if (shouldAutofill) {
let formValuesForAutofill = values;
if (typeof autofill === "object") {
formValuesForAutofill = Object.keys(autofill).reduce((accum, key) => {
if ((0, import_has.default)(values, key)) {
accum[key] = (0, import_get.default)(values, key);
}
return accum;
}, {});
}
Object.keys(formValuesForAutofill).filter((fieldName) => fieldName !== name).forEach((fieldName) => __async(void 0, null, function* () {
let rawValue = newValue;
if (!!newValue.label && !!newValue.value && typeof newValue.value === "object") {
rawValue = newValue.value;
}
let shouldAutofillField = false;
shouldAutofillField = typeof autofill === "object" ? autofill[fieldName] : (0, import_has.default)(rawValue, fieldName);
if (shouldAutofillField) {
let val;
if (typeof autofill === "object") {
if ((0, import_isFunction.default)(autofill[fieldName])) {
val = autofill[fieldName](rawValue);
} else if (typeof autofill[fieldName] === "string") {
val = (0, import_get.default)(rawValue, `${autofill[fieldName]}`, initialValues[fieldName]);
} else {
val = initialValues[fieldName];
}
} else {
val = (0, import_get.default)(rawValue, fieldName, initialValues[fieldName]);
}
valuesToSet[fieldName] = true;
yield setFieldValue(fieldName, val);
}
}));
}
if (onChangeCallback) {
onChangeCallback(newVal);
}
});
const handleCreate = (value) => {
const newOpt = createOption(value, (0, import_get.default)(attributes, "labelKey", "label"), (0, import_get.default)(attributes, "valueKey", "value"));
newOptions.push(newOpt);
setNewOptions([...newOptions]);
if (attributes.isMulti) {
onChangeHandler(Array.isArray(fieldValue) ? fieldValue.concat(newOpt) : [newOpt]);
} else {
onChangeHandler(newOpt);
}
};
let selectOptions;
if (!attributes.loadOptions) {
if (allowSelectAll && attributes.isMulti) {
if ([...options, ...newOptions].length > 0 && (values[name] === void 0 || values[name] === null || values[name].length < [...options, ...newOptions].length)) {
validateSelectAllOptions([...options, ...newOptions]);
selectOptions = [selectAllOption, ...options, ...newOptions];
} else {
selectOptions = [...options, ...newOptions];
}
} else {
selectOptions = [...options, ...newOptions];
}
if (!attributes.isMulti && !attributes.isClearable && (selectOptions == null ? void 0 : selectOptions.length) > 0 && getOptionValue(fieldValue) !== getOptionValue(selectOptions[0])) {
if (defaultToOnlyOption && (selectOptions == null ? void 0 : selectOptions.length) === 1) {
setFieldValue(name, getOptionValue(selectOptions[0]));
} else if (defaultToFirstOption) {
setFieldValue(name, getOptionValue(selectOptions[0]));
}
}
}
if (attributes.loadOptions && allowSelectAll) {
console.warn("allowSelectAll is ignored when loadOptions is defined.");
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: wrapperStyle, children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
Tag,
__spreadProps(__spreadValues(__spreadValues(__spreadProps(__spreadValues({}, field), {
onChange: onChangeHandler,
ref: attributes.loadOptions ? void 0 : selectRef,
selectRef: attributes.loadOptions ? selectRef : void 0,
name,
classNamePrefix: "av",
role: "listbox",
onCreateOption: handleCreate,
className: (0, import_classnames.default)(
className,
"av-select",
touched ? "is-touched" : "is-untouched",
fieldError ? "av-invalid" : "av-valid",
errorShown && "is-invalid"
),
getOptionLabel,
getOptionValue,
closeMenuOnSelect: !attributes.isMulti,
"aria-invalid": !!errorShown || void 0,
"aria-errormessage": feedback && fieldValue && errorShown ? `${name}-feedback`.toLowerCase() : "",
"aria-required": required,
placeholder,
components: __spreadValues(__spreadValues({}, components), componentOverrides),
options: selectOptions,
defaultOptions: waitUntilFocused ? [] : true,
cacheUniqs: _cacheUniq
}), selectStyles(!!errorShown, styles)), attributes), {
value: getViewValue()
})
),
attributes.isClearable || attributes.isMulti ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"button",
__spreadProps(__spreadValues({
type: "button",
className: clearButtonClassName,
"aria-label": `clear ${attributes["aria-label"] || name.replaceAll(/[\W_]+/g, " ").replaceAll(/[A-Z]/g, " $&") || ""}`,
onClick: () => onChangeHandler(attributes.isMulti ? [] : null),
disabled: !fieldValue || Array.isArray(fieldValue) && fieldValue.length === 0
}, clearButtonProps), {
children: clearButtonText
})
) : null
] });
};
Select.defaultTypes = {
waitUntilFocused: false
};
Select.defaultProps = {
clearButtonClassName: "btn btn-link link"
};
Select.propTypes = {
/** The name of the field. Will be the key of the selected option(s) that come through in the values of the onSubmit callback of the form. */
name: import_prop_types.default.string.isRequired,
validate: import_prop_types.default.func,
/** Array of options that populate the select menu. Grouped options are also supported, but must include the property type: 'group' */
options: import_prop_types.default.array,
loadOptions: import_prop_types.default.func,
/** If true, the entire object of the selected value is returned as the value instead of the value for the valueKey within the object. */
raw: import_prop_types.default.bool,
className: import_prop_types.default.string,
/** Ref passed to react-select-async-paginate component if in async mode. */
selectRef: import_prop_types.default.object,
/** refer to react-select docs for info on styles */
styles: import_prop_types.default.object,
/** The maximum number of options that can be selected ( when isMulti is true) */
maxLength: import_prop_types.default.number,
onChange: import_prop_types.default.func,
/** Allow new items to be created if not found. Default: false. */
creatable: import_prop_types.default.bool,
/** If true, when the value of the dropdown changes, if the isMulti prop is false and the new value of the dropdown is an object, all fields on the form corresponding to the new value are auto-filled. In order for a field to be auto-filled, the name property on the field must match the key inside the new value.
* For example, if the new value is { "payer": "Availity" }, in order for the payer input in the form to be auto-filled to "Availity", the name prop on the input must be "payer".
* If autofill is an object, when the value of the dropdown changes, if the isMulti prop is false and the new value of the dropdown is an object, all fields on the form corresponding to the keys in the autofill prop will be auto-filled.
* When autofill is an object, the values in the object can be a string or a function. When a string, the key in the autofill prop gets auto-filled to that path on the selected option. When a function, it gets called with the selected option, and the key in the autofill prop gets auto-filled to the return value of the function.
*/
autofill: import_prop_types.default.oneOfType([import_prop_types.default.bool, import_prop_types.default.object]),
/** Adds a Select all option ( when isMulti is true). Note: allowSelectAll is ignored when loadOptions is defined. */
allowSelectAll: import_prop_types.default.bool,
/** When true, the network request is not made until the dropdown has been focused. Defaults to false. */
waitUntilFocused: import_prop_types.default.bool,
/** Adds hidden help message to placeholder so it is read with aria-describedby (should match visible help message). */
helpMessage: import_prop_types.default.oneOfType([import_prop_types.default.string, import_prop_types.default.node]),
/** Will add default <Feedback /> id to aria-errormessage. */
feedback: import_prop_types.default.bool,
placeholder: import_prop_types.default.string,
components: import_prop_types.default.object,
/** Will add aria-required to input. */
required: import_prop_types.default.bool,
/** Class names to add to clear button (only available when isMulti or isClearable). Default: btn btn-link link */
clearButtonClassName: import_prop_types.default.string,
/** Text that should be displayed in the clear button (only available when isMulti or isClearable). Default: clear */
clearButtonText: import_prop_types.default.string,
/** Additional properties that should be set on the clear button (only available when isMulti or isClearable). */
clearButtonProps: import_prop_types.default.object,
/** Automatically select the option if it is the only one available. Ignored if loadOptions or isClearable/isMulti is used */
defaultToOnlyOption: import_prop_types.default.bool,
/** Automatically select the first option if there are any options. Ignored if loadOptions or isClearable/isMulti is used */
defaultToFirstOption: import_prop_types.default.bool
};
components.Option.propTypes = {
innerProps: import_prop_types.default.object,
isSelected: import_prop_types.default.bool
};
components.Input.propTypes = {
selectProps: import_prop_types.default.object
};
components.MultiValueRemove.propTypes = {
innerProps: import_prop_types.default.object
};
var Select_default = Select;
// src/SelectField.js
var import_react2 = __toESM(require("react"));
var import_prop_types2 = __toESM(require("prop-types"));
var import_classnames2 = __toESM(require("classnames"));
var import_reactstrap = require("reactstrap");
var import_form = require("@availity/form");
var import_jsx_runtime2 = require("react/jsx-runtime");
var SelectField = (_a) => {
var _b = _a, {
feedbackClass,
groupClass,
label,
labelClass,
labelHidden,
name,
helpId,
required,
helpMessage,
isHelpVideoType
} = _b, attributes = __objRest(_b, [
"feedbackClass",
"groupClass",
"label",
"labelClass",
"labelHidden",
"name",
"helpId",
"required",
"helpMessage",
"isHelpVideoType"
]);
(0, import_react2.useEffect)(() => {
if (attributes.id && attributes.id === name) {
console.warn(
"Warning: Using an 'id' equivalent to 'name' will result in an orphaned label and break 508 compliance."
);
}
}, [attributes.id, name]);
const thisLabel = label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
import_form.Label,
{
id: `${name}-label`,
for: name,
hidden: labelHidden,
className: labelClass,
required,
helpId,
isHelpVideoType,
children: label
}
) : null;
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_form.FormGroup, { className: groupClass, for: name, disabled: attributes.disabled, children: [
thisLabel,
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Select_default, __spreadValues({ name, feedback: true, helpMessage, required }, attributes)),
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_form.Feedback, { className: (0, import_classnames2.default)("d-block", feedbackClass), name }),
helpMessage ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_reactstrap.FormText, { id: `${name}-helpmessage`.toLowerCase(), children: helpMessage }) : null
] });
};
SelectField.propTypes = {
/** The name of the field and name of the HTML Input. Without this, no input will be rendered. Will be the key of the selected option(s) that come through in the values of the onSubmit callback of the form. */
name: import_prop_types2.default.string.isRequired,
/** Class names to pass to the Feedback. */
feedbackClass: import_prop_types2.default.string,
/** Class names to pass to the FormGroup. */
groupClass: import_prop_types2.default.string,
/** Help topic id, adds <FieldHelpIcon/> next to the label (should not be within label for accessibility). */
helpId: import_prop_types2.default.string,
/** Adds help message below input. */
helpMessage: import_prop_types2.default.oneOfType([import_prop_types2.default.string, import_prop_types2.default.node]),
/** The label to render above the Select input. */
label: import_prop_types2.default.node,
/** Class names to pass to the Label. */
labelClass: import_prop_types2.default.string,
/** Whether the label should be hidden. */
labelHidden: import_prop_types2.default.bool,
/** Will add <RequiredAsterisk /> to label. */
required: import_prop_types2.default.bool,
/** Allows the type of `<FieldHelpIcon/>` to be changed between help-icon and video-help */
isHelpVideoType: import_prop_types2.default.bool
};
var SelectField_default = SelectField;
// src/ResourceSelect.js
var import_react3 = __toESM(require("react"));
var import_prop_types3 = __toESM(require("prop-types"));
var import_qs = __toESM(require("qs"));
var import_get2 = __toESM(require("lodash/get"));
var import_formik2 = require("formik");
var import_jsx_runtime3 = require("react/jsx-runtime");
var ResourceSelect = (_a) => {
var _b = _a, {
name,
method,
delay,
debounceTimeout = delay,
itemsPerPage,
watchParams,
cacheUniq,
additional,
resource,
onPageChange,
hasMore,
graphqlConfig,
minCharsToSearch,
onFocus,
waitUntilFocused,
defaultToOnlyOption,
defaultToFirstOption,
shouldSearch,
additionalPostGetArgs,
pageAll,
pageAllSearchBy,
searchTerm,
encodeSearchValue
} = _b, rest = __objRest(_b, [
"name",
"method",
"delay",
"debounceTimeout",
"itemsPerPage",
"watchParams",
"cacheUniq",
"additional",
"resource",
"onPageChange",
"hasMore",
"graphqlConfig",
"minCharsToSearch",
"onFocus",
"waitUntilFocused",
"defaultToOnlyOption",
"defaultToFirstOption",
"shouldSearch",
"additionalPostGetArgs",
"pageAll",
"pageAllSearchBy",
"searchTerm",
"encodeSearchValue"
]);
const { setFieldValue } = (0, import_formik2.useFormikContext)();
let _cacheUniq = cacheUniq;
const selectRef = (0, import_react3.useRef)();
const [previousOptions, setPreviousOptions] = (0, import_react3.useState)([]);
const [numTimesResourceCalled, setNumTimesResourceCalled] = (0, import_react3.useState)(0);
if (_cacheUniq === void 0 && watchParams) {
const params = __spreadValues(__spreadValues({
customerId: rest.customerId
}, rest.parameters), additionalPostGetArgs || "");
_cacheUniq = watchParams.map((watchParam) => params[watchParam]);
}
if (!Array.isArray(_cacheUniq)) {
_cacheUniq = [_cacheUniq];
}
if (pageAll) {
debounceTimeout = 0;
}
(0, import_react3.useEffect)(() => {
setNumTimesResourceCalled(0);
}, [_cacheUniq]);
const onFocusHandler = (...args) => {
if (onFocus) onFocus(...args);
};
const loadOptions = (...args) => __async(void 0, null, function* () {
const [inputValue, , additional2 = {}] = args;
let { page } = additional2;
const shouldReturnPreviousOptions = inputValue.length > 0 && minCharsToSearch !== void 0 && inputValue.length < minCharsToSearch;
if (shouldReturnPreviousOptions) {
return {
options: previousOptions,
hasMore: false,
additional: {
page,
limit: itemsPerPage
}
};
}
let data;
let params;
if (graphqlConfig) {
data = {
variables: {
perPage: itemsPerPage,
filters: {
[searchTerm]: encodeSearchValue ? encodeURIComponent(inputValue) : inputValue
}
}
};
if (args.length !== 3) {
data = typeof rest.parameters === "function" ? rest.parameters(data) : __spreadValues(__spreadValues({}, data), rest.parameters);
}
if (graphqlConfig.query) {
data.query = graphqlConfig.query;
}
} else {
params = {
[searchTerm]: encodeSearchValue ? encodeURIComponent(inputValue) : inputValue,
limit: itemsPerPage,
customerId: rest.customerId
};
if (args.length !== 3) {
params = typeof rest.parameters === "function" ? rest.parameters(params) : __spreadValues(__spreadValues({}, params), rest.parameters);
}
}
if (args.length === 3) {
if (graphqlConfig) {
data.variables.page = page;
if (typeof rest.parameters === "function") {
data = rest.parameters(data);
}
} else {
params.offset = (page - 1) * itemsPerPage;
params = typeof rest.parameters === "function" ? rest.parameters(params) : __spreadValues(__spreadValues({}, params), rest.parameters);
}
} else {
page = 1;
}
let requiredSatisfied = !rest.requiredParams || rest.requiredParams.length === 0;
if (!requiredSatisfied) {
requiredSatisfied = graphqlConfig ? rest.requiredParams.every((param) => (0, import_get2.default)(data, `variables.filters.${param}`)) : rest.requiredParams.every((param) => params[param]);
}
let _shouldSearch = shouldSearch;
if (typeof shouldSearch === "function") {
_shouldSearch = shouldSearch(...args);
}
if (rest.isDisabled || !requiredSatisfied || !_shouldSearch) {
return {
options: [],
hasMore: false
};
}
if (onPageChange) onPageChange(inputValue, page);
if (pageAll && !hasMore && inputValue.length > 0) {
if (pageAllSearchBy && typeof pageAllSearchBy === "function") {
const options = yield pageAllSearchBy(previousOptions, inputValue);
return { options, hasMore: false };
}
return {
options: previousOptions.filter(
(option) => option[rest.labelKey || rest.label].toLowerCase().indexOf(inputValue.toLowerCase()) >= 0
),
hasMore: false
};
}
let fetch;
if (pageAll && hasMore === void 0 && resource.all) {
fetch = () => resource.all(data || params);
} else if (graphqlConfig || method === "POST") {
fetch = () => resource.post(data || params, __spreadValues({
headers: {
"Content-Type": "application/json"
}
}, rest.requestConfig));
} else if (method === "GET") {
fetch = () => resource.query({ params });
} else {
fetch = () => resource.postGet(
import_qs.default.stringify(params, {
encode: false,
arrayFormat: "repeat",
indices: false,
allowDots: true
}),
__spreadValues({
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
}, rest.requestConfig),
additionalPostGetArgs
);
}
return fetch().then((resp) => __async(void 0, null, function* () {
if (!pageAll && !(resp || resp.data) || pageAll && !resp) {
throw new Error(`API returned an invalid response.`);
}
const getResult = rest.getResult || resource.getResult;
let items = [];
if (pageAll) {
items = resp.data || resp;
if (getResult)
items = typeof getResult === "function" ? yield getResult.call(resource, items) : items[getResult];
} else {
items = typeof getResult === "function" ? yield getResult.call(resource, resp.data) : resp.data[getResult];
}
if (hasMore === void 0) {
if (graphqlConfig) {
hasMore = (data2) => (0, import_get2.default)(data2.data, `${graphqlConfig.type}Pagination.pageInfo.hasNextPage`, false);
} else if (pageAll) {
hasMore = false;
} else {
hasMore = ({ totalCount, limit, offset }) => totalCount > offset + limit;
}
}
hasMore = typeof hasMore === "function" ? hasMore(resp.data) : hasMore;
if (!Array.isArray(items)) {
throw new TypeError(
`Expected data to be an array but got \`${typeof items}\`. Use the \`getData\` prop to specify how to get the data from the API response.`
);
}
setPreviousOptions(items);
if (!waitUntilFocused && numTimesResourceCalled === 0 && items.length > 0) {
if (defaultToOnlyOption && items.length === 1 || defaultToFirstOption) {
yield setFieldValue(name, items[0]);
}
}
setNumTimesResourceCalled(numTimesResourceCalled + 1);
return {
options: items,
hasMore,
additional: __spreadProps(__spreadValues({}, additional2), {
page: page + 1
})
};
})).catch((error) => {
if (rest.onError && typeof rest.onError === "function") {
rest.onError(error);
}
return { options: [], hasMore: false };
});
});
const Tag = rest.label ? SelectField_default : Select_default;
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
Tag,
__spreadProps(__spreadValues({
name,
selectRef,
loadOptions,
defaultOptions: waitUntilFocused ? [] : true,
pagination: true,
raw: true,
debounceTimeout,
cacheUniqs: _cacheUniq,
additional: __spreadValues({
page: 1
}, additional)
}, rest), {
onFocus: onFocusHandler
})
);
};
ResourceSelect.propTypes = {
/** The name of the field. Will be the key of the selected date that comes through in the values of the onSubmit callback. */
name: import_prop_types3.default.string.isRequired,
/** Availity API resource ([see @availity/api-axios](https://availity.github.io/sdk-js/api/getting-started/)). */
resource: import_prop_types3.default.shape({
postGet: import_prop_types3.default.func,
post: import_prop_types3.default.func,
getResult: import_prop_types3.default.oneOfType([import_prop_types3.default.string, import_prop_types3.default.func]),
all: import_prop_types3.default.func,
// Avoid any type of backwards compatibility issues with resources not have query defined. Allow function or any.
query: import_prop_types3.default.oneOfType([import_prop_types3.default.func, import_prop_types3.default.any])
}).isRequired,
/** Configuration object used in the query method on the resource. Useful for defining headers to be sent with the request. */
requestConfig: import_prop_types3.default.object,
/** Override method to use POST request on REST calls with graphqlConfig. When method = 'GET', on populating the options it will call the query function on the API Resource rather then default to a POST GET for cases when not using graphql. */
method: import_prop_types3.default.string,
/** When a function, the function is called with the response body from the API call and is expected to return an array. When a string, the string is expected to be a simple key used to get the value from the response. ("simple" means dot notation is not supported for grabbing values from nested objects. If your result is deeply nested, provide a function.) */
getResult: import_prop_types3.default.oneOfType([import_prop_types3.default.string, import_prop_types3.default.func]),
/** If true, ResourceSelect attempts to retrieve the next page of results. response.data from the axios response is passed as the only argument to hasMore when hasMore is a function. Defaults to: ({ totalCount, limit, offset }) => totalCount > offset + limit; for non-GraphQL apis. Defaults to (data) => data.data[${this.props.graphqlConfig.type}Pagination].pageInfo.hasNextPage for GraphQL apis. */
hasMore: import_prop_types3.default.oneOfType([import_prop_types3.default.bool, import_prop_types3.default.func]),
/** Set to debounceTimeout if debounceTimeout is not provided. ([see react-select-async-paginate](https://www.npmjs.com/package/react-select-async-paginate)) */
delay: import_prop_types3.default.number,
/** The amount of time (in milliseconds) to wait after the user has stopped typing before making the network request (debounced input). Default: 350 */
debounceTimeout: import_prop_types3.default.number,
label: import_prop_types3.default.node,
/** The value of the customer ID, which is sent in the parameters. Useful for restricting the loaded options to be related to the organization the user has in context. */
customerId: import_prop_types3.default.string,
/** Object used to create querystring parameters in the request. If function, will return new object with params for request. */
parameters: import_prop_types3.default.oneOfType([import_prop_types3.default.object, import_prop_types3.default.func]),
/** the number of items to fetch at a time and display per page when the user scrolls down. */
itemsPerPage: import_prop_types3.default.number,
/** A callback function to inform you that the user has scrolled to the bottom of the list and more items are loaded. The current input value and the page the user wants to go to are provided as arguments to the callback function. */
onPageChange: import_prop_types3.default.func,
isDisabled: import_prop_types3.default.bool,
/** If present, the network request is not made until all of the required parameters specified in the array have a truthy value. */
requiredParams: import_prop_types3.default.array,
/** Provide a list of properties to listen to from the parameters prop. If present, the options reset when any of the parameters specified in the array change value. This is useful for when a customerId changes and you need to load a new list of options for the user to choose from. This list will be used to derive cacheUniq when the cacheUniq prop is not provided. When using watchParams, the parameters prop must must be populated with values that are in the watchParams object. */
watchParams: import_prop_types3.default.array,
/** The minimum number of characters the user must input before ResourceSelect makes the network request. If the user has not inputted any characters, the network request will still be made. Useful for relieving pressure on the api the resource is calling. */
minCharsToSearch: import_prop_types3.default.number,
/** When this prop changes, all cached options are cleared. ([see react-select-async-paginate](https://www.npmjs.com/package/react-select-async-paginate)) */
// eslint-disable-next-line react/forbid-prop-types
cacheUniq: import_prop_types3.default.any,
/** Additional properties to pass to AsyncPaginate ([see react-select-async-paginate](https://www.npmjs.com/package/react-select-async-paginate)) */
additional: import_prop_types3.default.object,
/** Object containing type (String) and query (String) properties. type is the type of asset returned. query is the GraphQL query to use in the request. */
graphqlConfig: import_prop_types3.default.shape({
type: import_prop_types3.default.string,
query: import_prop_types3.default.string
}),
onFocus: import_prop_types3.default.func,
/** When true, the network request is not made until the dropdown has been focused. */
waitUntilFocused: import_prop_types3.default.bool,
/** When true, if the resource only returns one result the first time it is called, the value is defaulted to the single result. Note: if waitUntilFocused is true, this prop is ignored. */
defaultToOnlyOption: import_prop_types3.default.bool,
/** When true, if the resource returns at least one result the first time it is called, the value is defaulted to the first result. Note: if waitUntilFocused is true, this prop is ignored. */
defaultToFirstOption: import_prop_types3.default.bool,
/** When false or a function that returns false, the network request won't be made. Defaults to true. */
shouldSearch: import_prop_types3.default.oneOfType([import_prop_types3.default.bool, import_prop_types3.default.func]),
/** This object can be used to pass additional arguments to a resource's postGet call. These additional arguments are separate from the parameters that are supported by an API and may be used for filtering or other methods called inside a resource's postGet method. */
additionalPostGetArgs: import_prop_types3.default.object,
/** When true, resource.all() is called to fetch all the results, and search strings will filter by the label values instead of making another network call. DebounceTimeout is set to zero in this case. This should only be used for resources with a consistently small result set and no api search params */
pageAll: import_prop_types3.default.bool,
/** A method to specify what to filter the results by when pageAll is true. The list of options and search string is passed in, and an array of similar options is expected to be returned. */
pageAllSearchBy: import_prop_types3.default.func,
/** Function that is called when the api call returned an error. The error is returned in the callback */
onError: import_prop_types3.default.func,
/** If present, this will serve as the argument name for the typed search value when sending the request to the API. This defaults to q. */
searchTerm: import_prop_types3.default.string,
encodeSearchValue: import_prop_types3.default.bool
};
ResourceSelect.defaultProps = {
delay: 350,
itemsPerPage: 50,
waitUntilFocused: false,
defaultToOnlyOption: false,
defaultToFirstOption: false,
shouldSearch: true,
pageAll: false,
searchTerm: "q",
encodeSearchValue: true
};
var ucFirst = (str) => str && str.charAt(0).toUpperCase() + str.slice(1);
ResourceSelect.create = (defaults) => {
const SpecificResourceSelect = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ResourceSelect, __spreadValues(__spreadValues({}, defaults), props));
SpecificResourceSelect.displayName = `${ucFirst(defaults.resource.defaultConfig.name)}Select`;
return SpecificResourceSelect;
};
var ResourceSelect_default = ResourceSelect;
// src/resources.js
var import_api_axios4 = require("@availity/api-axios");
// src/AvOrganizationSelect.js
var import_react4 = __toESM(require("react"));
var import_prop_types4 = __toESM(require("prop-types"));
var import_api_axios = require("@availity/api-axios");
var import_jsx_runtime4 = require("react/jsx-runtime");
var OrganizationSelect = ResourceSelect_default.create({
resource: import_api_axios.avOrganizationsApi,
labelKey: "name",
valueKey: "id"
});
var AvOrganizationSelect = (_a) => {
var _b = _a, { name, resourceIds, permissionIds } = _b, props = __objRest(_b, ["name", "resourceIds", "permissionIds"]);
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
OrganizationSelect,
__spreadValues({
name,
additionalPostGetArgs: resourceIds || permissionIds ? { resourceIds, permissionIds } : void 0
}, props)
);
};
AvOrganizationSelect.propTypes = {
name: import_prop_types4.default.string.isRequired,
/**
* The organizations API from sdk-js accepts a resourceIds prop inside of additionalPostGetArgs that can be either a string or nested array of strings.
* When AvOrganizationSelect has a resourceIds prop, then the results of the postGet call to organizations will be filtered, containing only organizations that have the specified permissions and resources.
* This is useful when a payer space app is restricted to permission A and resource B, a user can pass A and B as permissionIds and resourceIds into AvOrganizationSelect and expect the dropdown to only contain authorized organizations for that user in that app, instead of all the organizations that user belongs to.
* AND logic is enforced by putting resources in an array together.
*/
resourceIds: import_prop_types4.default.oneOfType([
import_prop_types4.default.arrayOf(
import_prop_types4.default.oneOfType([
import_prop_types4.default.arrayOf(import_prop_types4.default.oneOfType([import_prop_types4.default.string, import_prop_types4.default.number])),
import_prop_types4.default.string,
import_prop_types4.default.number
])
),
import_prop_types4.default.string,
import_prop_types4.default.number
]),
/**
* The organizations API from sdk-js accepts a permissionIds prop inside of additionalPostGetArgs that can be either a string or nested array of strings.
* When used with resourceIds, the results of the postGet call to organizations will be filtered, containing only organizations that have the specified permissions and resources.
* If additionalPostGetArgs.permissionsIds exists, these values will be used over parameters.permissionId.
* This is useful when a payer space app is restricted to permission A and resource B, a user can pass A and B as permissionIds and resourceIds into AvOrganizationSelect and expect the dropdown to only contain authorized organizations for that user in that app, instead of all the organizations that user belongs to. AND logic is enforced by putting permissions in an array together.
*/
permissionIds: import_prop_types4.default.oneOfType([
import_prop_types4.default.arrayOf(
import_prop_types4.default.oneOfType([
import_prop_types4.default.arrayOf(import_prop_types4.default.oneOfType([import_prop_types4.default.string, import_prop_types4.default.number])),
import_prop_types4.default.string,
import_prop_types4.default.number
])
),
import_prop_types4.default.string,
import_prop_types4.default.number
])
};
var AvOrganizationSelect_default = AvOrganizationSelect;
// src/AvPayerSelect.js
var import_react5 = __toESM(require("react"));
var import_prop_types5 = __toESM(require("prop-types"));
var import_api_axios2 = __toESM(require("@availity/api-axios"));
var import_jsx_runtime5 = require("react/jsx-runtime");
var extendedPayersApi = new import_api_axios2.default({ path: "/api/internal", name: "extended-payers" });
extendedPayersApi.all = (parameters) => __async(void 0, null, function* () {
return extendedPayersApi.query({
params: { state: parameters.region, transactionType: parameters.tranTypeCode },
headers: { "X-Availity-Customer-ID": parameters.customerId }
});
});
var AvPayerSelect = (_a) => {
var _b = _a, { name, customerId } = _b, props = __objRest(_b, ["name", "customerId"]);
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
ResourceSelect_default,
__spreadValues({
name,
labelKey: "payerName",
valueKey: "payerId",
resource: extendedPayersApi,
pageAll: true,
customerId,
requiredParams: ["region", "tranTypeCode"],
watchParams: ["region", "tranTypeCode"]
}, props)
);
};
AvPayerSelect.propTypes = {
/**
* The extended-payers API from aries requires a customerId prop that must be a string.
* The AvPayerSelect will use the customerId prop in the request header, X-Availity-Customer-Id, of the all call to extended-payers.
* This is necessary for the AvPayerSelect select to only contain payers that are accesible and related to the organization specified, and not all the organizations that the user belongs.
*/
customerId: import_prop_types5.default.string.isRequired,
name: import_prop_types5.default.string.isRequired
};
var AvPayerSelect_default = AvPayerSelect;
// src/AvRegionSelect.js
var import_react6 = __toESM(require("react"));
var import_prop_types6 = __toESM(require("prop-types"));
var import_formik3 = require("formik");
var import_api_axios3 = require("@availity/api-axios");
var import_jsx_runtime6 = require("react/jsx-runtime");
var RegionSelect = ResourceSelect_default.create({
resource: import_api_axios3.avRegionsApi,
labelKey: "value",
valueKey: "id"
});
var searchBy = (prevOptions, inputValue) => prevOptions.filter(
(option) => option.value.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0 || option.id.toLowerCase().indexOf(inputValue.toLowerCase()) >= 0
);
var AvRegionSelect = (_a) => {
var _b = _a, { defaultToCurrentRegion, name } = _b, props = __objRest(_b, ["defaultToCurrentRegion", "name"]);
const { setFieldValue } = (0, import_formik3.useFor