UNPKG

@availity/select

Version:
1,124 lines (1,115 loc) 47 kB
var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropSymbols = Object.getOwnPropertySymbols; 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 __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/Select.js import React, { useState } from "react"; import PropTypes from "prop-types"; import classNames from "classnames"; import { useField, useFormikContext } from "formik"; import RSelect, { components as reactSelectComponents } from "react-select"; import Creatable from "react-select/creatable"; import { AsyncPaginate as Async, withAsyncPaginate } from "react-select-async-paginate"; import get from "lodash/get"; import has from "lodash/has"; import isFunction from "lodash/isFunction"; import isEqual from "lodash/isEqual"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var { DownChevron, DropdownIndicator, Input, Option, MultiValueRemove } = reactSelectComponents; var CreatableAsyncPaginate = withAsyncPaginate(Creatable); var components = { DropdownIndicator: (props) => /* @__PURE__ */ jsxs(DropdownIndicator, __spreadProps(__spreadValues({}, props), { children: [ /* @__PURE__ */ jsx(DownChevron, {}), /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Toggle Select Options" }) ] })), ClearIndicator: () => null, Input: (props) => { const { "aria-required": required } = props.selectProps; return /* @__PURE__ */ 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__ */ jsx(Option, __spreadProps(__spreadValues({}, props), { innerProps })); }, MultiValueRemove: (props) => { const innerProps = __spreadProps(__spreadValues({}, props.innerProps), { "aria-hidden": false }); return /* @__PURE__ */ 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) => isEqual(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] = useField({ name, validate }), _c = _a2, { onChange, value: fieldValue } = _c, field = __objRest(_c, ["onChange", "value"]), [{ touched, error: fieldError }] = _b2; const { values, setFieldValue, initialValues } = useFormikContext(); const [newOptions, setNewOptions] = useState([]); const errorShown = touched && fieldError; let _cacheUniq = attributes.cacheUniq; if (!Array.isArray(_cacheUniq)) { _cacheUniq = [_cacheUniq]; } placeholder = /* @__PURE__ */ jsxs(Fragment, { children: [ placeholder || "Select...", /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [ errorShown || null, " ", helpMessage || null ] }) ] }); const getOptionLabel = (option) => { if (option.__isNew__) { return option.label; } return option[get(attributes, "labelKey", "label")]; }; const getValueKey = (attrs = attributes) => get(attrs, "valueKey", "value"); const getOptionValue = (option) => attributes.raw && !attributes.valueKey ? option : get(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 get(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 ? Async : RSelect; if (creatable) { Tag = attributes.loadOptions ? CreatableAsyncPaginate : Creatable; } 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 (has(values, key)) { accum[key] = get(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] : has(rawValue, fieldName); if (shouldAutofillField) { let val; if (typeof autofill === "object") { if (isFunction(autofill[fieldName])) { val = autofill[fieldName](rawValue); } else if (typeof autofill[fieldName] === "string") { val = get(rawValue, `${autofill[fieldName]}`, initialValues[fieldName]); } else { val = initialValues[fieldName]; } } else { val = get(rawValue, fieldName, initialValues[fieldName]); } valuesToSet[fieldName] = true; yield setFieldValue(fieldName, val); } })); } if (onChangeCallback) { onChangeCallback(newVal); } }); const handleCreate = (value) => { const newOpt = createOption(value, get(attributes, "labelKey", "label"), get(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__ */ jsxs("div", { style: wrapperStyle, children: [ /* @__PURE__ */ 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: classNames( 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__ */ 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: PropTypes.string.isRequired, validate: PropTypes.func, /** Array of options that populate the select menu. Grouped options are also supported, but must include the property type: 'group' */ options: PropTypes.array, loadOptions: PropTypes.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: PropTypes.bool, className: PropTypes.string, /** Ref passed to react-select-async-paginate component if in async mode. */ selectRef: PropTypes.object, /** refer to react-select docs for info on styles */ styles: PropTypes.object, /** The maximum number of options that can be selected ( when isMulti is true) */ maxLength: PropTypes.number, onChange: PropTypes.func, /** Allow new items to be created if not found. Default: false. */ creatable: PropTypes.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: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]), /** Adds a Select all option ( when isMulti is true). Note: allowSelectAll is ignored when loadOptions is defined. */ allowSelectAll: PropTypes.bool, /** When true, the network request is not made until the dropdown has been focused. Defaults to false. */ waitUntilFocused: PropTypes.bool, /** Adds hidden help message to placeholder so it is read with aria-describedby (should match visible help message). */ helpMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), /** Will add default <Feedback /> id to aria-errormessage. */ feedback: PropTypes.bool, placeholder: PropTypes.string, components: PropTypes.object, /** Will add aria-required to input. */ required: PropTypes.bool, /** Class names to add to clear button (only available when isMulti or isClearable). Default: btn btn-link link */ clearButtonClassName: PropTypes.string, /** Text that should be displayed in the clear button (only available when isMulti or isClearable). Default: clear */ clearButtonText: PropTypes.string, /** Additional properties that should be set on the clear button (only available when isMulti or isClearable). */ clearButtonProps: PropTypes.object, /** Automatically select the option if it is the only one available. Ignored if loadOptions or isClearable/isMulti is used */ defaultToOnlyOption: PropTypes.bool, /** Automatically select the first option if there are any options. Ignored if loadOptions or isClearable/isMulti is used */ defaultToFirstOption: PropTypes.bool }; components.Option.propTypes = { innerProps: PropTypes.object, isSelected: PropTypes.bool }; components.Input.propTypes = { selectProps: PropTypes.object }; components.MultiValueRemove.propTypes = { innerProps: PropTypes.object }; var Select_default = Select; // src/SelectField.js import React2, { useEffect } from "react"; import PropTypes2 from "prop-types"; import classNames2 from "classnames"; import { FormText } from "reactstrap"; import { FormGroup, Feedback, Label } from "@availity/form"; import { jsx as jsx2, jsxs as jsxs2 } from "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" ]); 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__ */ jsx2( Label, { id: `${name}-label`, for: name, hidden: labelHidden, className: labelClass, required, helpId, isHelpVideoType, children: label } ) : null; return /* @__PURE__ */ jsxs2(FormGroup, { className: groupClass, for: name, disabled: attributes.disabled, children: [ thisLabel, /* @__PURE__ */ jsx2(Select_default, __spreadValues({ name, feedback: true, helpMessage, required }, attributes)), /* @__PURE__ */ jsx2(Feedback, { className: classNames2("d-block", feedbackClass), name }), helpMessage ? /* @__PURE__ */ jsx2(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: PropTypes2.string.isRequired, /** Class names to pass to the Feedback. */ feedbackClass: PropTypes2.string, /** Class names to pass to the FormGroup. */ groupClass: PropTypes2.string, /** Help topic id, adds <FieldHelpIcon/> next to the label (should not be within label for accessibility). */ helpId: PropTypes2.string, /** Adds help message below input. */ helpMessage: PropTypes2.oneOfType([PropTypes2.string, PropTypes2.node]), /** The label to render above the Select input. */ label: PropTypes2.node, /** Class names to pass to the Label. */ labelClass: PropTypes2.string, /** Whether the label should be hidden. */ labelHidden: PropTypes2.bool, /** Will add <RequiredAsterisk /> to label. */ required: PropTypes2.bool, /** Allows the type of `<FieldHelpIcon/>` to be changed between help-icon and video-help */ isHelpVideoType: PropTypes2.bool }; var SelectField_default = SelectField; // src/ResourceSelect.js import React3, { useRef, useState as useState2, useEffect as useEffect2 } from "react"; import PropTypes3 from "prop-types"; import qs from "qs"; import get2 from "lodash/get"; import { useFormikContext as useFormikContext2 } from "formik"; import { jsx as jsx3 } from "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 } = useFormikContext2(); let _cacheUniq = cacheUniq; const selectRef = useRef(); const [previousOptions, setPreviousOptions] = useState2([]); const [numTimesResourceCalled, setNumTimesResourceCalled] = useState2(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; } useEffect2(() => { 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) => get2(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( qs.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) => get2(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__ */ jsx3( 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: PropTypes3.string.isRequired, /** Availity API resource ([see @availity/api-axios](https://availity.github.io/sdk-js/api/getting-started/)). */ resource: PropTypes3.shape({ postGet: PropTypes3.func, post: PropTypes3.func, getResult: PropTypes3.oneOfType([PropTypes3.string, PropTypes3.func]), all: PropTypes3.func, // Avoid any type of backwards compatibility issues with resources not have query defined. Allow function or any. query: PropTypes3.oneOfType([PropTypes3.func, PropTypes3.any]) }).isRequired, /** Configuration object used in the query method on the resource. Useful for defining headers to be sent with the request. */ requestConfig: PropTypes3.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: PropTypes3.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: PropTypes3.oneOfType([PropTypes3.string, PropTypes3.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: PropTypes3.oneOfType([PropTypes3.bool, PropTypes3.func]), /** Set to debounceTimeout if debounceTimeout is not provided. ([see react-select-async-paginate](https://www.npmjs.com/package/react-select-async-paginate)) */ delay: PropTypes3.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: PropTypes3.number, label: PropTypes3.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: PropTypes3.string, /** Object used to create querystring parameters in the request. If function, will return new object with params for request. */ parameters: PropTypes3.oneOfType([PropTypes3.object, PropTypes3.func]), /** the number of items to fetch at a time and display per page when the user scrolls down. */ itemsPerPage: PropTypes3.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: PropTypes3.func, isDisabled: PropTypes3.bool, /** If present, the network request is not made until all of the required parameters specified in the array have a truthy value. */ requiredParams: PropTypes3.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: PropTypes3.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: PropTypes3.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: PropTypes3.any, /** Additional properties to pass to AsyncPaginate ([see react-select-async-paginate](https://www.npmjs.com/package/react-select-async-paginate)) */ additional: PropTypes3.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: PropTypes3.shape({ type: PropTypes3.string, query: PropTypes3.string }), onFocus: PropTypes3.func, /** When true, the network request is not made until the dropdown has been focused. */ waitUntilFocused: PropTypes3.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: PropTypes3.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: PropTypes3.bool, /** When false or a function that returns false, the network request won't be made. Defaults to true. */ shouldSearch: PropTypes3.oneOfType([PropTypes3.bool, PropTypes3.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: PropTypes3.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: PropTypes3.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: PropTypes3.func, /** Function that is called when the api call returned an error. The error is returned in the callback */ onError: PropTypes3.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: PropTypes3.string, encodeSearchValue: PropTypes3.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__ */ jsx3(ResourceSelect, __spreadValues(__spreadValues({}, defaults), props)); SpecificResourceSelect.displayName = `${ucFirst(defaults.resource.defaultConfig.name)}Select`; return SpecificResourceSelect; }; var ResourceSelect_default = ResourceSelect; // src/resources.js import { avCodesApi, avNavigationApi, avPermissionsApi, avProvidersApi, avUserApi } from "@availity/api-axios"; // src/AvOrganizationSelect.js import React4 from "react"; import PropTypes4 from "prop-types"; import { avOrganizationsApi } from "@availity/api-axios"; import { jsx as jsx4 } from "react/jsx-runtime"; var OrganizationSelect = ResourceSelect_default.create({ resource: avOrganizationsApi, labelKey: "name", valueKey: "id" }); var AvOrganizationSelect = (_a) => { var _b = _a, { name, resourceIds, permissionIds } = _b, props = __objRest(_b, ["name", "resourceIds", "permissionIds"]); return /* @__PURE__ */ jsx4( OrganizationSelect, __spreadValues({ name, additionalPostGetArgs: resourceIds || permissionIds ? { resourceIds, permissionIds } : void 0 }, props) ); }; AvOrganizationSelect.propTypes = { name: PropTypes4.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: PropTypes4.oneOfType([ PropTypes4.arrayOf( PropTypes4.oneOfType([ PropTypes4.arrayOf(PropTypes4.oneOfType([PropTypes4.string, PropTypes4.number])), PropTypes4.string, PropTypes4.number ]) ), PropTypes4.string, PropTypes4.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: PropTypes4.oneOfType([ PropTypes4.arrayOf( PropTypes4.oneOfType([ PropTypes4.arrayOf(PropTypes4.oneOfType([PropTypes4.string, PropTypes4.number])), PropTypes4.string, PropTypes4.number ]) ), PropTypes4.string, PropTypes4.number ]) }; var AvOrganizationSelect_default = AvOrganizationSelect; // src/AvPayerSelect.js import React5 from "react"; import PropTypes5 from "prop-types"; import AvApi from "@availity/api-axios"; import { jsx as jsx5 } from "react/jsx-runtime"; var extendedPayersApi = new AvApi({ 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__ */ jsx5( 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: PropTypes5.string.isRequired, name: PropTypes5.string.isRequired }; var AvPayerSelect_default = AvPayerSelect; // src/AvRegionSelect.js import React6, { useEffect as useEffect3, useCallback } from "react"; import PropTypes6 from "prop-types"; import { useFormikContext as useFormikContext3 } from "formik"; import { avRegionsApi } from "@availity/api-axios"; import { jsx as jsx6 } from "react/jsx-runtime"; var RegionSelect = ResourceSelect_default.create({ resource: 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 } = useFormikContext3(); const defaultRegion = useCallback(() => __async(void 0, null, function* () { if (defaultToCurrentRegion) { try { const response = yield avRegionsApi.getCurrentRegion(); const value = response.data.regions[0]; setFieldValue(name, value); } catch (e) { console.warn("AvRegionSelect failed to load the current region"); } } }), [defaultToCurrentRegion, setFieldValue, name]); useEffect3(() => { defaultRegion(); }, [defaultRegion]); return /* @__PURE__ */ jsx6( RegionSelect, __spreadValues({ name, pageAll: true, pageAllSearchBy: searchBy, getResult: (regions) => regions.map((region) => ({ id: region.id, value: region.value })) }, props) ); }; AvRegionSelect.propTypes = { name: PropTypes6.string.isRequired, /** When true, the input will be defaulted to the user's currently selected region. Defaults to false */ defaultToCurrentRegion: PropTypes6.bool }; var AvRegionSelect_default = AvRegionSelect; // src/resources.js var AvCodeSelect = ResourceSelect_default.create({ resource: avCodesApi, valueKey: "code", getOptionLabel: (option) => `${option.code} - ${option.value}`, requiredParams: ["list"], watchParams: ["list"] }); var AvNavigationSelect = ResourceSelect_default.create({ resource: avNavigationApi, labelKey: "name", valueKey: "id" }); var AvPermissionSelect = ResourceSelect_default.create({ resource: avPermissionsApi, labelKey: "description", valueKey: "id" }); var AvProviderSelect = ResourceSelect_default.create({ resource: avProvidersApi, labelKey: "uiDisplayName", valueKey: "npi", requiredParams: ["customerId"], watchParams: ["customerId"] }); var AvUserSelect = ResourceSelect_default.create({ resource: avUserApi, getOptionLabel: (option) => `${option.firstName} ${option.lastName} (${option.id}) - ${option.userId}`, valueKey: "userId" }); export { AvCodeSelect, AvNavigationSelect, AvOrganizationSelect_default as AvOrganizationSelect, AvPayerSelect_default as AvPayerSelect, AvPermissionSelect, AvProviderSelect, AvRegionSelect_default as AvRegionSelect, AvUserSelect, ResourceSelect_default as ResourceSelect, SelectField_default as SelectField, Select_default as default, selectStyles };