@carbon/ibm-products
Version:
Carbon for IBM Products
355 lines (346 loc) • 12.1 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 icons = require('@carbon/react/icons');
var ConditionBuilderItem = require('../ConditionBuilderItem/ConditionBuilderItem.js');
var index = require('../../../_virtual/index.js');
var cx = require('classnames');
var ConditionConnector = require('../ConditionBuilderConnector/ConditionConnector.js');
var ConditionBuilderItemNumber = require('../ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.js');
var ConditionBuilderItemText = require('../ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.js');
var ConditionBuilderItemDate = require('../ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.js');
var ConditionBuilderProvider = require('../ConditionBuilderContext/ConditionBuilderProvider.js');
var ConditionBuilderButton = require('../ConditionBuilderButton/ConditionBuilderButton.js');
var util = require('../utils/util.js');
var ConditionBuilderItemTime = require('../ConditionBuilderItem/ConditionBuilderItemTime/ConditionBuilderItemTime.js');
var ConditionBuilderAdd = require('../ConditionBuilderAdd/ConditionBuilderAdd.js');
var ItemOption = require('../ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.js');
var ItemOptionForValueField = require('../ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.js');
var useTranslations = require('../utils/useTranslations.js');
var useDataConfigs = require('../utils/useDataConfigs.js');
/**
* This component build each block of condition consisting of property, operator value and close button.
*/
const ConditionBlock = props => {
const {
onRemove,
onChange,
condition = {},
conjunction,
onConnectorOperatorChange,
isStatement,
group,
onStatementChange,
conditionIndex,
addConditionHandler,
addConditionSubGroupHandler,
aria,
hideConditionSubGroupPreviewHandler,
showConditionSubGroupPreviewHandler,
hideConditionPreviewHandler,
showConditionPreviewHandler,
isLastCondition
} = props;
const {
property,
value,
operator
} = condition;
const {
inputConfig,
variant,
conditionBuilderRef
} = React.useContext(ConditionBuilderProvider.ConditionBuilderContext);
const [showDeletionPreview, setShowDeletionPreview] = React.useState(false);
const [showAllActions, setShowAllActions] = React.useState(false);
const [conditionRowText, conditionText, propertyText, operatorText, removeConditionText] = useTranslations.useTranslations(['conditionRowText', 'conditionText', 'propertyText', 'operatorText', 'removeConditionText']);
const {
statementConfig,
operatorConfig
} = useDataConfigs.useDataConfigs();
//filtering the current property to access its properties and config options
const getCurrentConfig = property => {
return inputConfig?.properties?.find(eachProperty => eachProperty.id == property) ?? {};
};
const {
icon,
type,
config,
label,
description
} = getCurrentConfig(property);
//Below possible input types expected for value field.
const itemComponents = {
text: ConditionBuilderItemText.ConditionBuilderItemText,
number: ConditionBuilderItemNumber.ConditionBuilderItemNumber,
date: ConditionBuilderItemDate.ConditionBuilderItemDate,
time: ConditionBuilderItemTime.ConditionBuilderItemTime,
option: ItemOptionForValueField.ItemOptionForValueField,
custom: config?.component,
textarea: ConditionBuilderItemText.ConditionBuilderItemText
};
const ItemComponent = itemComponents[type];
const showAllActionsHandler = () => {
setShowAllActions(true);
};
const hideAllActionsHandler = () => {
setShowAllActions(false);
};
const onStatementChangeHandler = (v, evt) => {
util.focusThisField(evt, conditionBuilderRef);
onStatementChange?.(v);
};
const onPropertyChangeHandler = newProperty => {
onChange({
...condition,
property: newProperty,
operator: undefined,
value: '',
popoverToOpen: util.checkIsValid(newProperty) ? 'operatorField' : ''
});
};
const onOperatorChangeHandler = newOperator => {
onChange({
...condition,
operator: newOperator,
value: undefined,
popoverToOpen: util.checkIsValid(newOperator) ? 'valueField' : ''
});
};
const onValueChangeHandler = newValue => {
const currentCondition = {
...condition
};
delete currentCondition.popoverToOpen;
onChange({
...currentCondition,
value: newValue
});
};
const handleShowDeletionPreview = () => {
setShowDeletionPreview(true);
};
const handleHideDeletionPreview = () => {
setShowDeletionPreview(false);
};
const manageActionButtons = (conditionIndex, conditions) => {
if (variant === util.HIERARCHICAL_VARIANT) {
return true;
}
return isLastCondition(conditionIndex, conditions);
};
const getOperators = () => {
if (config?.operators) {
return config?.operators;
}
return operatorConfig.filter(operator => operator.type.indexOf(type) != -1 || operator.type == 'all');
};
const getAriaAttributes = () => {
return variant == util.HIERARCHICAL_VARIANT ? {
'aria-level': aria.level,
'aria-posinset': aria.posinset,
'aria-setsize': aria.setsize
} : {};
};
const renderChildren = popoverRef => {
return /*#__PURE__*/React.createElement(ItemComponent, {
conditionState: {
property,
operator,
value
},
onChange: onValueChangeHandler,
config: config,
"data-name": "valueField",
parentRef: popoverRef,
type: type
});
};
return /*#__PURE__*/React.createElement("div", _rollupPluginBabelHelpers.extends({
className: cx(`${util.blockClass}__condition-block`, {
[`${util.blockClass}__condition__deletion-preview`]: showDeletionPreview
}, {
[`${util.blockClass}__gap-bottom`]: variant == util.HIERARCHICAL_VARIANT
}, {
[`${util.blockClass}__gap ${util.blockClass}__gap-bottom`]: variant == util.NON_HIERARCHICAL_VARIANT
}, {
[`${util.blockClass}__condition--interacting`]: showAllActions
}),
role: "row",
"aria-label": conditionRowText
}, getAriaAttributes(), {
tabIndex: -1,
onMouseEnter: showAllActionsHandler,
onMouseLeave: hideAllActionsHandler,
onBlur: hideAllActionsHandler
}), conjunction ? /*#__PURE__*/React.createElement(ConditionConnector.default, {
className: `${util.blockClass}__gap`,
operator: conjunction,
onChange: op => onConnectorOperatorChange?.(op)
}) : '', isStatement && /*#__PURE__*/React.createElement(ConditionBuilderItem.ConditionBuilderItem, {
label: group.statement,
title: conditionText,
"data-name": "connectorField",
popOverClassName: `${util.blockClass}__gap`,
className: `${util.blockClass}__statement-button`,
tabIndex: 0
}, /*#__PURE__*/React.createElement(ItemOption.ItemOption, {
conditionState: {
value: group.statement,
label: conditionText
},
onChange: onStatementChangeHandler,
config: {
options: statementConfig,
isStatement: true
}
})), /*#__PURE__*/React.createElement(ConditionBuilderItem.ConditionBuilderItem, {
label: label ?? condition?.property,
title: propertyText,
renderIcon: icon ?? undefined,
className: `${util.blockClass}__property-field`,
"data-name": "propertyField",
condition: condition,
type: type,
description: description,
onChange: onPropertyChangeHandler
}, /*#__PURE__*/React.createElement(ItemOption.ItemOption, {
conditionState: {
value: property,
label: propertyText
},
onChange: onPropertyChangeHandler,
config: {
options: inputConfig?.properties
}
})), util.checkIsValid(property) && /*#__PURE__*/React.createElement(ConditionBuilderItem.ConditionBuilderItem, {
label: operator,
title: operatorText,
"data-name": "operatorField",
condition: condition,
type: type,
config: config,
onChange: onOperatorChangeHandler
}, /*#__PURE__*/React.createElement(ItemOption.ItemOption, {
config: {
options: getOperators()
},
conditionState: {
value: operator,
label: operatorText
},
onChange: onOperatorChangeHandler
})), util.checkIsValid(property) && util.checkIsValid(operator) && /*#__PURE__*/React.createElement(ConditionBuilderItem.ConditionBuilderItem, {
label: value,
type: type,
title: label,
showToolTip: true,
"data-name": "valueField",
condition: condition,
config: config,
onChange: onValueChangeHandler,
renderChildren: renderChildren
}), /*#__PURE__*/React.createElement("span", {
role: "gridcell",
"aria-label": removeConditionText
}, /*#__PURE__*/React.createElement(ConditionBuilderButton.ConditionBuilderButton, {
hideLabel: true,
label: removeConditionText,
onClick: onRemove,
onMouseEnter: handleShowDeletionPreview,
onMouseLeave: handleHideDeletionPreview,
onFocus: handleShowDeletionPreview,
onBlur: handleHideDeletionPreview,
renderIcon: icons.Close,
className: `${util.blockClass}__close-condition`,
"data-name": "closeCondition",
wrapperClassName: `${util.blockClass}__close-condition-wrapper`
})), manageActionButtons(conditionIndex, group.conditions) && /*#__PURE__*/React.createElement(ConditionBuilderAdd.default, {
onClick: () => {
addConditionHandler?.(conditionIndex);
},
addConditionSubGroupHandler: () => {
addConditionSubGroupHandler?.(conditionIndex);
},
showConditionSubGroupPreviewHandler: showConditionSubGroupPreviewHandler,
hideConditionSubGroupPreviewHandler: hideConditionSubGroupPreviewHandler,
enableSubGroup: variant == util.HIERARCHICAL_VARIANT,
showConditionPreviewHandler: showConditionPreviewHandler,
hideConditionPreviewHandler: hideConditionPreviewHandler,
className: `${util.blockClass}__gap ${util.blockClass}__gap-left`,
group: group
}));
};
ConditionBlock.propTypes = {
/**
* callback to add a new condition
*/
addConditionHandler: index.default.func,
/**
* callback to add a new condition subgroup
*/
addConditionSubGroupHandler: index.default.func,
/**
* object hold aria attributes
*/
aria: index.default.object,
condition: index.default.object,
conditionIndex: index.default.number,
/**
* string that decides to show the condition connector
*/
conjunction: index.default.string,
/**
* object that hold the current group object where is condition is part of
*/
group: index.default.object,
/**
* handler for hiding sub group preview
*/
hideConditionPreviewHandler: index.default.func,
/**
* handler for hiding sub group preview
*/
hideConditionSubGroupPreviewHandler: index.default.func,
isLastCondition: index.default.func,
/**
* boolean that decides to show the statement(if/ excl.if)
*/
isStatement: index.default.bool,
/**
* callback to update the current condition of the state tree
*/
onChange: index.default.func,
/**
* callback to handle the connector(and/or) change
*/
onConnectorOperatorChange: index.default.func,
/**
* callback for Remove a condition
*/
onRemove: index.default.func,
/**
* callback to handle the statement(if/ excl.if) change
*/
onStatementChange: index.default.func,
/**
* handler for showing add condition preview
*/
showConditionPreviewHandler: index.default.func,
/**
* handler for showing sub group preview
*/
showConditionSubGroupPreviewHandler: index.default.func,
/**
* object that hold the current condition
*/
state: index.default.object
};
exports.default = ConditionBlock;