@open-formulieren/formio-builder
Version:
An opinionated Formio webform builder for Open Forms
99 lines (98 loc) • 6.78 kB
JavaScript
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;
};
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useField } from 'formik';
import ReactSelect from 'react-select';
import Component from './component';
import Description from './description';
function isOption(opt) {
return opt.options === undefined;
}
function isOptionGroup(opt) {
return opt.options !== undefined;
}
function extractSelectedValue(options, currentValue, isSingle, valueProperty = 'value') {
// normalize everything to arrays, for isSingle -> return the first (and only) element.
const normalizedCurrentValue = isSingle ? [currentValue] : currentValue;
const value = [];
const valueTest = (opt) => normalizedCurrentValue.includes(opt[valueProperty]);
for (const optionOrGroup of options) {
if (isOption(optionOrGroup) && valueTest(optionOrGroup)) {
value.push(optionOrGroup);
}
if (isOptionGroup(optionOrGroup)) {
for (const option of optionOrGroup.options) {
if (valueTest(option)) {
value.push(option);
}
}
}
}
// if no value is set an isSingle is true -> returns undefined, as intended
return isSingle ? value[0] : value;
}
// See https://github.com/JedWatson/react-select/blob/master/packages/react-select/src/theme.ts
const BUILDER_SELECT_THEME = theme => (Object.assign(Object.assign({}, theme), { borderRadius: 4 }));
export function getReactSelectStyles() {
return {
control: (baseStyles, state) => (Object.assign(Object.assign({}, baseStyles), { backgroundColor: 'var(--form-input-bg, #fff)', borderColor: state.isFocused ? 'var(--body-quiet-color, #666)' : 'var(--border-color, #ccc)', boxShadow: undefined, '&:hover': {
borderColor: undefined,
} })),
placeholder: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--body-quiet-color, #e0e0e0)' })),
indicatorSeparator: baseStyles => (Object.assign(Object.assign({}, baseStyles), { backgroundColor: 'var(--border-color, #ccc)' })),
dropdownIndicator: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--body-quiet-color, #e0e0e0)', '&:hover': {
color: 'var(--body-loud-color, #000)',
} })),
clearIndicator: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--body-quiet-color, #e0e0e0)', '&:hover': {
color: 'var(--body-loud-color, #000)',
} })),
valueContainer: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--body-fg, #333)' })),
input: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--body-fg, #333)' })),
singleValue: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--body-fg, #333)' })),
multiValue: baseStyles => (Object.assign(Object.assign({}, baseStyles), { backgroundColor: 'var(--default-button-bg, #017092)' })),
multiValueLabel: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--formio-dropdown-value-label-color, #fff)' })),
multiValueRemove: baseStyles => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--formio-dropdown-value-label-color, #fff)' })),
menu: baseStyles => (Object.assign(Object.assign({}, baseStyles), { backgroundColor: 'var(--form-input-bg, #fff)', borderColor: 'var(--border-color, #ccc)' })),
menuList: baseStyles => (Object.assign(Object.assign({}, baseStyles), { border: 'solid 1px var(--border-color, #ccc)', borderRadius: '4px' })),
option: (baseStyles, state) => (Object.assign(Object.assign({}, baseStyles), { color: 'var(--body-fg, #333)', backgroundColor: state.isFocused
? 'var(--formio-dropdown-highlighted-bg, #f2f2f2)'
: undefined })),
};
}
// can't use React.FC with generics
function Select(_a) {
var { name, label, required = false, tooltip = '', description = '', isClearable = false, isLoading = false, valueProperty = 'value',
// react-select uses null internally, see
// https://github.com/JedWatson/react-select/blob/06e34882638d1526b9f5a1238bb567a3e9460ce5/packages/react-select/src/Select.tsx#L1083
emptyValue = null, onChange } = _a, props = __rest(_a, ["name", "label", "required", "tooltip", "description", "isClearable", "isLoading", "valueProperty", "emptyValue", "onChange"]);
const [field, , { setValue }] = useField(name);
const htmlId = `editform-${name}`;
let value = undefined;
if (props.options) {
const currentValue = field.value;
const isSingle = !Array.isArray(currentValue);
value = extractSelectedValue(props.options, currentValue, isSingle, valueProperty);
}
return (_jsxs(Component, Object.assign({ type: "select", field: name, required: required, htmlId: htmlId, label: label, tooltip: tooltip }, { children: [_jsx("div", { children: _jsx(ReactSelect, Object.assign({ inputId: htmlId, isClearable: isClearable, isLoading: isLoading, getOptionValue: opt => isOption(opt) && opt[valueProperty], className: "formio-builder-select", classNamePrefix: "formio-builder-select", theme: BUILDER_SELECT_THEME, styles: getReactSelectStyles(), menuPlacement: "auto" }, field, props, { onChange: (newValue, action) => {
const isSingle = !Array.isArray(newValue);
// for multiple, the value is reset to empty array (`[]`)
if (action.action === 'clear' && isSingle) {
newValue = emptyValue;
}
const normalized = (isSingle ? [newValue] : newValue);
const rawValues = normalized.map(val => { var _a; return (_a = val === null || val === void 0 ? void 0 : val[valueProperty]) !== null && _a !== void 0 ? _a : emptyValue; });
const rawValue = isSingle ? rawValues[0] : rawValues;
setValue(rawValue);
onChange === null || onChange === void 0 ? void 0 : onChange({ target: { name, value: rawValue } });
}, value: value })) }), description && _jsx(Description, { text: description })] })));
}
export default Select;