@carbon/ibm-products
Version:
Carbon for IBM Products
254 lines (246 loc) • 9.7 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2025
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var _rollupPluginBabelHelpers = require('../../../_virtual/_rollupPluginBabelHelpers.js');
var React = require('react');
var index = require('../../../_virtual/index.js');
var react = require('@carbon/react');
var icons = require('@carbon/react/icons');
var ConditionGroupBuilder = require('../ConditionGroupBuilder/ConditionGroupBuilder.js');
var ConditionBuilderProvider = require('../ConditionBuilderContext/ConditionBuilderProvider.js');
var ConditionBuilderButton = require('../ConditionBuilderButton/ConditionBuilderButton.js');
var uuidv4 = require('../../../global/js/utils/uuidv4.js');
var ConditionPreview = require('../ConditionPreview/ConditionPreview.js');
var GroupConnector = require('../ConditionBuilderConnector/GroupConnector.js');
var ConditionBuilderActions = require('../ConditionBuilderActions/ConditionBuilderActions.js');
var useTranslations = require('../utils/useTranslations.js');
var util = require('../utils/util.js');
var _GroupConnector;
const ConditionBuilderContent = _ref => {
let {
startConditionLabel,
getConditionState,
getActionsState,
initialState,
actions
} = _ref;
const {
rootState,
setRootState,
variant,
actionState,
onAddItem
} = React.useContext(ConditionBuilderProvider.ConditionBuilderContext);
const initialConditionState = React.useRef(initialState?.state ? JSON.parse(JSON.stringify(initialState?.state)) : null);
const [isConditionBuilderActive, setIsConditionBuilderActive] = React.useState(false);
const [showConditionGroupPreview, setShowConditionGroupPreview] = React.useState(false);
const [addConditionGroupText, conditionHeadingText, conditionBuilderHierarchicalText] = useTranslations.useTranslations(['addConditionGroupText', 'conditionHeadingText', 'conditionBuilderHierarchicalText']);
const showConditionGroupPreviewHandler = () => {
setShowConditionGroupPreview(true);
};
const hideConditionGroupPreviewHandler = () => {
setShowConditionGroupPreview(false);
};
React.useEffect(() => {
if (rootState?.groups?.length) {
setIsConditionBuilderActive(true);
} else {
setIsConditionBuilderActive(false);
}
if (getConditionState) {
getConditionState(rootState ?? {});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [rootState]);
React.useEffect(() => {
getActionsState?.(actionState ?? []);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [actionState]);
React.useEffect(() => {
if (initialState?.enabledDefault) {
setRootState?.(initialState.state);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [initialState]);
const onStartConditionBuilder = () => {
//when add condition button is clicked.
setIsConditionBuilderActive(true);
if (initialConditionState?.current?.groups?.length) {
setRootState?.(initialConditionState.current);
initialConditionState.current = null;
} else {
setRootState?.(ConditionBuilderProvider.emptyState); //here we can set an empty skeleton object for an empty condition builder,
}
//or we can even pre-populate some existing builder and continue editing
};
const onRemove = React.useCallback(groupId => {
const groups = rootState?.groups?.filter(group => groupId !== group?.id);
setRootState?.({
...rootState,
groups: rootState ? groups : []
});
//set the initial state to empty.
if (groups?.length === 0) {
initialConditionState.current = null;
}
}, [setRootState, rootState]);
const onChangeHandler = (updatedGroup, groupIndex) => {
/**
* This method is triggered from inner components. This will be called every time when any change is to be updated in the rootState.
* This gets the updated group as argument.
*/
if (rootState && rootState.groups) {
const groups = [...(rootState.groups ? rootState.groups.slice(0, groupIndex) : []), updatedGroup, ...(rootState.groups ? rootState.groups.slice(groupIndex + 1) : [])];
setRootState?.({
...rootState,
groups
});
}
};
const addConditionGroupHandler = () => {
const {
preventAdd
} = onAddItem?.({
type: 'group',
state: rootState
}) ?? {};
if (!preventAdd) {
const newGroup = {
statement: 'ifAll',
groupOperator: 'and',
id: uuidv4.default(),
conditions: [{
property: undefined,
operator: '',
value: '',
popoverToOpen: 'propertyField',
id: uuidv4.default()
}]
};
setRootState?.({
...rootState,
groups: rootState && rootState.groups ? [...rootState.groups, newGroup] : [newGroup]
});
}
};
const getColorIndex = () => {
const groupLength = rootState?.groups?.length ?? 0;
return groupLength % 5;
};
if (!isConditionBuilderActive) {
return /*#__PURE__*/React.createElement(react.Button, {
className: `${util.blockClass}__addConditionText-button`,
renderIcon: props => /*#__PURE__*/React.createElement(icons.Add, props),
iconDescription: startConditionLabel,
kind: "ghost",
size: "sm",
onClick: onStartConditionBuilder
}, startConditionLabel);
}
const wrapperRole = variant === util.HIERARCHICAL_VARIANT ? {
role: 'treegrid',
'aria-label': conditionBuilderHierarchicalText
} : null;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(react.Section, {
className: `${util.blockClass}__heading`,
level: 4
}, /*#__PURE__*/React.createElement(react.Heading, null, conditionHeadingText)), /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
className: `${util.blockClass}__content-container`
}, wrapperRole), rootState && rootState?.groups?.map((eachGroup, groupIndex) => /*#__PURE__*/React.createElement("div", {
key: eachGroup.id,
className: `${util.blockClass}__group-wrapper`
}, /*#__PURE__*/React.createElement(ConditionGroupBuilder.default, {
className: `${util.blockClass}__group`,
aria: {
level: 1,
posinset: groupIndex * 2 + 1,
setsize: (rootState.groups && rootState.groups.length * 2) ?? 0
},
group: eachGroup,
onRemove: () => {
onRemove(eachGroup.id);
},
onChange: updatedGroup => {
onChangeHandler(updatedGroup, groupIndex);
}
}), rootState.groups && groupIndex < rootState.groups.length - 1 && (_GroupConnector || (_GroupConnector = /*#__PURE__*/React.createElement(GroupConnector.default, null))))), variant == util.HIERARCHICAL_VARIANT && /*#__PURE__*/React.createElement("div", {
role: "row",
tabIndex: -1,
"aria-level": 1,
className: `${util.blockClass}__add-group`
}, /*#__PURE__*/React.createElement(ConditionBuilderButton.ConditionBuilderButton, {
renderIcon: icons.TextNewLine,
onClick: addConditionGroupHandler,
onMouseEnter: showConditionGroupPreviewHandler,
onMouseLeave: hideConditionGroupPreviewHandler,
onFocus: showConditionGroupPreviewHandler,
onBlur: hideConditionGroupPreviewHandler,
className: `${util.blockClass}__add-condition-group `,
hideLabel: true,
label: addConditionGroupText,
wrapperProps: {
role: 'gridcell',
'aria-label': addConditionGroupText
}
})), showConditionGroupPreview && /*#__PURE__*/React.createElement(ConditionPreview.default, {
previewType: "newGroup",
colorIndex: getColorIndex(),
group: {
groupOperator: rootState?.operator,
id: uuidv4.default()
}
})), actions && /*#__PURE__*/React.createElement(ConditionBuilderActions.default, {
actions: actions,
className: `${util.blockClass}__actions-container`
}));
};
ConditionBuilderContent.propTypes = {
/**
* optional array of object that give the list of actions.
*/
actions: index.default.arrayOf(index.default.shape({
id: index.default.oneOfType([index.default.string, index.default.number]).isRequired,
label: index.default.string.isRequired
})),
/**
* callback functions that will provide the updated action state back.
*/
getActionsState: index.default.func,
/**
* This is a callback function that returns the updated state
*/
getConditionState: index.default.func.isRequired,
/**
* Optional prop if the condition building need to start from a predefined initial state
*/
initialState: index.default.shape({
state: index.default.shape({
groups: index.default.arrayOf(index.default.shape({
groupOperator: index.default.string,
statement: index.default.string,
conditions: index.default.arrayOf(index.default.oneOfType([index.default.shape({
property: index.default.string,
operator: index.default.string,
value: index.default.oneOfType([index.default.string, index.default.arrayOf(index.default.shape({
id: index.default.string,
label: index.default.string
})), index.default.shape({
id: index.default.string,
label: index.default.string
})])
}), index.default.object]))
})),
operator: index.default.string
}),
enabledDefault: index.default.bool
}),
/* Provide a label to the button that starts condition builder
*/
startConditionLabel: index.default.string.isRequired
};
exports.default = ConditionBuilderContent;