@open-formulieren/formio-builder
Version:
An opinionated Formio webform builder for Open Forms
77 lines (76 loc) • 5.48 kB
JavaScript
"use strict";
var __rest = (this && this.__rest) || function (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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.withMultiple = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
/**
* Wrapper/HOC component to enable multi-input behaviour for (certain) fields.
*
* This component operates on arrays of values instead of just scalars, e.g. a list of
* strings, a list of dates... This is not guaranteed to be compatible with every
* 'atomic' component type of Form.io - Select/File upload handle this property
* themselves rather than needing to be wrapped.
*
* Usage:
*
* const MyComponent = ({name, label, description, ...props}) => {...}
* const MultipleMyComponent = withMultiple(MyComponent);
*
* <MyComponent name="foo" {...props} /> // <input name="foo" />
* <MultipleMyComponent multiple={true|false} name="foo" {...props} /> // <input name="foo[0]" /> etc. />
*
*/
const formik_1 = require("formik");
const react_intl_1 = require("react-intl");
const context_1 = require("../../context");
const component_label_1 = __importDefault(require("./component-label"));
const description_1 = __importDefault(require("./description"));
const Multiple = (props) => {
const { label, description, required, tooltip } = props;
const { as: WrappedComponent, defaultValue, name } = props, otherProps = __rest(props, ["as", "defaultValue", "name"]);
// TypeScript can't infer this itself with generics, as it doesn't know yet what P looks
// like by omitting multiple - but *we* know that HoC forward the remainder of the props.
const nestedProps = otherProps;
const { getFieldProps } = (0, formik_1.useFormikContext)();
let { value: fieldValue } = getFieldProps(name);
// due to possibly bad value initialization, it's possible the value is undefined or
// even a completely different type (because you're switching from multiple false -> true)
// TODO: figure out we can figure this at the formik level? this probably depends on render
// order though
if (!Array.isArray(fieldValue)) {
fieldValue = [];
}
return ((0, jsx_runtime_1.jsxs)(context_1.RenderContext.Provider, Object.assign({ value: { bareInput: true } }, { children: [label && (0, jsx_runtime_1.jsx)(component_label_1.default, { label: label, required: required, tooltip: tooltip }), (0, jsx_runtime_1.jsx)(formik_1.FieldArray, Object.assign({ name: name }, { children: arrayHelpers => ((0, jsx_runtime_1.jsx)("table", Object.assign({ className: "table table-bordered" }, { children: (0, jsx_runtime_1.jsxs)("tbody", { children: [(fieldValue || []).map((_, index) => ((0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("td", { children: (0, jsx_runtime_1.jsx)(WrappedComponent, Object.assign({ name: `${name}[${index}]` }, nestedProps)) }), (0, jsx_runtime_1.jsx)("td", { children: (0, jsx_runtime_1.jsxs)("button", Object.assign({ className: "btn btn-secondary", type: "button", onClick: () => arrayHelpers.remove(index) }, { children: [(0, jsx_runtime_1.jsx)("span", Object.assign({ className: "sr-only" }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: 'd5SKAT', defaultMessage: [{ type: 0, value: "Remove item" }] }) })), (0, jsx_runtime_1.jsx)("i", { className: "fa fa-times-circle-o", "aria-hidden": "true" })] })) })] }, index))), (0, jsx_runtime_1.jsx)("tr", { children: (0, jsx_runtime_1.jsx)("td", Object.assign({ colSpan: 2 }, { children: (0, jsx_runtime_1.jsxs)("button", Object.assign({ type: "button", className: "btn btn-primary formio-button-add-another", onClick: () => arrayHelpers.push(defaultValue) }, { children: [(0, jsx_runtime_1.jsx)("i", { className: "fa fa-plus", "aria-hidden": "true" }), (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: 'Fc/emc', defaultMessage: [{ type: 0, value: "Add another" }] })] })) })) })] }) }))) })), description && (0, jsx_runtime_1.jsx)(description_1.default, { text: description })] })));
};
/**
* Wrap a given component into a higher order Multiple component.
*/
function withMultiple(WrappedComponent, defaultValue) {
return (props) => {
const { multiple } = props, otherProps = __rest(props, ["multiple"]);
// TypeScript can't infer this itself with generics, as it doesn't know yet what P looks
// like by omitting multiple - but *we* know that HoC forward the remainder of the props.
const nestedProps = otherProps;
// in single value/scalar mode -> just render the component itself
if (!multiple) {
return (0, jsx_runtime_1.jsx)(WrappedComponent, Object.assign({}, nestedProps));
}
// otherwise, go into array-of-fields mode
return (0, jsx_runtime_1.jsx)(Multiple, Object.assign({ as: WrappedComponent, defaultValue: defaultValue }, otherProps));
};
}
exports.withMultiple = withMultiple;
exports.default = Multiple;