diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.stories.jsx b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.stories.jsx index 1a535d4719..4332fa5554 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.stories.jsx +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.stories.jsx @@ -220,6 +220,18 @@ const ConditionBuilderTemplate = (args) => { * TODO: Declare one or more stories, generally one per design scenario. * NB no need for a 'Playground' because all stories have all controls anyway. */ +const statementConfigCustom = [ + { + id: 'if', + connector: 'and', + label: 'if', + }, + { + id: 'exclIf', + connector: 'or', + label: 'excl. if', + }, +]; export const conditionBuilder = ConditionBuilderTemplate.bind({}); conditionBuilder.storyName = 'Condition Builder'; conditionBuilder.args = { @@ -249,6 +261,17 @@ conditionBuilderWithInitialState.args = { translateWithId: translateWithId, }; +export const conditionBuilderWithCustomStatements = + ConditionBuilderTemplate.bind({}); +conditionBuilderWithCustomStatements.storyName = + 'With Custom statement configuration'; +conditionBuilderWithCustomStatements.args = { + inputConfig: inputData, + variant: NON_HIERARCHICAL_VARIANT, + translateWithId: translateWithId, + statementConfigCustom: statementConfigCustom, +}; + export const conditionBuilderWithActions = ConditionBuilderTemplate.bind({}); conditionBuilderWithActions.storyName = 'With Actions'; conditionBuilderWithActions.args = { diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.test.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.test.js index b53be1ec6d..17a6ed8d7c 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.test.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.test.js @@ -1622,6 +1622,68 @@ describe(componentName, () => { expect(selectedItem); }); + it('check with custom statement configuration ', async () => { + const statementConfigCustom = [ + { + id: 'if', + connector: 'and', + label: 'if', + }, + { + id: 'exclIf', + connector: 'or', + label: 'excl. if', + }, + ]; + + render( + + ); + + // add one condition + await act(() => userEvent.click(screen.getByText('Add condition'))); + + expect(screen.getByRole('option', { name: 'Continent' })); + + await act(() => + userEvent.click(screen.getByRole('option', { name: 'Continent' })) + ); + + expect(screen.getByRole('option', { name: 'is' })); + + await act(() => + userEvent.click(screen.getByRole('option', { name: 'is' })) + ); + + expect(screen.getByRole('option', { name: 'Africa' })); + + await act(() => + userEvent.click(screen.getByRole('option', { name: 'Africa' })) + ); + + const selectedItem = screen.getByRole('button', { name: 'Africa' }); + + expect(selectedItem); + + //change statement option + + expect(screen.getByRole('button', { name: 'if' })); + await act(() => + userEvent.click(screen.getByRole('button', { name: 'if' })) + ); + expect(screen.getByRole('option', { name: 'if (and)' })); + expect(screen.getByRole('option', { name: 'excl. if (or)' })); + + await act(() => + userEvent.click(screen.getByRole('option', { name: 'excl. if (or)' })) + ); + expect(screen.getByRole('button', { name: 'excl. if' })); + }); + // keyboard navigation tests //for Non-Hierarchical variant it('add and remove conditions using keyboard', async () => { diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.tsx b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.tsx index 9faeb1d9a0..63300d1051 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.tsx +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.tsx @@ -65,6 +65,7 @@ export let ConditionBuilder = React.forwardRef( variant = NON_HIERARCHICAL_VARIANT, actions, translateWithId, + statementConfigCustom, ...rest }: ConditionBuilderProps, ref: ForwardedRef @@ -84,6 +85,7 @@ export let ConditionBuilder = React.forwardRef( variant={variant} translateWithId={translateWithId} conditionBuilderRef={conditionBuilderRef} + statementConfigCustom={statementConfigCustom} >
string; + statementConfigCustom: statementConfig[]; }; export type InitialState = { @@ -202,6 +211,7 @@ export interface ConditionBuilderContextInputProps extends PropsWithChildren { ) => Promise; variant?: string; translateWithId?: (id: string) => string; + statementConfigCustom?: statementConfig[]; conditionBuilderRef?: ForwardedRef; } diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.tsx b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.tsx index 143bab6d37..ec5eb70aee 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.tsx +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.tsx @@ -60,6 +60,7 @@ export const ConditionBuilderProvider: React.FC< variant: props.variant, translateWithId: props.translateWithId, conditionBuilderRef: props.conditionBuilderRef, + statementConfigCustom: props.statementConfigCustom, }; return ( diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.tsx b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.tsx index d1d01f7dcd..a61bb1d110 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.tsx +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.tsx @@ -31,6 +31,7 @@ import { Option, } from '../ConditionBuilder.types'; import { blockClass, getValue } from '../utils/util'; +import { translationsObject } from '../ConditionBuilderContext/translationObject'; interface ConditionBuilderItemProps extends PropsWithChildren { className?: string; @@ -68,12 +69,22 @@ export const ConditionBuilderItem = ({ }: ConditionBuilderItemProps) => { const popoverRef = useRef(null); const [open, setOpen] = useState(false); + + const { conditionBuilderRef, statementConfigCustom } = useContext( + ConditionBuilderContext + ); + const statementIdMap = { - ifAll: 'if', - ifAny: 'if', - unlessAll: 'unless', - unlessAny: 'unless', + ifAll: translationsObject.ifText, + ifAny: translationsObject.ifText, + unlessAll: translationsObject.unlessText, + unlessAny: translationsObject.unlessText, }; + //Appending statements from custom statement configuration if present + statementConfigCustom?.forEach((statement) => { + statementIdMap[statement.id] = statement.label; + }); + const [ invalidText, addConditionText, @@ -92,7 +103,7 @@ export const ConditionBuilderItem = ({ ], statementIdMap ); - const { conditionBuilderRef } = useContext(ConditionBuilderContext); + const getPropertyDetails = () => { const { property, operator } = condition || {}; if ( diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.tsx b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.tsx index 83f421674c..35ef954f0d 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.tsx +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.tsx @@ -14,7 +14,7 @@ import { Checkmark } from '@carbon/react/icons'; import PropTypes from 'prop-types'; import { ConditionBuilderContext } from '../../ConditionBuilderContext/ConditionBuilderProvider'; import { useTranslations } from '../../utils/useTranslations'; -import { PropertyConfigOption } from '../../ConditionBuilder.types'; +import { option, statementConfig } from '../../ConditionBuilder.types'; import { blockClass } from '../../utils/util'; interface ItemOptionProps { @@ -22,7 +22,9 @@ interface ItemOptionProps { label?: string; value?: string; }; - config: PropertyConfigOption['config'] & { isStatement?: boolean }; + config: { options?: option[] | statementConfig[] } & { + isStatement?: boolean; + }; onChange: (value: string, e: Event) => void; } export const ItemOption = ({ @@ -78,9 +80,9 @@ export const ItemOption = ({ return (
- {option.text1} ({option.connector}) + {option.label} ({option.connector})
-
{option.text2}
+
{option.secondaryLabel}
); }; @@ -104,7 +106,7 @@ export const ItemOption = ({
    {filteredItems?.map((option) => { const isSelected = selection === option.id; - const Icon = option.icon; + const Icon = (option as option).icon; return (
  • { const [ @@ -46,35 +48,32 @@ export const useDataConfigs = () => { 'after', 'between', ]); + const { statementConfigCustom } = useContext(ConditionBuilderContext); - const statementConfig = [ + const statementConfigDefault = [ { - label: 'ifText', id: 'ifAll', connector: 'and', - text1: ifAll, - text2: '(a && b)', + label: ifAll, + secondaryLabel: '(a && b)', }, { - label: 'ifText', id: 'ifAny', connector: 'or', - text1: ifAny, - text2: '(a || b)', + label: ifAny, + secondaryLabel: '(a || b)', }, { - label: 'unlessText', id: 'unlessAll', connector: 'and', - text1: unlessAll, - text2: '! (a && b)', + label: unlessAll, + secondaryLabel: '! (a && b)', }, { - label: 'unlessText', id: 'unlessAny', connector: 'or', - text1: unlessAny, - text2: '! (a || b)', + label: unlessAny, + secondaryLabel: '! (a || b)', }, ]; @@ -153,7 +152,7 @@ export const useDataConfigs = () => { ]; return { - statementConfig, + statementConfig: statementConfigCustom ?? statementConfigDefault, connectorConfig, operatorConfig, };