@arudovwen/react-form-builder
Version:
A complete form builder for react.
144 lines (141 loc) • 7.64 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = MultiSelectValue;
var _react = _interopRequireWildcard(require("react"));
var _react2 = require("@headlessui/react");
var _lucideReact = require("lucide-react");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function MultiSelectValue({
value = [],
onChange,
options = []
}) {
const [selectedOptions, setSelectedOptions] = (0, _react.useState)(value);
(0, _react.useEffect)(() => {
if (onChange) {
const normalized = selectedOptions.map(i => ({
...i,
fieldType: i.fieldType || 'text',
operator: i.operator || 'equals',
value: i.value ?? '' // handles empty string, 0, false properly
}));
onChange(normalized);
}
}, [selectedOptions]);
const filteredOptions = options.filter(opt => !selectedOptions.some(sel => sel.id === opt.id));
const removeItem = id => {
setSelectedOptions(prev => prev.filter(item => item.id !== id));
};
// const handleLabelChange = (index, newLabel) => {
// setSelectedOptions((prev) => prev.map((item, i) => (i === index ? { ...item, label: newLabel } : item)));
// };
const handleValueChange = (index, name, newValue) => {
setSelectedOptions(prev => prev.map((item, i) => i === index ? {
...item,
[name]: newValue
} : item));
};
return /*#__PURE__*/_react.default.createElement("div", {
className: "space-y-2"
}, /*#__PURE__*/_react.default.createElement(_react2.Listbox, {
value: selectedOptions,
onChange: setSelectedOptions,
multiple: true
}, /*#__PURE__*/_react.default.createElement("div", {
className: "relative mt-1"
}, /*#__PURE__*/_react.default.createElement(_react2.Listbox.Button, {
className: "relative w-full py-2 pl-3 pr-10 text-sm text-left bg-white border border-gray-300 rounded shadow-sm cursor-default focus:outline-none"
}, /*#__PURE__*/_react.default.createElement("span", {
className: "block truncate"
}, selectedOptions.length > 0 ? selectedOptions.map(opt => opt.label).join(', ') : 'Select options'), /*#__PURE__*/_react.default.createElement("span", {
className: "absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none"
}, /*#__PURE__*/_react.default.createElement(_lucideReact.ChevronDown, {
className: "w-4 h-4 text-gray-400"
}))), /*#__PURE__*/_react.default.createElement(_react2.Listbox.Options, {
className: "absolute z-10 w-full py-1 mt-1 overflow-auto text-base bg-white border border-gray-200 rounded shadow max-h-60 focus:outline-none sm:text-sm"
}, filteredOptions.length > 0 ? filteredOptions.map(option => /*#__PURE__*/_react.default.createElement(_react2.Listbox.Option, {
key: option.id,
value: option,
className: ({
active
}) => `relative cursor-pointer select-none py-2 pl-4 pr-4 ${active ? 'bg-blue-100 text-blue-900' : 'text-gray-900'}`
}, ({
selected
}) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
className: `block truncate ${selected ? 'font-medium' : 'font-normal'}`
}, option.label), selected && /*#__PURE__*/_react.default.createElement("span", {
className: "absolute inset-y-0 left-0 flex items-center pl-3 text-blue-600"
}, /*#__PURE__*/_react.default.createElement(_lucideReact.Check, {
className: "w-4 h-4",
"aria-hidden": "true"
}))))) : /*#__PURE__*/_react.default.createElement("div", {
className: "px-4 py-2 text-gray-500"
}, "No option selected")))), selectedOptions.length > 0 && /*#__PURE__*/_react.default.createElement("div", {
className: "grid items-center grid-cols-1 gap-2 mt-1"
}, selectedOptions.map((opt, index) => /*#__PURE__*/_react.default.createElement("div", {
key: opt.id,
className: "flex items-center gap-1 px-2 py-1 text-sm bg-gray-100 border rounded-lg outline-none hover:outline-none focus:outline-none"
}, /*#__PURE__*/_react.default.createElement("input", {
type: "text",
value: opt.label,
readOnly: true,
className: "flex-1 px-1 py-1 text-xs border rounded"
}), /*#__PURE__*/_react.default.createElement("select", {
value: opt.fieldType,
onChange: e => handleValueChange(index, 'fieldType', e.target.value),
className: "flex-1 px-1 py-1 text-xs border rounded outline-none hover:outline-none focus:outline-none"
}, /*#__PURE__*/_react.default.createElement("option", {
value: "text"
}, "Text"), /*#__PURE__*/_react.default.createElement("option", {
value: "number"
}, "Number"), /*#__PURE__*/_react.default.createElement("option", {
value: "boolean"
}, "Boolean")), /*#__PURE__*/_react.default.createElement("select", {
value: opt.operator,
onChange: e => handleValueChange(index, 'operator', e.target.value),
className: "flex-1 px-2 py-1 text-xs border rounded outline-none focus:ring-1 focus:ring-blue-300"
}, /*#__PURE__*/_react.default.createElement("option", {
value: "equals"
}, "Equals"), /*#__PURE__*/_react.default.createElement("option", {
value: "not_equals"
}, "Not equals"), opt.fieldType === 'number' && /*#__PURE__*/_react.default.createElement("option", {
value: "greater"
}, "Greater than"), opt.fieldType === 'number' && /*#__PURE__*/_react.default.createElement("option", {
value: "less"
}, "Less than"), /*#__PURE__*/_react.default.createElement("option", {
value: "contains"
}, "Contains"), /*#__PURE__*/_react.default.createElement("option", {
value: "not_contains"
}, "Does not contain")), opt.fieldType !== 'boolean' ? /*#__PURE__*/_react.default.createElement("input", {
type: opt.fieldType,
value: opt.value || '',
onChange: e => handleValueChange(index, 'value', e.target.value),
className: "flex-1 px-1 py-1 text-xs border rounded outline-none hover:outline-none focus:outline-none",
placeholder: "Value"
}) : /*#__PURE__*/_react.default.createElement("div", {
className: "flex items-center justify-center flex-1 px-1 py-1 text-xs bg-white border rounded outline-none gap-x-4 hover:outline-none focus:outline-none"
}, /*#__PURE__*/_react.default.createElement("label", {
className: "flex items-center !mb-0 gap-x-2"
}, /*#__PURE__*/_react.default.createElement("input", {
type: "radio",
name: `boolean-${index}` // ensures mutual exclusivity per item
,
checked: opt.value === true,
onChange: () => handleValueChange(index, 'value', true)
}), "True"), /*#__PURE__*/_react.default.createElement("label", {
className: "flex items-center gap-x-2 !mb-0"
}, /*#__PURE__*/_react.default.createElement("input", {
type: "radio",
name: `boolean-${index}`,
checked: opt.value === false,
onChange: () => handleValueChange(index, 'value', false)
}), "False")), /*#__PURE__*/_react.default.createElement("button", {
type: "button",
onClick: () => removeItem(opt.id),
className: "text-gray-500 hover:text-gray-700"
}, /*#__PURE__*/_react.default.createElement(_lucideReact.X, {
className: "w-3 h-3"
}))))));
}