@carbon/ibm-products
Version:
Carbon for IBM Products
308 lines (306 loc) • 11.1 kB
JavaScript
/**
* Copyright IBM Corp. 2020, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import { __toESM } from "../../../_virtual/_rolldown/runtime.js";
import { require_classnames } from "../../../node_modules/classnames/index.js";
import { HIERARCHICAL_VARIANT, NON_HIERARCHICAL_VARIANT, blockClass, checkIsValid, focusThisField } from "../utils/util.js";
import { ConditionBuilderContext } from "../ConditionBuilderContext/ConditionBuilderProvider.js";
import { ConditionBuilderButton } from "../ConditionBuilderButton/ConditionBuilderButton.js";
import { useTranslations } from "../utils/useTranslations.js";
import { ConditionBuilderItem } from "../ConditionBuilderItem/ConditionBuilderItem.js";
import { ItemOption } from "../ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.js";
import { useDataConfigs } from "../utils/useDataConfigs.js";
import ConditionConnector from "../ConditionBuilderConnector/ConditionConnector.js";
import { ConditionBuilderItemNumber } from "../ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.js";
import { ConditionBuilderItemText } from "../ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.js";
import { ConditionBuilderItemDate } from "../ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.js";
import { ConditionBuilderItemTime } from "../ConditionBuilderItem/ConditionBuilderItemTime/ConditionBuilderItemTime.js";
import ConditionBuilderAdd from "../ConditionBuilderAdd/ConditionBuilderAdd.js";
import { ItemOptionForValueField } from "../ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.js";
import React, { useContext, useState } from "react";
import PropTypes from "prop-types";
import { Close } from "@carbon/react/icons";
//#region src/components/ConditionBuilder/ConditionBlock/ConditionBlock.tsx
/**
* Copyright IBM Corp. 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
var import_classnames = /* @__PURE__ */ __toESM(require_classnames());
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, readOnly } = useContext(ConditionBuilderContext);
const [showDeletionPreview, setShowDeletionPreview] = useState(false);
const [showAllActions, setShowAllActions] = useState(false);
const [conditionRowText, conditionText, propertyText, operatorText, removeConditionText] = useTranslations([
"conditionRowText",
"conditionText",
"propertyText",
"operatorText",
"removeConditionText"
]);
const { statementConfig, operatorConfig } = useDataConfigs();
const getCurrentConfig = (property) => {
return inputConfig?.properties?.find((eachProperty) => eachProperty.id == property) ?? {};
};
const { icon, type, config, label, description } = getCurrentConfig(property);
const ItemComponent = {
text: ConditionBuilderItemText,
number: ConditionBuilderItemNumber,
date: ConditionBuilderItemDate,
time: ConditionBuilderItemTime,
option: ItemOptionForValueField,
custom: config?.component,
textarea: ConditionBuilderItemText
}[type];
const showAllActionsHandler = () => {
setShowAllActions(true);
};
const hideAllActionsHandler = () => {
setShowAllActions(false);
};
const onStatementChangeHandler = (v, evt) => {
focusThisField(evt, conditionBuilderRef);
onStatementChange?.(v);
};
const onPropertyChangeHandler = (newProperty) => {
onChange({
...condition,
property: newProperty,
operator: void 0,
value: "",
popoverToOpen: checkIsValid(newProperty) ? "operatorField" : ""
});
};
const onOperatorChangeHandler = (newOperator) => {
onChange({
...condition,
operator: newOperator,
value: void 0,
popoverToOpen: 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 === "Hierarchical") 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 == "Hierarchical" ? {
"aria-level": aria.level,
"aria-posinset": aria.posinset,
"aria-setsize": aria.setsize
} : {};
};
const renderChildren = (popoverRef, closePopover) => {
return /* @__PURE__ */ React.createElement(ItemComponent, {
conditionState: {
property,
operator,
value
},
onChange: onValueChangeHandler,
config,
"data-name": "valueField",
parentRef: popoverRef,
type,
closePopover
});
};
const renderItemOption = (popoverRef, closePopover) => {
return /* @__PURE__ */ React.createElement(ItemOption, {
conditionState: {
value: property,
label: propertyText
},
onChange: onPropertyChangeHandler,
config: { options: inputConfig?.properties },
closePopover,
group
});
};
return /* @__PURE__ */ React.createElement("div", {
className: (0, import_classnames.default)(`${blockClass}__condition-block`, { [`${blockClass}__condition__deletion-preview`]: showDeletionPreview }, { [`${blockClass}__gap-bottom`]: variant == HIERARCHICAL_VARIANT }, { [`${blockClass}__gap ${blockClass}__gap-bottom`]: variant == NON_HIERARCHICAL_VARIANT }, { [`${blockClass}__condition--interacting`]: showAllActions }),
role: "row",
"aria-label": conditionRowText,
...getAriaAttributes(),
onMouseEnter: showAllActionsHandler,
onMouseLeave: hideAllActionsHandler,
onBlur: hideAllActionsHandler
}, conjunction ? /* @__PURE__ */ React.createElement(ConditionConnector, {
className: `${blockClass}__gap`,
operator: conjunction,
onChange: (op) => onConnectorOperatorChange?.(op)
}) : "", isStatement && /* @__PURE__ */ React.createElement(ConditionBuilderItem, {
label: group.statement,
title: conditionText,
"data-name": "connectorField",
popOverClassName: `${blockClass}__gap ${blockClass}__connector`,
className: `${blockClass}__statement-button`,
tabIndex: 0
}, /* @__PURE__ */ React.createElement(ItemOption, {
conditionState: {
value: group.statement,
label: conditionText
},
onChange: onStatementChangeHandler,
config: {
options: statementConfig,
isStatement: true
}
})), /* @__PURE__ */ React.createElement("div", { className: `${blockClass}__condition-inner-block` }, /* @__PURE__ */ React.createElement(ConditionBuilderItem, {
label: label ?? condition?.property,
title: propertyText,
renderIcon: icon ?? void 0,
className: `${blockClass}__property-field`,
"data-name": "propertyField",
condition,
type,
description,
onChange: onPropertyChangeHandler,
renderChildren: renderItemOption
}), checkIsValid(property) && /* @__PURE__ */ React.createElement(ConditionBuilderItem, {
label: operator,
title: operatorText,
"data-name": "operatorField",
condition,
type,
config,
onChange: onOperatorChangeHandler
}, /* @__PURE__ */ React.createElement(ItemOption, {
config: { options: getOperators() },
conditionState: {
value: operator,
label: operatorText
},
onChange: onOperatorChangeHandler
})), checkIsValid(property) && checkIsValid(operator) && /* @__PURE__ */ React.createElement(ConditionBuilderItem, {
label: value,
type,
title: label,
showToolTip: true,
"data-name": "valueField",
condition,
config,
onChange: onValueChangeHandler,
renderChildren
})), !readOnly && /* @__PURE__ */ React.createElement("span", {
role: "gridcell",
"aria-label": removeConditionText
}, /* @__PURE__ */ React.createElement(ConditionBuilderButton, {
hideLabel: true,
label: removeConditionText,
onClick: onRemove,
onMouseEnter: handleShowDeletionPreview,
onMouseLeave: handleHideDeletionPreview,
onFocus: handleShowDeletionPreview,
onBlur: handleHideDeletionPreview,
renderIcon: Close,
className: `${blockClass}__close-condition`,
"data-name": "closeCondition",
wrapperClassName: `${blockClass}__close-condition-wrapper`
})), !readOnly && manageActionButtons(conditionIndex, group.conditions) ? /* @__PURE__ */ React.createElement(ConditionBuilderAdd, {
onClick: () => {
addConditionHandler?.(conditionIndex);
},
addConditionSubGroupHandler: () => {
addConditionSubGroupHandler?.(conditionIndex);
},
showConditionSubGroupPreviewHandler,
hideConditionSubGroupPreviewHandler,
enableSubGroup: variant == HIERARCHICAL_VARIANT,
showConditionPreviewHandler,
hideConditionPreviewHandler,
className: `${blockClass}__gap ${blockClass}__gap-left`,
group
}) : null);
};
ConditionBlock.propTypes = {
/**
* callback to add a new condition
*/
addConditionHandler: PropTypes.func,
/**
* callback to add a new condition subgroup
*/
addConditionSubGroupHandler: PropTypes.func,
/**
* object hold aria attributes
*/
aria: PropTypes.object,
condition: PropTypes.object,
conditionIndex: PropTypes.number,
/**
* string that decides to show the condition connector
*/
conjunction: PropTypes.string,
/**
* object that hold the current group object where is condition is part of
*/
group: PropTypes.object,
/**
* handler for hiding sub group preview
*/
hideConditionPreviewHandler: PropTypes.func,
/**
* handler for hiding sub group preview
*/
hideConditionSubGroupPreviewHandler: PropTypes.func,
isLastCondition: PropTypes.func,
/**
* boolean that decides to show the statement(if/ excl.if)
*/
isStatement: PropTypes.bool,
/**
* callback to update the current condition of the state tree
*/
onChange: PropTypes.func,
/**
* callback to handle the connector(and/or) change
*/
onConnectorOperatorChange: PropTypes.func,
/**
* callback for Remove a condition
*/
onRemove: PropTypes.func,
/**
* callback to handle the statement(if/ excl.if) change
*/
onStatementChange: PropTypes.func,
/**
* handler for showing add condition preview
*/
showConditionPreviewHandler: PropTypes.func,
/**
* handler for showing sub group preview
*/
showConditionSubGroupPreviewHandler: PropTypes.func,
/**
* object that hold the current condition
*/
state: PropTypes.object
};
//#endregion
export { ConditionBlock as default };