@appbuckets/react-ui-smart-components
Version:
UI Extended Components that work with @appbuckets/react-client and @appbuckets/react-ui
292 lines (285 loc) • 9.35 kB
JavaScript
;
var _tslib = require('../_virtual/_tslib.js');
var React = require('react');
var arraySort = require('array-sort');
var reactAppClient = require('@appbuckets/react-app-client');
function _interopDefaultLegacy(e) {
return e && typeof e === 'object' && 'default' in e ? e : { default: e };
}
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(
n,
k,
d.get
? d
: {
enumerable: true,
get: function () {
return e[k];
},
}
);
}
});
}
n['default'] = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/ _interopNamespace(React);
var arraySort__default = /*#__PURE__*/ _interopDefaultLegacy(arraySort);
// eslint-disable-next-line max-len
function buildSelector(config) {
var /** Component Options */
displayName = config.displayName,
DefaultDefinedSelector = config.Selector,
defaultGetOptionValue = config.getOptionValue,
defaultGetOptionLabel = config.getOptionLabel,
/** Props Builder */
defaultPropsBuilder = config.defaultProps,
overridePropsBuilder = config.overrideProps,
/** Client Request Configuration */
defaultReloadDataOnMenuOpen = config.reloadDataOnMenuOpen,
request = config.request,
useHook = config.useHook,
/** Data Manipulation */
defaultDefinedFilter = config.filter,
defaultDefinedOptions = config.options,
defaultDefinedSort = config.sort,
/** Text Options */
defaultPlaceholder = config.placeholder,
defaultNoOptionsMessage = config.noOptionsMessage;
/** Define the SelectorWrapper */
var SelectorWrapper = function (props) {
var _a, _b, _c, _d;
var UserDefinedSelector = props.Selector,
restProps = _tslib.__rest(props, ['Selector']);
/* --------
* Build the Component Props
* using defined default props
* builder and override props
* -------- */
/** Compute Default Props */
var defaultProps =
typeof defaultPropsBuilder === 'function'
? defaultPropsBuilder(restProps)
: defaultPropsBuilder;
/** Compute override Props */
var overrideProps =
typeof overridePropsBuilder === 'function'
? overridePropsBuilder(
_tslib.__assign(_tslib.__assign({}, defaultProps), props)
)
: overridePropsBuilder;
/** Merge all props */
var componentProps = _tslib.__assign(
_tslib.__assign(_tslib.__assign({}, defaultProps), props),
overrideProps
);
/** Get Selector Props */
var userDefinedFilter = componentProps.filter,
userDefinedOptions = componentProps.options,
userDefinedRequestConfig = componentProps.requestConfig,
userDefinedReloadDataOnMenuOpen = componentProps.reloadDataOnMenuOpen,
userDefinedSort = componentProps.sort,
OverrideSelector = componentProps.Selector,
restSelectProps = _tslib.__rest(componentProps, [
'filter',
'options',
'requestConfig',
'reloadDataOnMenuOpen',
'sort',
'Selector',
]);
/* --------
* Rebuild Options using Sorter and Filter
* -------- */
var _e = _tslib.__read(
React__namespace.useState(function () {
return typeof useHook === 'function';
}),
1
),
hasHook = _e[0];
var hookResult = hasHook ? useHook() : undefined;
var getOptionsList = function (optionsList) {
/** Build Data */
var data =
typeof optionsList === 'function'
? optionsList(props, hookResult)
: optionsList;
/** Filter Data */
var filter =
defaultDefinedFilter !== null && defaultDefinedFilter !== void 0
? defaultDefinedFilter
: userDefinedFilter;
var filteredData =
typeof filter === 'function' ? data.filter(filter) : data;
/** Get Sorter */
var sort =
defaultDefinedSort !== null && defaultDefinedSort !== void 0
? defaultDefinedSort
: userDefinedSort;
return Array.isArray(sort)
? arraySort__default['default'](filteredData, sort)
: filteredData;
};
/**
* In this special case, useClientRequest hook will
* be called conditionally.
* It means that once a selector has been initialized using
* an API request it could not change to plain data selector
* without showing a React Warning.
* To prevent any accidentally change of this behaviour
* isAPISelector will be saved as a state variable to never
* change on component using
*/
var _f = _tslib.__read(
React__namespace.useState(
(typeof request === 'object' && request !== null) ||
typeof request === 'function'
),
1
),
isAPISelector = _f[0];
var clientRequest = null;
if (isAPISelector) {
var _g =
typeof request === 'function' ? request(componentProps) : request,
url = _g.url,
method = _g.method,
restRequestConfig = _tslib.__rest(_g, ['url', 'method']);
// eslint-disable-next-line
clientRequest = reactAppClient.useClientRequest({
url: url,
method: method,
request: _tslib.__assign(
_tslib.__assign({}, restRequestConfig),
userDefinedRequestConfig
),
});
}
/* --------
* Hooks and State Definition
* -------- */
var _h = _tslib.__read(
React__namespace.useState(function () {
return getOptionsList(
defaultDefinedOptions || userDefinedOptions || []
);
}),
2
),
options = _h[0],
setOptions = _h[1];
var _j = _tslib.__read(React__namespace.useState(isAPISelector), 2),
isInitiallyLoading = _j[0],
setInitiallyLoading = _j[1];
/* --------
* Data Reloading Hook
* -------- */
if (isAPISelector && clientRequest) {
// eslint-disable-next-line
React__namespace.useEffect(
function () {
if (!clientRequest || clientRequest.isLoading) {
return;
}
if (clientRequest.error) {
return;
}
setOptions(getOptionsList(clientRequest.response));
setInitiallyLoading(false);
},
// eslint-disable-next-line
[clientRequest, clientRequest.isLoading, clientRequest.response]
);
}
/* --------
* Handlers
* -------- */
var handleMenuOpen = React__namespace.useCallback(
function (nothing, selectProps) {
var mustReload =
defaultReloadDataOnMenuOpen !== null &&
defaultReloadDataOnMenuOpen !== void 0
? defaultReloadDataOnMenuOpen
: userDefinedReloadDataOnMenuOpen;
if (clientRequest && mustReload) {
clientRequest.reload();
}
if (restSelectProps.onMenuOpen) {
restSelectProps.onMenuOpen(nothing, selectProps);
}
},
[clientRequest, restSelectProps, userDefinedReloadDataOnMenuOpen]
);
// @ts-ignore
var Selector =
(_a =
OverrideSelector !== null && OverrideSelector !== void 0
? OverrideSelector
: UserDefinedSelector) !== null && _a !== void 0
? _a
: DefaultDefinedSelector;
var isLoading =
isInitiallyLoading ||
!!(clientRequest === null || clientRequest === void 0
? void 0
: clientRequest.isLoading);
var isDisabled =
restSelectProps.disabled ||
!!(clientRequest === null || clientRequest === void 0
? void 0
: clientRequest.error);
/** Return the Selector Component */
return (
// @ts-ignore
React__namespace.createElement(
Selector,
_tslib.__assign(
{
isClearable: true,
getOptionValue: defaultGetOptionValue,
getOptionLabel: defaultGetOptionLabel,
},
restSelectProps,
{
defaultValue: restSelectProps.defaultValue,
noOptionsMessage:
(_b = restSelectProps.noOptionsMessage) !== null && _b !== void 0
? _b
: defaultNoOptionsMessage,
placeholder:
(_c = restSelectProps.placeholder) !== null && _c !== void 0
? _c
: defaultPlaceholder,
name:
(_d = restSelectProps.name) !== null && _d !== void 0
? _d
: 'unnamed-selector',
danger:
restSelectProps.danger ||
!!(clientRequest === null || clientRequest === void 0
? void 0
: clientRequest.error),
disabled: isLoading || isDisabled,
loading: isLoading,
options: options,
onMenuOpen: handleMenuOpen,
}
)
)
);
};
/** Set the Display Name */
SelectorWrapper.displayName = displayName;
/** Return the Wrapped Component */
return SelectorWrapper;
}
module.exports = buildSelector;