@episub/rhf-mui
Version:
Glue components to help intergrating react-hook-forms with mui
253 lines (235 loc) • 14.2 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var core = require('@material-ui/core');
var match = require('autosuggest-highlight/match');
var parse = require('autosuggest-highlight/parse');
var React = require('react');
var reactWindow = require('react-window');
var reactHookForm = require('react-hook-form');
var lab = require('@material-ui/lab');
var mdiMaterialUi = require('mdi-material-ui');
var pickers = require('@material-ui/pickers');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var match__default = /*#__PURE__*/_interopDefaultLegacy(match);
var parse__default = /*#__PURE__*/_interopDefaultLegacy(parse);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
var LISTBOX_PADDING = 8; // px
var LISTBOX_ROW_COUNT = 8; // rows
var ITEM_HEIGHT_STARTING_VALUE = 0;
var FONT_WEIGHT_BOLD = 700;
var FONT_WEIGHT_REGULAR = 400;
var ITEM_HEIGHT_SM_UP = 36;
var ITEM_HEIGHT_XS = 48;
var FINAL_PADDING_MULTIPLYER = 2;
function renderRow(props) {
var data = props.data, index = props.index, style = props.style;
return React__default['default'].cloneElement(data[index], {
style: __assign(__assign({}, style), { top: style.top + LISTBOX_PADDING })
});
}
var OuterElementContext = React__default['default'].createContext({});
// eslint-disable-next-line react/display-name
var OuterElementType = React__default['default'].forwardRef(function (props, ref) {
var outerProps = React__default['default'].useContext(OuterElementContext);
return React__default['default'].createElement("div", __assign({ ref: ref }, props, outerProps));
});
function useResetCache(data) {
var ref = React__default['default'].useRef(null);
React__default['default'].useEffect(function () {
if (ref.current !== null) {
ref.current.resetAfterIndex(ITEM_HEIGHT_STARTING_VALUE, true);
}
}, [data]);
return ref;
}
// Adapter for react-window
var ListboxComponent = React__default['default'].forwardRef(function ListboxComponent(props, ref) {
// eslint-disable-next-line react/prop-types
var children = props.children, other = __rest(props, ["children"]);
var itemData = React__default['default'].Children.toArray(children);
var theme = core.useTheme();
var smUp = core.useMediaQuery(theme.breakpoints.up('sm'), { noSsr: true });
var itemCount = itemData.length;
var itemSize = smUp ? ITEM_HEIGHT_SM_UP : ITEM_HEIGHT_XS;
var getChildSize = function (child) {
if (React__default['default'].isValidElement(child) && child.type === core.ListSubheader) {
return ITEM_HEIGHT_SM_UP;
}
return itemSize;
};
var getHeight = function () {
if (itemCount > LISTBOX_ROW_COUNT) {
return LISTBOX_ROW_COUNT * itemSize;
}
// eslint-disable-next-line unicorn/no-fn-reference-in-iterator,unicorn/no-reduce
return (itemData
.map(function (item) { return getChildSize(item); })
// eslint-disable-next-line unicorn/no-reduce
.reduce(function (a, b) { return a + b; }, ITEM_HEIGHT_STARTING_VALUE));
};
var gridRef = useResetCache(itemCount);
return (React__default['default'].createElement("div", { ref: ref },
React__default['default'].createElement(OuterElementContext.Provider, { value: other },
React__default['default'].createElement(reactWindow.VariableSizeList, { itemData: itemData, height: getHeight() + FINAL_PADDING_MULTIPLYER * LISTBOX_PADDING, width: "100%", ref: gridRef, outerElementType: OuterElementType, innerElementType: "ul", itemSize: function (index) { return getChildSize(itemData[index]); }, overscanCount: 5, itemCount: itemCount }, renderRow))));
});
var RenderGroup = function (params) { return [
React__default['default'].createElement(core.ListSubheader, { key: params.key, component: "div" }, params.group),
params.children,
]; };
var RenderListOption = function (name, inputValue) {
var matches = match__default['default'](name, inputValue);
var parts = parse__default['default'](name, matches);
return (React__default['default'].createElement(core.Typography, { noWrap: true }, parts.map(function (part, index) { return (React__default['default'].createElement("span", {
// eslint-disable-next-line react/no-array-index-key
key: index, style: {
fontWeight: part.highlight ? FONT_WEIGHT_BOLD : FONT_WEIGHT_REGULAR
} }, part.text)); })));
};
var useListboxStyles = core.makeStyles({
listbox: {
boxSizing: 'border-box',
'& ul': {
padding: 0,
margin: 0
}
}
});
/**
* A helper function to quickly get all the values rhf values needed to
* implement an input in material-ui. Given a field name and text props it will
* return associated errors and a new TextFieldProps object with common defaults
* set
*/
var useRHFGetFields = function (_a) {
var name = _a.name, textFieldProps = _a.textFieldProps;
// eslint-disable-next-line @typescript-eslint/unbound-method
var _b = reactHookForm.useFormContext(), control = _b.control, errors = _b.errors;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
var fieldError = reactHookForm.get(errors, name);
var isError = !!fieldError;
return {
control: control,
fieldError: fieldError,
isError: isError,
textFieldProps: __assign(__assign({}, DefaultTextFieldProps), textFieldProps)
};
};
var DefaultTextFieldProps = {
variant: 'outlined',
fullWidth: true
};
/**
* AutocompletePrefilled component is configured as an easy way to setup an
* autocomplete field with virtulised fields already setup.
*/
var AutocompletePrefilled = function (_a) {
var loading = _a.loading, textProps = _a.textProps, autoCompleteProps = _a.autoCompleteProps, disabled = _a.disabled;
var classes = useListboxStyles();
return (React__default['default'].createElement(lab.Autocomplete, __assign({ multiple: false, disableClearable: false, freeSolo: false, loading: loading, disabled: disabled }, autoCompleteProps, { classes: classes, disableListWrap: true, ListboxComponent: ListboxComponent, renderOption: function (option, _a) {
var input = _a.inputValue;
return RenderListOption(autoCompleteProps.getOptionLabel(option), input);
}, renderInput: function (params) { return (React__default['default'].createElement(core.TextField, __assign({}, textProps, params, { disabled: disabled, InputProps: __assign(__assign({}, params.InputProps), { endAdornment: (React__default['default'].createElement(React__default['default'].Fragment, null,
loading ? (React__default['default'].createElement(core.CircularProgress, { color: "inherit", size: 20 })) : null,
params.InputProps.endAdornment)) }) }))); } })));
};
/**
* react-hook-form field for using a checkbox
*/
var RHFCheckbox = function (_a) {
var name = _a.name, label = _a.label, disabled = _a.disabled;
var _b = useRHFGetFields({ name: name }), control = _b.control, isError = _b.isError, fieldError = _b.fieldError;
return (React__default['default'].createElement(core.FormControl, { error: isError },
React__default['default'].createElement(core.FormGroup, null,
React__default['default'].createElement(core.FormControlLabel, { label: label, control: React__default['default'].createElement(reactHookForm.Controller, { name: name, control: control, render: function (_a) {
var onChange = _a.onChange, onBlur = _a.onBlur, value = _a.value, renderName = _a.name;
return (React__default['default'].createElement(core.Checkbox, { disabled: disabled, onBlur: onBlur, onChange: function (e) { return onChange(e.target.checked); }, checked: value, name: renderName }));
} }) }),
React__default['default'].createElement(core.FormHelperText, null, fieldError === null || fieldError === void 0 ? void 0 : fieldError.message))));
};
/**
* react-hook-form field for working with dollars. The field value is expected
* to be representing dollars **not** cents (with the input value being a number
* not a string).
*/
var RHFDollar = function (_a) {
var _b;
var name = _a.name, label = _a.label, disabled = _a.disabled, textFieldProps = _a.textFieldProps;
var _c = useRHFGetFields({ name: name, textFieldProps: textFieldProps }), control = _c.control, mergedTextProps = _c.textFieldProps, isError = _c.isError, fieldError = _c.fieldError;
return (React__default['default'].createElement(reactHookForm.Controller, { as: React__default['default'].createElement(core.TextField, __assign({ inputProps: { step: 0.01, type: 'number' }, InputProps: {
startAdornment: (React__default['default'].createElement(core.InputAdornment, { position: "start" },
React__default['default'].createElement(mdiMaterialUi.CurrencyUsd, { color: "action" })))
} }, mergedTextProps, { id: "dollar-field-" + name, disabled: disabled, error: isError, helperText: (_b = fieldError === null || fieldError === void 0 ? void 0 : fieldError.message) !== null && _b !== void 0 ? _b : mergedTextProps.helperText, label: label })), name: name, control: control }));
};
var RHFKeyboardDate = function (props) {
var _a = useRHFGetFields({
name: props.name,
textFieldProps: props.textFieldProps
}), isError = _a.isError, fieldError = _a.fieldError, control = _a.control, textFieldProps = _a.textFieldProps;
var variant = textFieldProps.variant, otherTextProps = __rest(textFieldProps, ["variant"]);
return (React__default['default'].createElement(reactHookForm.Controller, { render: function (_a) {
var _b;
var onChange = _a.onChange, value = _a.value, onBlur = _a.onBlur;
return (React__default['default'].createElement(pickers.KeyboardDatePicker, __assign({}, otherTextProps, { onChange: onChange, value: value, onBlur: onBlur, disabled: props.disabled, error: isError, format: props.displayDateFormat, helperText: (_b = fieldError === null || fieldError === void 0 ? void 0 : fieldError.message) !== null && _b !== void 0 ? _b : otherTextProps.helperText, label: props.label, inputVariant: variant, InputAdornmentProps: { position: 'start' }, clearable: props.clearable })));
}, control: control, name: props.name }));
};
/**
* If number of errors in RHF is greater than this value it should disable submit
*/
var DISABLE_THRESHOLD = 0;
var RHFSubmitButton = function (_a) {
var disabled = _a.disabled, errors = _a.errors, loading = _a.loading, buttonText = _a.buttonText, otherProps = __rest(_a, ["disabled", "errors", "loading", "buttonText"]);
return (React__default['default'].createElement(core.Button, __assign({}, otherProps, { type: "submit", disabled: loading ||
disabled ||
Object.keys(errors !== null && errors !== void 0 ? errors : {}).length > DISABLE_THRESHOLD }), loading ? React__default['default'].createElement(core.CircularProgress, { size: 23 }) : buttonText !== null && buttonText !== void 0 ? buttonText : 'Submit'));
};
var RHFTextField = function (_a) {
var _b;
var name = _a.name, textFieldProps = _a.textFieldProps, otherProps = __rest(_a, ["name", "textFieldProps"]);
var _c = useRHFGetFields({ name: name, textFieldProps: textFieldProps }), control = _c.control, mergedTextProps = _c.textFieldProps, isError = _c.isError, fieldError = _c.fieldError;
return (React__default['default'].createElement(reactHookForm.Controller, { as: React__default['default'].createElement(core.TextField, __assign({}, otherProps, mergedTextProps, { helperText: (_b = fieldError === null || fieldError === void 0 ? void 0 : fieldError.message) !== null && _b !== void 0 ? _b : mergedTextProps.helperText, error: isError })), name: name, control: control }));
};
exports.AutocompletePrefilled = AutocompletePrefilled;
exports.DefaultTextFieldProps = DefaultTextFieldProps;
exports.ListboxComponent = ListboxComponent;
exports.RHFCheckbox = RHFCheckbox;
exports.RHFDollar = RHFDollar;
exports.RHFKeyboardDate = RHFKeyboardDate;
exports.RHFSubmitButton = RHFSubmitButton;
exports.RHFTextField = RHFTextField;
exports.RenderGroup = RenderGroup;
exports.RenderListOption = RenderListOption;
exports.useListboxStyles = useListboxStyles;
exports.useRHFGetFields = useRHFGetFields;