@vojtechportes/react-query-builder
Version:
Simple, highly configurable query builder for react
1,232 lines (1,092 loc) • 41.4 kB
JavaScript
import React, { createContext, useContext, useState, useEffect } from 'react';
import styled, { css } from 'styled-components';
import uniqid from 'uniqid';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _taggedTemplateLiteralLoose(strings, raw) {
if (!raw) {
raw = strings.slice(0);
}
strings.raw = raw;
return strings;
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return;
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(o);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
return arr2;
}
function _createForOfIteratorHelperLoose(o, allowArrayLike) {
var it;
if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
if (it) o = it;
var i = 0;
return function () {
if (i >= o.length) return {
done: true
};
return {
done: false,
value: o[i++]
};
};
}
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
it = o[Symbol.iterator]();
return it.next.bind(it);
}
var colors = {
primary: '#20639B',
secondary: '#3CAEA3',
tertiary: '#911803',
light: '#f4f4f4',
medium: '#d9d9d9',
darker: '#bfbfbf',
dark: '#848484',
enabled: '#3caea3',
disabled: '#9fb2b0'
};
var strings = {
group: {
not: 'Not',
or: 'Or',
and: 'And',
addRule: 'Add Rule',
addGroup: 'Add Group',
"delete": 'Delete'
},
component: {
"delete": 'Delete'
},
form: {
selectYourValue: 'Select your value'
},
operators: {
LARGER: 'Larger',
SMALLER: 'Smaller',
LARGER_EQUAL: 'Larger or equal',
SMALLER_EQUAL: 'Smaller or equal',
EQUAL: 'Equal',
NOT_EQUAL: 'Not equal',
ALL_IN: 'All in',
ANY_IN: 'Any in',
NOT_IN: 'Not in',
BETWEEN: 'Between',
NOT_BETWEEN: 'Not between',
LIKE: 'Like',
NOT_LIKE: 'Not like'
}
};
var clone = function clone(data) {
return JSON.parse(JSON.stringify(data));
};
var assignIds = function assignIds(data) {
data = {
children: clone(data)
};
var run = function run(d) {
if (typeof d.children !== 'undefined') {
d.children = d.children.map(function (item) {
item.id = uniqid();
return run(item);
});
}
return d;
};
return run(data).children;
};
var denormalizeTree = function denormalizeTree(data) {
var clonedData = clone(data);
var denormalizedData = clonedData.filter(function (item) {
return !item.parent;
});
var run = function run(d, originalData) {
d.map(function (item) {
if (typeof item.children !== 'undefined') {
var tmpItem = clone(item);
delete item.children;
delete item.id;
delete item.parent;
delete item.operators;
item.children = [];
tmpItem.children.map(function (id) {
var clonedChildrenData = clone(originalData.filter(function (oItem) {
return oItem.id === id;
})[0]);
delete clonedChildrenData.id;
delete clonedChildrenData.parent;
delete clonedChildrenData.operators;
item.children.push(clonedChildrenData);
});
run(item.children, originalData);
}
});
};
run(denormalizedData, clonedData);
return denormalizedData;
};
var normalizeTree = function normalizeTree(data) {
var clonedData = {
children: clone(data)
};
var normalizedData = [];
var run = function run(d, parentId) {
if (parentId === void 0) {
parentId = 0;
}
if (typeof d.children !== 'undefined') {
var children = [];
d.children.map(function (item) {
if (parentId !== 0) {
item.parent = parentId;
}
var tmpItem = clone(item);
delete tmpItem.children;
normalizedData.push(tmpItem);
children.push(tmpItem.id);
run(item, item.id);
});
if (parentId !== 0) {
for (var _iterator = _createForOfIteratorHelperLoose(normalizedData), _step; !(_step = _iterator()).done;) {
var item = _step.value;
if (item.id === parentId) {
item.children = children;
}
}
}
}
};
run(clonedData);
return normalizedData;
};
var _templateObject;
var StyledButton = styled.button(_templateObject || (_templateObject = _taggedTemplateLiteralLoose(["\n padding: 0.6rem 1.2rem;\n color: #fff;\n font-size: 0.7rem;\n white-space: nowrap;\n text-transform: uppercase;\n background-color: ", ";\n border: 0;\n border-radius: 3px;\n outline: none;\n cursor: pointer;\n"])), colors.primary);
var Button = function Button(_ref) {
var onClick = _ref.onClick,
className = _ref.className,
label = _ref.label;
return React.createElement(StyledButton, {
onClick: onClick,
className: className
}, label);
};
var _templateObject$1, _templateObject2, _templateObject3;
var StyledComponent = styled.div(_templateObject$1 || (_templateObject$1 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-auto-flow: column;\n margin: 0.5rem 0;\n padding: 0.7rem;\n background-color: #fff;\n border: 1px solid ", ";\n"])), colors.medium);
var Content = styled.div(_templateObject2 || (_templateObject2 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-auto-columns: min-content;\n grid-auto-flow: column;\n grid-gap: 0.5rem;\n"])));
var Controls = styled.div(_templateObject3 || (_templateObject3 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-auto-columns: min-content;\n grid-auto-flow: column;\n grid-gap: 0.5rem;\n justify-self: flex-end;\n"])));
var Component = function Component(_ref) {
var children = _ref.children,
controls = _ref.controls,
className = _ref.className;
return React.createElement(StyledComponent, {
className: className
}, React.createElement(Content, null, children), React.createElement(Controls, null, controls));
};
var BuilderContext = /*#__PURE__*/createContext( // tslint:disable-next-line: no-object-literal-type-assertion
{});
var BuilderContextProvider = function BuilderContextProvider(_ref) {
var fields = _ref.fields,
components = _ref.components,
strings$1 = _ref.strings,
data = _ref.data,
readOnly = _ref.readOnly,
setData = _ref.setData,
onChange = _ref.onChange,
children = _ref.children;
components = _extends({}, defaultComponents, components, {
form: _extends({}, defaultComponents.form, components.form)
});
strings$1 = _extends({}, strings, strings$1, {
component: _extends({}, strings.component, strings$1.component),
form: _extends({}, strings.form, strings$1.form),
group: _extends({}, strings.group, strings$1.group),
operators: _extends({}, strings.operators, strings$1.operators)
});
return React.createElement(BuilderContext.Provider, {
value: {
fields: fields,
components: components,
strings: strings$1,
data: data,
readOnly: readOnly,
setData: setData,
onChange: onChange
}
}, children);
};
var _templateObject$2;
var StyledInput = styled.input(_templateObject$2 || (_templateObject$2 = _taggedTemplateLiteralLoose(["\n min-width: 160px;\n padding: 0.4rem 0.6rem;\n border: 1px solid ", ";\n border-radius: 3px;\n"])), colors.medium);
var Input = function Input(_ref) {
var type = _ref.type,
value = _ref.value,
onChange = _ref.onChange,
className = _ref.className,
_ref$disabled = _ref.disabled,
disabled = _ref$disabled === void 0 ? false : _ref$disabled;
var handleChange = function handleChange(event) {
onChange(event.target.value);
};
return React.createElement(StyledInput, {
type: type,
value: value,
onChange: handleChange,
className: className,
disabled: disabled
});
};
var _templateObject$3;
var StyledSelect = styled.select(_templateObject$3 || (_templateObject$3 = _taggedTemplateLiteralLoose(["\n min-width: 160px;\n padding: 0.4rem 0.6rem;\n border: 1px solid ", ";\n border-radius: 3px;\n"])), colors.medium);
var Select = function Select(_ref) {
var values = _ref.values,
selectedValue = _ref.selectedValue,
emptyValue = _ref.emptyValue,
onChange = _ref.onChange,
className = _ref.className,
_ref$disabled = _ref.disabled,
disabled = _ref$disabled === void 0 ? false : _ref$disabled;
var handleChange = function handleChange(event) {
if (!disabled) {
onChange(event.target.value);
}
};
return React.createElement(StyledSelect, {
onChange: handleChange,
value: selectedValue,
className: className,
disabled: !!disabled
}, React.createElement("option", {
value: "",
disabled: true
}, emptyValue), values.map(function (_ref2) {
var optionValue = _ref2.value,
optionLabel = _ref2.label;
return React.createElement("option", {
value: optionValue,
key: optionValue
}, optionLabel);
}));
};
var _templateObject$4, _templateObject2$1, _templateObject3$1, _templateObject4;
var Container = styled.div(_templateObject$4 || (_templateObject$4 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-auto-columns: min-content;\n grid-auto-flow: column;\n grid-gap: 0.5rem;\n"])));
var OptionContainer = styled.div(_templateObject2$1 || (_templateObject2$1 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-auto-columns: min-content;\n grid-auto-flow: column;\n grid-gap: 0.5rem;\n align-self: center;\n"])));
var Option = styled.span(_templateObject3$1 || (_templateObject3$1 = _taggedTemplateLiteralLoose(["\n padding: 0.3rem 0.5rem;\n color: ", ";\n font-size: 0.7rem;\n line-height: 0.7rem;\n white-space: nowrap;\n border: 1px solid ", ";\n border-radius: 3rem;\n"])), colors.dark, colors.dark);
var Delete = styled.span(_templateObject4 || (_templateObject4 = _taggedTemplateLiteralLoose(["\n cursor: ", ";\n"])), function (_ref) {
var disabled = _ref.disabled;
return !disabled && "pointer";
});
var SelectMulti = function SelectMulti(_ref2) {
var onChange = _ref2.onChange,
onDelete = _ref2.onDelete,
selectedValue = _ref2.selectedValue,
emptyValue = _ref2.emptyValue,
values = _ref2.values,
className = _ref2.className,
_ref2$disabled = _ref2.disabled,
disabled = _ref2$disabled === void 0 ? false : _ref2$disabled;
return React.createElement(Container, {
className: className
}, React.createElement(Select, {
onChange: onChange,
selectedValue: "",
emptyValue: emptyValue,
values: values,
disabled: disabled
}), React.createElement(OptionContainer, null, selectedValue.map(function (value, key) {
var labelIndex = values.findIndex(function (item) {
return item.value === value;
});
return React.createElement(Option, {
key: key
}, values[labelIndex].label, ' ', React.createElement(Delete, {
onClick: function onClick() {
return !disabled && onDelete(value);
},
disabled: !!disabled,
"data-test": "Delete"
}, "[x]"));
})));
};
var _templateObject$5, _templateObject2$2, _templateObject3$2;
var Knob = styled.div(_templateObject$5 || (_templateObject$5 = _taggedTemplateLiteralLoose(["\n position: absolute;\n width: 1.3rem;\n height: 1.3rem;\n background: white;\n border: 1px solid ", ";\n border-radius: 50%;\n box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.4);\n"])), colors.dark);
var StyledSwitch = styled.div(_templateObject2$2 || (_templateObject2$2 = _taggedTemplateLiteralLoose(["\n position: relative;\n width: 3rem;\n height: 1.65rem;\n background-color: ", ";\n border: 1px solid ", ";\n border-radius: 1.4rem;\n cursor: pointer;\n transition: all 0.5s;\n\n ", "\n\n ", " {\n top: 0.1rem;\n left: ", ";\n transition: all 0.5s;\n }\n"])), function (_ref) {
var switched = _ref.switched;
return switched ? colors.primary : colors.darker;
}, colors.dark, function (_ref2) {
var disabled = _ref2.disabled;
return disabled && css(_templateObject3$2 || (_templateObject3$2 = _taggedTemplateLiteralLoose(["\n background-color: ", ";\n cursor: initial;\n\n ", " {\n background: ", ";\n }\n "])), colors.darker, Knob, colors.disabled);
}, Knob, function (_ref3) {
var switched = _ref3.switched;
return switched ? '1.3rem' : '0.1rem';
});
var Switch = function Switch(_ref4) {
var switched = _ref4.switched,
onChange = _ref4.onChange,
_ref4$disabled = _ref4.disabled,
disabled = _ref4$disabled === void 0 ? false : _ref4$disabled,
className = _ref4.className;
var handleClick = function handleClick() {
if (onChange && !disabled) {
onChange(!switched);
}
};
return React.createElement(StyledSwitch, {
"data-test": "Switch",
switched: switched,
disabled: !!disabled,
onClick: handleClick,
className: className
}, React.createElement(Knob, null));
};
var _templateObject$6, _templateObject2$3, _templateObject3$3, _templateObject4$1;
var StyledGroup = styled.div(_templateObject$6 || (_templateObject$6 = _taggedTemplateLiteralLoose(["\n margin: 0.5rem 0;\n padding: 0.7rem;\n background: #f4f4f4;\n border: 1px solid ", ";\n box-shadow: 0px 0px 5px -1px rgba(0, 0, 0, 0.15);\n"])), colors.medium);
var GroupHeader = styled.div(_templateObject2$3 || (_templateObject2$3 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-gap: 1rem;\n grid-template-columns: 1fr 1fr;\n padding: 0 0 0.5rem;\n border-bottom: 1px solid ", ";\n"])), colors.medium);
var Left = styled.div(_templateObject3$3 || (_templateObject3$3 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-auto-columns: min-content;\n grid-auto-flow: column;\n align-self: end;\n justify-self: start;\n\n > div:first-child {\n border-right: 0;\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n }\n\n > div:last-child {\n border-left: 0;\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n }\n\n > div:nth-child(2) {\n border-right: 0;\n border-left: 0;\n }\n"])));
var Right = styled.div(_templateObject4$1 || (_templateObject4$1 = _taggedTemplateLiteralLoose(["\n display: grid;\n grid-auto-columns: min-content;\n grid-auto-flow: column;\n grid-gap: 0.5rem;\n justify-self: end;\n"])));
var Group = function Group(_ref) {
var controlsLeft = _ref.controlsLeft,
controlsRight = _ref.controlsRight,
children = _ref.children,
className = _ref.className;
return React.createElement(StyledGroup, {
className: className
}, React.createElement(GroupHeader, null, React.createElement(Left, null, controlsLeft), React.createElement(Right, null, controlsRight)), children);
};
var _templateObject$7, _templateObject2$4;
var StyledOption = styled.div(_templateObject$7 || (_templateObject$7 = _taggedTemplateLiteralLoose(["\n padding: 0.5rem 0.6rem;\n color: #fff;\n font-weight: bold;\n font-size: 0.7rem;\n text-transform: uppercase;\n background: ", ";\n border: 1px solid ", ";\n cursor: pointer;\n\n ", "\n"])), function (_ref) {
var isSelected = _ref.isSelected;
return !!isSelected ? colors.primary : colors.darker;
}, colors.dark, function (_ref2) {
var disabled = _ref2.disabled,
isSelected = _ref2.isSelected;
return disabled && css(_templateObject2$4 || (_templateObject2$4 = _taggedTemplateLiteralLoose(["\n background: ", ";\n cursor: initial;\n "])), !!isSelected ? colors.dark : colors.darker);
});
var Option$1 = function Option(_ref3) {
var children = _ref3.children,
onClick = _ref3.onClick,
disabled = _ref3.disabled,
value = _ref3.value,
isSelected = _ref3.isSelected,
className = _ref3.className;
var handleClick = function handleClick() {
if (!disabled) {
onClick(value);
}
};
return React.createElement(StyledOption, {
className: className,
isSelected: isSelected,
disabled: disabled,
onClick: handleClick
}, children);
};
var isBoolean = function isBoolean(value) {
return typeof value === 'boolean';
};
var isString = function isString(value) {
return typeof value === 'string';
};
var isUndefined = function isUndefined(value) {
return typeof value === 'undefined';
};
var isArray = function isArray(value) {
return Array.isArray(value);
};
var isStringArray = function isStringArray(value) {
return isArray(value) && value.every(function (item) {
return isString(item);
});
};
var isOptionList = function isOptionList(value) {
return isArray(value) && value.every(function (item) {
return isString(item.value) && isString(item.label);
});
};
var Boolean = function Boolean(_ref) {
var selectedValue = _ref.selectedValue,
id = _ref.id;
var _useContext = useContext(BuilderContext),
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
components = _useContext.components,
readOnly = _useContext.readOnly;
var form = components.form;
var handleChange = function handleChange(value) {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
clonedData[parentIndex].value = value;
setData(clonedData);
onChange(clonedData);
};
if (form) {
return React.createElement(form.Switch, {
onChange: handleChange,
switched: selectedValue,
disabled: readOnly
});
}
return null;
};
var FieldSelect = function FieldSelect(_ref) {
var selectedValue = _ref.selectedValue,
id = _ref.id;
var _useContext = useContext(BuilderContext),
fields = _useContext.fields,
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
components = _useContext.components,
strings = _useContext.strings,
readOnly = _useContext.readOnly;
var form = components.form;
var handleChange = function handleChange(value) {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
var nextField = fields.filter(function (item) {
return item.field === value;
})[0];
clonedData[parentIndex].field = value;
delete clonedData[parentIndex].value;
delete clonedData[parentIndex].operators;
delete clonedData[parentIndex].operator;
switch (nextField.type) {
case 'BOOLEAN':
clonedData[parentIndex].value = false;
break;
case 'DATE':
clonedData[parentIndex].value = nextField.operators && ['BETWEEN', 'NOT_BETWEEN'].includes(nextField.operators[0]) ? ['', ''] : '';
clonedData[parentIndex].operator = nextField.operators && nextField.operators[0];
clonedData[parentIndex].operators = nextField.operators;
break;
case 'TEXT':
clonedData[parentIndex].value = nextField.operators && ['BETWEEN', 'NOT_BETWEEN'].includes(nextField.operators[0]) ? ['', ''] : '';
clonedData[parentIndex].operator = nextField.operators && nextField.operators[0];
clonedData[parentIndex].operators = nextField.operators;
break;
case 'NUMBER':
clonedData[parentIndex].value = nextField.operators && ['BETWEEN', 'NOT_BETWEEN'].includes(nextField.operators[0]) ? ['0', '0'] : '0';
clonedData[parentIndex].operator = nextField.operators && nextField.operators[0];
clonedData[parentIndex].operators = nextField.operators;
break;
case 'LIST':
if (isOptionList(nextField.value)) {
clonedData[parentIndex].value = nextField.value[0].value;
}
clonedData[parentIndex].operator = nextField.operators && nextField.operators[0];
clonedData[parentIndex].operators = nextField.operators;
break;
case 'MULTI_LIST':
if (isOptionList(nextField.value)) {
clonedData[parentIndex].value = [];
}
clonedData[parentIndex].operator = nextField.operators && nextField.operators[0];
clonedData[parentIndex].operators = nextField.operators;
break;
case 'STATEMENT':
clonedData[parentIndex].value = nextField.value;
break;
}
setData(clonedData);
onChange(clonedData);
};
var fieldNames = fields.map(function (field) {
return {
value: field.field,
label: field.label
};
});
if (form && strings.form) {
return React.createElement(form.Select, {
values: fieldNames,
selectedValue: selectedValue,
emptyValue: strings.form.selectYourValue,
onChange: handleChange,
disabled: readOnly
});
}
return null;
};
var Input$1 = function Input(_ref) {
var type = _ref.type,
value = _ref.value,
id = _ref.id;
var _useContext = useContext(BuilderContext),
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
components = _useContext.components,
readOnly = _useContext.readOnly;
var form = components.form;
var handleChange = function handleChange(changedValue, index) {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
if (!isUndefined(index)) {
clonedData[parentIndex].value[index] = changedValue;
} else {
clonedData[parentIndex].value = changedValue;
}
setData(clonedData);
onChange(clonedData);
};
if (form) {
if (isStringArray(value)) {
return React.createElement(React.Fragment, null, React.createElement(form.Input, {
type: type,
value: value[0],
onChange: function onChange(changedValue) {
return handleChange(changedValue, 0);
},
disabled: readOnly
}), React.createElement(form.Input, {
type: type,
value: value[1],
onChange: function onChange(changedValue) {
return handleChange(changedValue, 1);
},
disabled: readOnly
}));
} else {
return React.createElement(form.Input, {
type: type,
value: value,
onChange: handleChange,
disabled: readOnly
});
}
}
return null;
};
var OperatorSelect = function OperatorSelect(_ref) {
var values = _ref.values,
selectedValue = _ref.selectedValue,
id = _ref.id;
var _useContext = useContext(BuilderContext),
fields = _useContext.fields,
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
components = _useContext.components,
strings = _useContext.strings,
readOnly = _useContext.readOnly;
var form = components.form;
var handleChange = function handleChange(value) {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
var fieldIndex = fields.findIndex(function (item) {
return clonedData[parentIndex].field === item.field;
});
if (['DATE', 'TEXT', 'NUMBER'].includes(fields[fieldIndex].type)) {
if (!['BETWEEN', 'NOT_BETWEEN'].includes(value) && isStringArray(clonedData[parentIndex].value)) {
clonedData[parentIndex].value = fields[fieldIndex].type === 'NUMBER' ? '0' : '';
} else if (['BETWEEN', 'NOT_BETWEEN'].includes(value) && !isStringArray(clonedData[parentIndex].value)) {
clonedData[parentIndex].value = fields[fieldIndex].type === 'NUMBER' ? ['0', '0'] : ['', ''];
}
}
clonedData[parentIndex].operator = value;
setData(clonedData);
onChange(clonedData);
};
if (form && strings.form) {
return React.createElement(form.Select, {
values: values,
selectedValue: selectedValue,
emptyValue: strings.form.selectYourValue,
onChange: handleChange,
disabled: readOnly
});
}
return null;
};
var Select$1 = function Select(_ref) {
var selectedValue = _ref.selectedValue,
values = _ref.values,
id = _ref.id;
var _useContext = useContext(BuilderContext),
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
components = _useContext.components,
strings = _useContext.strings,
readOnly = _useContext.readOnly;
var form = components.form;
var handleChange = function handleChange(value) {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
clonedData[parentIndex].value = value;
setData(clonedData);
onChange(clonedData);
};
if (form && strings.form && !readOnly) {
return React.createElement(form.Select, {
onChange: handleChange,
selectedValue: selectedValue,
emptyValue: strings.form.selectYourValue,
values: values,
disabled: readOnly
});
}
return null;
};
var SelectMulti$1 = function SelectMulti(_ref) {
var values = _ref.values,
selectedValue = _ref.selectedValue,
id = _ref.id;
var _useContext = useContext(BuilderContext),
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
components = _useContext.components,
strings = _useContext.strings,
readOnly = _useContext.readOnly;
var form = components.form;
var handleChange = function handleChange(value) {
if (setData && onChange) {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
clonedData[parentIndex].value = clonedData[parentIndex].value.filter(function (item) {
return item !== value;
});
clonedData[parentIndex].value.push(value);
setData(clonedData);
onChange(clonedData);
}
};
var handleDelete = function handleDelete(value) {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
clonedData[parentIndex].value = clonedData[parentIndex].value.filter(function (item) {
return item !== value;
});
setData(clonedData);
onChange(clonedData);
};
if (form && strings.form) {
return React.createElement(form.SelectMulti, {
onChange: handleChange,
onDelete: handleDelete,
selectedValue: selectedValue,
emptyValue: strings.form.selectYourValue,
values: values,
disabled: !!readOnly
});
}
return null;
};
var _templateObject$8;
var BooleanContainer = styled.div(_templateObject$8 || (_templateObject$8 = _taggedTemplateLiteralLoose(["\n align-self: center;\n"])));
var Component$1 = function Component(_ref) {
var fieldRef = _ref.field,
selectedValue = _ref.value,
operator = _ref.operator,
id = _ref.id;
var _useContext = useContext(BuilderContext),
fields = _useContext.fields,
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
components = _useContext.components,
strings = _useContext.strings,
readOnly = _useContext.readOnly;
var ComponentContainer = components.Component,
Remove = components.Remove;
var handleDelete = function handleDelete() {
var clonedData = clone(data);
var index = clonedData.findIndex(function (item) {
return item.id === id;
});
var parentIndex = clonedData.findIndex(function (item) {
return item.id === clonedData[index].parent;
});
var parent = clonedData[parentIndex];
parent.children = parent.children.filter(function (item) {
return item !== id;
});
clonedData = clonedData.filter(function (item) {
return item.id !== id;
});
setData(clonedData);
onChange(clonedData);
};
if (fields && strings.component) {
if (fieldRef === '') {
return React.createElement(ComponentContainer, {
controls: !readOnly && React.createElement(Remove, {
label: strings.component["delete"],
onClick: handleDelete
})
}, React.createElement(FieldSelect, {
selectedValue: '',
id: id
}));
} else {
try {
var fieldIndex = fields.findIndex(function (item) {
return item.field === fieldRef;
});
var _fields$fieldIndex = fields[fieldIndex],
field = _fields$fieldIndex.field,
operators = _fields$fieldIndex.operators,
type = _fields$fieldIndex.type,
fieldValue = _fields$fieldIndex.value;
var operatorsOptionList = operators && operators.map(function (item) {
return {
value: item,
label: strings.operators && strings.operators[item]
};
});
return React.createElement(ComponentContainer, {
controls: !readOnly && React.createElement(Remove, {
label: strings.component["delete"],
onClick: handleDelete
})
}, React.createElement(FieldSelect, {
selectedValue: field,
id: id
}), type === 'BOOLEAN' && isBoolean(selectedValue) && React.createElement(BooleanContainer, null, React.createElement(Boolean, {
id: id,
selectedValue: selectedValue
})), type === 'LIST' && isString(selectedValue) && isOptionList(fieldValue) && isOptionList(operatorsOptionList) && React.createElement(React.Fragment, null, React.createElement(OperatorSelect, {
id: id,
values: operatorsOptionList,
selectedValue: operator
}), operator && React.createElement(Select$1, {
id: id,
selectedValue: selectedValue,
values: fieldValue
})), type === 'MULTI_LIST' && isOptionList(fieldValue) && isOptionList(operatorsOptionList) && isStringArray(selectedValue) && React.createElement(React.Fragment, null, React.createElement(OperatorSelect, {
id: id,
values: operatorsOptionList,
selectedValue: operator
}), operator && React.createElement(SelectMulti$1, {
id: id,
values: fieldValue,
selectedValue: selectedValue
})), type === 'TEXT' && isOptionList(operatorsOptionList) && (isString(selectedValue) || isStringArray(selectedValue)) && React.createElement(React.Fragment, null, React.createElement(OperatorSelect, {
id: id,
values: operatorsOptionList,
selectedValue: operator
}), operator && React.createElement(Input$1, {
type: "text",
value: selectedValue,
id: id
})), type === 'NUMBER' && isOptionList(operatorsOptionList) && (isString(selectedValue) || isStringArray(selectedValue)) && React.createElement(React.Fragment, null, React.createElement(OperatorSelect, {
id: id,
values: operatorsOptionList,
selectedValue: operator
}), operator && React.createElement(Input$1, {
type: "number",
value: selectedValue,
id: id
})), type === 'DATE' && isOptionList(operatorsOptionList) && (isString(selectedValue) || isStringArray(selectedValue)) && React.createElement(React.Fragment, null, React.createElement(OperatorSelect, {
id: id,
values: operatorsOptionList,
selectedValue: operator
}), !isUndefined(operator) && React.createElement(Input$1, {
type: "date",
value: selectedValue,
id: id
})));
} catch (e) {
// tslint:disable-next-line: no-console
console.error("Field \"" + fieldRef + "\" not found in fields definition.");
}
}
}
return null;
};
var Group$1 = function Group(_ref) {
var value = _ref.value,
isNegated = _ref.isNegated,
children = _ref.children,
id = _ref.id,
isRoot = _ref.isRoot;
var _useContext = useContext(BuilderContext),
components = _useContext.components,
data = _useContext.data,
setData = _useContext.setData,
onChange = _useContext.onChange,
strings = _useContext.strings,
readOnly = _useContext.readOnly;
var Add = components.Add,
GroupContainer = components.Group,
Option = components.GroupHeaderOption,
Remove = components.Remove;
var findIndex = function findIndex() {
var clonedData = clone(data);
var parentIndex = clonedData.findIndex(function (item) {
return item.id === id;
});
var insertAfter = parentIndex;
if (data[parentIndex].children && data[parentIndex].children.length > 0) {
var lastChildren = clonedData[parentIndex].children.slice(-1)[0];
insertAfter = clonedData.findIndex(function (item) {
return item.id === lastChildren;
});
}
return {
insertAfter: insertAfter,
parentIndex: parentIndex,
clonedData: clonedData
};
};
var addItem = function addItem(payload) {
var _findIndex = findIndex(),
insertAfter = _findIndex.insertAfter,
parentIndex = _findIndex.parentIndex,
clonedData = _findIndex.clonedData;
if (!clonedData[parentIndex].children) {
clonedData[insertAfter].children = [];
}
clonedData[parentIndex].children.push(payload.id);
clonedData.splice(Number(insertAfter) + 1, 0, payload);
setData(clonedData);
onChange(clonedData);
};
var handleAddGroup = function handleAddGroup() {
var EmptyGroup = {
type: 'GROUP',
value: 'AND',
isNegated: false,
id: uniqid(),
parent: id,
children: []
};
addItem(EmptyGroup);
};
var handleAddRule = function handleAddRule() {
var EmptyRule = {
field: '',
id: uniqid(),
parent: id
};
addItem(EmptyRule);
};
var handleChangeGroupType = function handleChangeGroupType(nextValue) {
var _findIndex2 = findIndex(),
clonedData = _findIndex2.clonedData,
parentIndex = _findIndex2.parentIndex;
clonedData[parentIndex].value = nextValue;
setData(clonedData);
onChange(clonedData);
};
var handleToggleNegateGroup = function handleToggleNegateGroup(nextValue) {
var _findIndex3 = findIndex(),
clonedData = _findIndex3.clonedData,
parentIndex = _findIndex3.parentIndex;
clonedData[parentIndex].isNegated = nextValue;
setData(clonedData);
onChange(clonedData);
};
var handleDeleteGroup = function handleDeleteGroup() {
var clonedData = clone(data).filter(function (item) {
return item.id !== id;
});
clonedData = clonedData.map(function (item) {
if (item.children && item.children.length > 0) {
item.children = item.children.filter(function (childId) {
return childId !== id;
});
}
return item;
});
setData(clonedData);
onChange(clonedData);
};
if (strings.group) {
return React.createElement(GroupContainer, {
controlsLeft: React.createElement(React.Fragment, null, React.createElement(Option, {
isSelected: !!isNegated,
value: !isNegated,
disabled: readOnly,
onClick: handleToggleNegateGroup,
"data-test": "Option[not]"
}, strings.group.not), React.createElement(Option, {
isSelected: value === 'AND',
value: "AND",
disabled: readOnly,
onClick: handleChangeGroupType,
"data-test": "Option[and]"
}, strings.group.and), React.createElement(Option, {
isSelected: value === 'OR',
value: "OR",
disabled: readOnly,
onClick: handleChangeGroupType,
"data-test": "Option[or]"
}, strings.group.or)),
controlsRight: !readOnly && React.createElement(React.Fragment, null, React.createElement(Add, {
onClick: handleAddRule,
label: strings.group.addRule,
"data-test": "AddRule"
}), React.createElement(Add, {
onClick: handleAddGroup,
label: strings.group.addGroup,
"data-test": "AddGroup"
}), !isRoot && React.createElement(Remove, {
onClick: handleDeleteGroup,
label: strings.group["delete"],
"data-test": "Remove"
}))
}, children);
}
return null;
};
var Iterator = function Iterator(_ref) {
var originalData = _ref.originalData,
filteredData = _ref.filteredData,
_ref$isRoot = _ref.isRoot,
isRoot = _ref$isRoot === void 0 ? true : _ref$isRoot;
return React.createElement(React.Fragment, null, filteredData.map(function (item) {
if (typeof item.children !== 'undefined') {
var items = [];
item.children.forEach(function (id) {
items.push(originalData.filter(function (fitem) {
return id === fitem.id;
})[0]);
});
if (item.type === 'GROUP') {
var id = item.id,
value = item.value,
isNegated = item.isNegated;
return React.createElement(Group$1, {
key: id,
value: value,
isNegated: isNegated,
id: id,
isRoot: isRoot
}, React.createElement(Iterator, {
originalData: originalData,
filteredData: items,
isRoot: false
}));
}
return null;
} else {
var field = item.field,
_value = item.value,
_id = item.id,
operator = item.operator;
return React.createElement(Component$1, {
key: _id,
field: field,
value: _value,
operator: operator,
id: _id,
"data-test": "IteratorComponent"
});
}
}));
};
var _templateObject$9;
var SecondaryButton = /*#__PURE__*/styled(Button)(_templateObject$9 || (_templateObject$9 = _taggedTemplateLiteralLoose(["\n background-color: ", ";\n"])), colors.tertiary);
var _templateObject$a;
var Text = styled.span(_templateObject$a || (_templateObject$a = _taggedTemplateLiteralLoose(["\n min-width: 160px;\n padding: 0.4rem 0.6rem;\n color: ", ";\n line-height: 1.3;\n border: 1px solid ", ";\n border-radius: 3px;\n"])), colors.dark, colors.medium);
var _templateObject$b;
var StyledBuilder = styled.div(_templateObject$b || (_templateObject$b = _taggedTemplateLiteralLoose(["\n padding: 1rem;\n background: #fff;\n border: 1px solid ", ";\n"])), colors.light);
var defaultComponents = {
form: {
Input: Input,
Select: Select,
SelectMulti: SelectMulti,
Switch: Switch
},
Remove: SecondaryButton,
Add: Button,
Component: Component,
Group: Group,
GroupHeaderOption: Option$1,
Text: Text
};
var Builder = function Builder(_ref) {
var originalData = _ref.data,
fields = _ref.fields,
_ref$components = _ref.components,
components = _ref$components === void 0 ? defaultComponents : _ref$components,
_ref$strings = _ref.strings,
strings$1 = _ref$strings === void 0 ? strings : _ref$strings,
_ref$readOnly = _ref.readOnly,
readOnly = _ref$readOnly === void 0 ? false : _ref$readOnly,
onChange = _ref.onChange;
var normalizedData;
originalData = assignIds(originalData);
if (originalData.length === 0) {
originalData = [{
type: 'GROUP',
value: 'AND',
isNegated: false,
id: uniqid(),
children: originalData
}];
}
try {
normalizedData = normalizeTree(originalData);
} catch (e) {
throw new Error('Input data tree is in invalid format');
}
var _useState = useState(normalizedData),
data = _useState[0],
setData = _useState[1];
var filteredData = data.filter(function (item) {
return !item.parent;
});
useEffect(function () {
handleChange(normalizedData);
}, []);
var handleChange = function handleChange(nextData) {
if (onChange) {
try {
onChange(denormalizeTree(nextData));
} catch (e) {
throw new Error('Input data tree is in invalid format');
}
}
};
return React.createElement(BuilderContextProvider, {
fields: fields,
components: components,
strings: strings$1,
readOnly: readOnly,
data: data,
setData: setData,
onChange: handleChange
}, React.createElement(StyledBuilder, null, React.createElement(Iterator, {
originalData: data,
filteredData: filteredData
})));
};
export { Builder, BuilderContext, Button, Component, Group, Option$1 as GroupHeaderOption, Input, Option, OptionContainer, SecondaryButton, Select, SelectMulti, Switch, colors, defaultComponents, strings };
//# sourceMappingURL=react-query-builder.esm.js.map