From 4d2e6e8df8fc06763d03859d6a42ef336d1fe00e Mon Sep 17 00:00:00 2001 From: Amal K Joy <153802538+amal-k-joy@users.noreply.github.com> Date: Tue, 20 Aug 2024 09:34:12 +0530 Subject: [PATCH] chore(Conditionbuilder): typescript migration (#5841) * feat(conditionbuilder): design review changes 2 * feat(conditionBuilder): test case fix for delete conditions * fix(ConditionBuilder): incomplete state icon and text order * chore(ConditionBuilder): add typescript for condition builder files * chore(ConditionBuilder): add typescript for condition builder files2 * chore(conditionbuilder): type correction * feat(Conditionbuilder): review comments1 --- .../styles/_conditionBuilderItem.scss | 40 ++-- .../{ConditionBlock.js => ConditionBlock.tsx} | 68 ++++-- ...nditionBuilder.js => ConditionBuilder.tsx} | 26 ++- .../ConditionBuilder.types.ts | 207 ++++++++++++++++++ ...Actions.js => ConditionBuilderActions.tsx} | 29 ++- ...nBuilderAdd.js => ConditionBuilderAdd.tsx} | 14 +- ...erButton.js => ConditionBuilderButton.tsx} | 24 +- ...ionConnector.js => ConditionConnector.tsx} | 21 +- ...Content.js => ConditionBuilderContent.tsx} | 82 ++++--- ...ovider.js => ConditionBuilderProvider.tsx} | 67 +++--- ...uilderItem.js => ConditionBuilderItem.tsx} | 57 ++++- ...emDate.js => ConditionBuilderItemDate.tsx} | 10 +- ...mber.js => ConditionBuilderItemNumber.tsx} | 34 ++- .../{ItemOption.js => ItemOption.tsx} | 32 ++- ...ueField.js => ItemOptionForValueField.tsx} | 44 +++- ...emText.js => ConditionBuilderItemText.tsx} | 21 +- ...emTime.js => ConditionBuilderItemTime.tsx} | 12 +- ...upBuilder.js => ConditionGroupBuilder.tsx} | 115 ++++++---- ...nditionPreview.js => ConditionPreview.tsx} | 13 +- .../utils/handleKeyboardEvents.js | 2 +- 20 files changed, 701 insertions(+), 217 deletions(-) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBlock/{ConditionBlock.js => ConditionBlock.tsx} (85%) rename packages/ibm-products/src/components/ConditionBuilder/{ConditionBuilder.js => ConditionBuilder.tsx} (94%) create mode 100644 packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.types.ts rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderActions/{ConditionBuilderActions.js => ConditionBuilderActions.tsx} (87%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderAdd/{ConditionBuilderAdd.js => ConditionBuilderAdd.tsx} (90%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderButton/{ConditionBuilderButton.js => ConditionBuilderButton.tsx} (79%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderConnector/{ConditionConnector.js => ConditionConnector.tsx} (86%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContent/{ConditionBuilderContent.js => ConditionBuilderContent.tsx} (79%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/{ConditionBuilderProvider.js => ConditionBuilderProvider.tsx} (78%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/{ConditionBuilderItem.js => ConditionBuilderItem.tsx} (82%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/{ConditionBuilderItemDate.js => ConditionBuilderItemDate.tsx} (87%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/{ConditionBuilderItemNumber.js => ConditionBuilderItemNumber.tsx} (65%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/{ItemOption.js => ItemOption.tsx} (80%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/{ItemOptionForValueField.js => ItemOptionForValueField.tsx} (84%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemText/{ConditionBuilderItemText.js => ConditionBuilderItemText.tsx} (72%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemTime/{ConditionBuilderItemTime.js => ConditionBuilderItemTime.tsx} (83%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionGroupBuilder/{ConditionGroupBuilder.js => ConditionGroupBuilder.tsx} (84%) rename packages/ibm-products/src/components/ConditionBuilder/ConditionPreview/{ConditionPreview.js => ConditionPreview.tsx} (93%) diff --git a/packages/ibm-products-styles/src/components/ConditionBuilder/styles/_conditionBuilderItem.scss b/packages/ibm-products-styles/src/components/ConditionBuilder/styles/_conditionBuilderItem.scss index c6585b412a..072b3e6dc2 100644 --- a/packages/ibm-products-styles/src/components/ConditionBuilder/styles/_conditionBuilderItem.scss +++ b/packages/ibm-products-styles/src/components/ConditionBuilder/styles/_conditionBuilderItem.scss @@ -263,25 +263,27 @@ $colors: ( align-self: center; margin-left: auto; } -.#{$block-class}__add-button-wrapper > :nth-child(1) { - @include actions-animation(-100%); -} -.#{$block-class}__add-button-wrapper > :nth-child(2) { - @include actions-animation(-200%); -} - -.#{$block-class}__condition-block:focus-within:first-child - .#{$block-class}__add-button-wrapper - > span, -.#{$block-class}__condition--interacting - .#{$block-class}__add-button-wrapper - > span { - z-index: 0; - opacity: 1; - pointer-events: all; - transform: translateX(0); - /* stylelint-disable-next-line carbon/motion-easing-use */ - transition: transform motion(exit, productive) $duration-fast-02; +.#{$block-class}__content-container { + .#{$block-class}__add-button-wrapper > :nth-child(1) { + @include actions-animation(-100%); + } + .#{$block-class}__add-button-wrapper > :nth-child(2) { + @include actions-animation(-200%); + } + + .#{$block-class}__condition-block:focus-within:first-child + .#{$block-class}__add-button-wrapper + > span, + .#{$block-class}__condition--interacting + .#{$block-class}__add-button-wrapper + > span { + z-index: 0; + opacity: 1; + pointer-events: all; + transform: translateX(0); + /* stylelint-disable-next-line carbon/motion-easing-use */ + transition: transform motion(exit, productive) $duration-fast-02; + } } .#{$block-class}__invalid-input { diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBlock/ConditionBlock.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBlock/ConditionBlock.tsx similarity index 85% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBlock/ConditionBlock.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBlock/ConditionBlock.tsx index f1416906e7..e8f7ef34bf 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBlock/ConditionBlock.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBlock/ConditionBlock.tsx @@ -27,17 +27,50 @@ import ConditionBuilderAdd from '../ConditionBuilderAdd/ConditionBuilderAdd'; import { ItemOption } from '../ConditionBuilderItem/ConditionBuilderItemOption/ItemOption'; import { ItemOptionForValueField } from '../ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField'; import { useTranslations } from '../utils/useTranslations'; +import { + Condition, + ConditionGroup, + LogicalOperator, + Property, + PropertyConfig, + PropertyConfigCustom, +} from '../ConditionBuilder.types'; /** * This component build each block of condition consisting of property, operator value and close button. */ -const ConditionBlock = (props) => { - const { property, value, operator } = props.condition; +interface ConditionBlockProps { + condition?: Condition; + onRemove: (e: React.MouseEvent) => void; + onChange: (condition: Condition) => void; + onConnectorOperatorChange?: (op: string) => void; + onStatementChange?: (v: string) => void; + addConditionHandler?: (conditionIndex: number) => void; + addConditionSubGroupHandler?: (conditionIndex: number) => void; + hideConditionSubGroupPreviewHandler?: () => void; + showConditionSubGroupPreviewHandler?: () => void; + hideConditionPreviewHandler?: () => void; + showConditionPreviewHandler?: () => void; + conjunction?: LogicalOperator; + isStatement?: boolean; + group: ConditionGroup; + conditionIndex: number; + aria: { + level: number; + posinset: number; + setsize?: number; + }; + isLastCondition: ( + index: number, + conditions: (ConditionGroup | Condition)[] + ) => void; +} +const ConditionBlock = (props: ConditionBlockProps) => { const { onRemove, onChange, - condition, + condition = {}, conjunction, onConnectorOperatorChange, isStatement, @@ -53,6 +86,7 @@ const ConditionBlock = (props) => { showConditionPreviewHandler, isLastCondition, } = props; + const { property, value, operator } = condition; const { inputConfig, variant, conditionBuilderRef } = useContext( ConditionBuilderContext ); @@ -77,13 +111,15 @@ const ConditionBlock = (props) => { //filtering the current property to access its properties and config options const getCurrentConfig = (property) => { return ( - inputConfig.properties?.find( + inputConfig?.properties?.find( (eachProperty) => eachProperty.id == property ) ?? {} ); }; - const { icon, type, config, label } = getCurrentConfig(property); + const { icon, type, config, label }: Property = getCurrentConfig( + property + ) as Property; //Below possible input types expected for value field. const itemComponents = { @@ -92,10 +128,10 @@ const ConditionBlock = (props) => { date: ConditionBuilderItemDate, time: ConditionBuilderItemTime, option: ItemOptionForValueField, - custom: config?.component, + custom: (config as PropertyConfigCustom['config'])?.component, textarea: ConditionBuilderItemText, }; - const ItemComponent = property ? itemComponents[type] : null; + const ItemComponent = itemComponents[type]; const showAllActionsHandler = () => { setShowAllActions(true); @@ -105,7 +141,7 @@ const ConditionBlock = (props) => { }; const onStatementChangeHandler = (v, evt) => { focusThisField(evt, conditionBuilderRef); - onStatementChange(v); + onStatementChange?.(v); }; const onPropertyChangeHandler = (newProperty) => { @@ -147,8 +183,8 @@ const ConditionBlock = (props) => { return isLastCondition(conditionIndex, conditions); }; const getOperators = () => { - if (config?.operators) { - return config.operators; + if ((config as PropertyConfigCustom['config'])?.operators) { + return (config as PropertyConfigCustom['config']).operators; } return operatorConfig.filter( (operator) => operator.type.indexOf(type) != -1 || operator.type == 'all' @@ -210,7 +246,7 @@ const ConditionBlock = (props) => { onConnectorOperatorChange(op)} + onChange={(op) => onConnectorOperatorChange?.(op)} /> ) : (
@@ -241,7 +277,7 @@ const ConditionBlock = (props) => { { label: propertyText, }} onChange={onPropertyChangeHandler} - config={{ options: inputConfig.properties }} + config={{ options: inputConfig?.properties }} /> {checkIsValid(property) && ( @@ -286,7 +322,7 @@ const ConditionBlock = (props) => { showToolTip={true} data-name="valueField" condition={condition} - config={config} + config={config as PropertyConfig} onChange={onValueChangeHandler} renderChildren={renderChildren} /> @@ -309,10 +345,10 @@ const ConditionBlock = (props) => { {manageActionButtons(conditionIndex, group.conditions) && ( { - addConditionHandler(conditionIndex); + addConditionHandler?.(conditionIndex); }} addConditionSubGroupHandler={() => { - addConditionSubGroupHandler(conditionIndex); + addConditionSubGroupHandler?.(conditionIndex); }} showConditionSubGroupPreviewHandler={ showConditionSubGroupPreviewHandler diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.tsx similarity index 94% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.tsx index b6cfc7ecdf..3bdffac77f 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.tsx @@ -6,8 +6,9 @@ */ // Import portions of React that are needed. -import React, { useRef } from 'react'; +import React, { ForwardedRef, useRef } from 'react'; +/**@ts-ignore */ import { VStack } from '@carbon/react'; // Other standard imports. @@ -22,6 +23,8 @@ import { pkg } from '../../settings'; import { blockClass } from './ConditionBuilderContext/DataConfigs'; import { handleKeyDown } from './utils/handleKeyboardEvents'; +import { ConditionBuilderProps } from './ConditionBuilder.types'; + // Carbon and package components we use. /* TODO: @import(s) of carbon components and other package components. */ @@ -50,9 +53,6 @@ const componentName = 'ConditionBuilder'; export let ConditionBuilder = React.forwardRef( ( { - // The component props, in alphabetical order (for consistency). - - // children /* TODO: remove if not needed. */, className, inputConfig, startConditionLabel, @@ -65,10 +65,10 @@ export let ConditionBuilder = React.forwardRef( actions, translateWithId, ...rest - }, - ref + }: ConditionBuilderProps, + ref: ForwardedRef ) => { - const localRef = useRef(); + const localRef = useRef(null); const conditionBuilderRef = ref || localRef; const handleKeyDownHandler = (evt) => { @@ -134,6 +134,7 @@ ConditionBuilder.propTypes = { /** * optional array of actions */ + /**@ts-ignore */ actions: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, @@ -177,16 +178,17 @@ ConditionBuilder.propTypes = { * Optional prop if you want to pass a saved condition state. * This object should respect the structure of condition state that is available in getConditionState callback */ + /**@ts-ignore */ initialState: PropTypes.shape({ groups: PropTypes.arrayOf( PropTypes.shape({ - groupOperator: PropTypes.string.isRequired, - statement: PropTypes.string.isRequired, + groupOperator: PropTypes.string, + statement: PropTypes.string, conditions: PropTypes.arrayOf( PropTypes.oneOfType([ PropTypes.shape({ - property: PropTypes.string.isRequired, - operator: PropTypes.string.isRequired, + property: PropTypes.string, + operator: PropTypes.string, value: PropTypes.oneOfType([ PropTypes.string, PropTypes.arrayOf( @@ -213,6 +215,7 @@ ConditionBuilder.propTypes = { * This is a mandatory prop that defines the input to the condition builder. */ + /**@ts-ignore */ inputConfig: PropTypes.shape({ properties: PropTypes.arrayOf( PropTypes.shape({ @@ -263,6 +266,7 @@ ConditionBuilder.propTypes = { * The message id will be one of [ "ifText","addConditionText", "addConditionGroupText", "addSubgroupText", "conditionText", "propertyText", "operatorText", "valueText", "connectorText", "conditionRowText","conditionRowGroupText","conditionBuilderText","actionSectionText", "removeConditionText", "addConditionRowText", "startText", "endText", "clearSearchText", "actionsText", "then", "removeActionText", "addActionText", "invalidText", "invalidNumberWarnText"] ] */ + /**@ts-ignore */ translateWithId: PropTypes.func, /* TODO: add types and DocGen for all props. */ /** diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.types.ts b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.types.ts new file mode 100644 index 0000000000..288933980f --- /dev/null +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilder.types.ts @@ -0,0 +1,207 @@ +/** + * 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. + */ +import { TextAreaProps, TextInputProps } from '@carbon/react'; +import { CarbonIconType } from '@carbon/react/icons'; +import { NumberInputProps } from '@carbon/react/lib/components/NumberInput/NumberInput'; +import { + Dispatch, + ForwardedRef, + PropsWithChildren, + ReactNode, + SetStateAction, +} from 'react'; + +export type LogicalOperator = 'and' | 'or'; +export type StatementOperator = 'if' | 'if-not'; + +type CoreOperator = 'is'; +type NumberOperator = 'greater' | 'greaterEqual' | 'lower' | 'lowerEqual'; +type StringOperator = 'startsWith' | 'endsWith'; +type ArrayOperator = 'contains'; +type OptionOperator = 'oneOf'; +type DateOperator = 'before' | 'after'; + +export type Operator = + | LogicalOperator + | StatementOperator + | CoreOperator + | NumberOperator + | StringOperator + | ArrayOperator + | OptionOperator + | DateOperator; + +export type OperatorGroups = + | 'logical' + | 'statement' + | 'core' + | 'number' + | 'string' + | 'array' + | 'option' + | 'date'; + +export type Operators = { + logical: LogicalOperator; + statement: StatementOperator; + core: CoreOperator; + number: NumberOperator; + string: StringOperator; + array: ArrayOperator; + option: OptionOperator; + date: DateOperator; +}; + +export type PropertyConfigOption = { + type: 'option'; + config?: { + options?: { + id: string; + label: string; + icon?: CarbonIconType; + }[]; + }; +}; + +export interface PropertyConfigText { + type: 'text'; + config: TextInputProps; +} + +export interface PropertyConfigTextArea { + type: 'textarea'; + config: TextAreaProps; +} + +export interface PropertyConfigNumber { + type: 'number'; + config: { + min?: number; + max?: number; + step?: number; + unit?: string; + } & NumberInputProps; +} + +export type PropertyConfigDate = { + type: 'date'; + config: object; +}; + +export type PropertyConfigTime = { + type: 'time'; + config: { + timeZones: string[]; + }; +}; + +export type PropertyConfigCustom = { + type: 'custom'; + config: { + component: React.ComponentType; + operators: { + label: string; + id: string; + }[]; + }; +}; + +export type PropertyConfig = { + option: PropertyConfigOption; + text: PropertyConfigText; + textarea: PropertyConfigTextArea; + number: PropertyConfigNumber; + date: PropertyConfigDate; + time: PropertyConfigTime; + custom: PropertyConfigCustom; +}; + +export type Property = { + id: string; + label: string; + icon?: CarbonIconType; +} & ( + | PropertyConfig['option'] + | PropertyConfig['text'] + | PropertyConfig['number'] + | PropertyConfig['date'] + | PropertyConfig['textarea'] + | PropertyConfig['time'] + | PropertyConfig['custom'] +); + +export type inputConfig = { + properties: Property[]; +}; + +export type Option = { + id: string; + label: string; + icon?: CarbonIconType; +}; +export type Condition = { + property?: string; + operator?: Operator | '' | 'INVALID'; + value?: string | Option[] | Option; + id?: string | number; + popoverToOpen?: string; +}; + +export type ConditionGroup = { + conditions?: (ConditionGroup | Condition)[]; + groupOperator?: LogicalOperator; + statement?: StatementOperator; + id: string; +}; + +export type ConditionBuilderState = { + groups?: ConditionGroup[]; + operator?: LogicalOperator; +}; + +export type Action = { + id?: string | number; + label?: string; +}; + +export type ConditionBuilderProps = { + inputConfig: inputConfig; + initialState?: ConditionBuilderState; + getActionsState?: (state: Action[] | undefined) => void; + getConditionState: (state: ConditionBuilderState | undefined) => void; + getOptions?: ( + state: ConditionBuilderState, + condition: Condition + ) => Promise; + actions?: Action[]; + className?: string; + popOverSearchThreshold: number; + startConditionLabel: string; + variant?: 'sentence' | 'tree'; + translateWithId: (id: string) => string; +}; + +export interface ConditionBuilderContextInputProps extends PropsWithChildren { + children?: ReactNode; + inputConfig?: inputConfig; + popOverSearchThreshold?: number; + getOptions?: ( + state: ConditionBuilderState, + condition: Condition + ) => Promise; + variant?: string; + translateWithId?: (id: string) => string; + + conditionBuilderRef?: ForwardedRef; +} + +export type ConditionBuilderContextProps = { + rootState?: ConditionBuilderState; + setRootState?: Dispatch>; + actionState?: Action[]; + setActionState?: Dispatch>; +} & ConditionBuilderContextInputProps; diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderActions/ConditionBuilderActions.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderActions/ConditionBuilderActions.tsx similarity index 87% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderActions/ConditionBuilderActions.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderActions/ConditionBuilderActions.tsx index e27452e946..8c330c9947 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderActions/ConditionBuilderActions.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderActions/ConditionBuilderActions.tsx @@ -9,6 +9,7 @@ import React, { useContext, useState } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { Close } from '@carbon/react/icons'; +/**@ts-ignore */ import { Section, Heading } from '@carbon/react'; import { ConditionBuilderItem } from '../ConditionBuilderItem/ConditionBuilderItem'; import { blockClass } from '../ConditionBuilderContext/DataConfigs'; @@ -18,9 +19,19 @@ import uuidv4 from '../../../global/js/utils/uuidv4'; import { ConditionBuilderButton } from '../ConditionBuilderButton/ConditionBuilderButton'; import { useTranslations } from '../utils/useTranslations'; import { ItemOptionForValueField } from '../ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField'; +import { Action, Option } from '../ConditionBuilder.types'; -const ConditionBuilderActions = ({ actions, className }) => { - const { actionState, setActionState } = useContext(ConditionBuilderContext); +interface ConditionBuilderActionsProps { + actions: Action[] | Option[]; + className?: string; +} +const ConditionBuilderActions = ({ + actions, + className, +}: ConditionBuilderActionsProps) => { + const { actionState = [], setActionState } = useContext( + ConditionBuilderContext + ); const [showDeletionPreview, setShowDeletionPreview] = useState(-1); const [ actionsText, @@ -44,15 +55,15 @@ const ConditionBuilderActions = ({ actions, className }) => { label: undefined, popoverToOpen: 'valueField', }; - setActionState([...actionState, action]); + setActionState?.([...actionState, action]); }; - const onchangeHandler = (selectedId, actionIndex) => { + const onchangeHandler = (selectedId: string, actionIndex: number) => { const action = actions.find((action) => action.id === selectedId); //fetch the selected action from the input action array // same actions can be added multiple times const newAction = { ...action, id: actionState[actionIndex].id }; - setActionState([ + setActionState?.([ ...actionState.slice(0, actionIndex), newAction, ...actionState.slice(actionIndex + 1), @@ -60,9 +71,9 @@ const ConditionBuilderActions = ({ actions, className }) => { }; const onRemove = (selectedId) => { - setActionState(actionState.filter((action) => action.id !== selectedId)); + setActionState?.(actionState.filter((action) => action.id !== selectedId)); }; - const handleShowDeletionPreview = (index) => { + const handleShowDeletionPreview = (index: number) => { setShowDeletionPreview(index); }; const handleHideDeletionPreview = () => { @@ -100,7 +111,7 @@ const ConditionBuilderActions = ({ actions, className }) => { @@ -109,7 +120,7 @@ const ConditionBuilderActions = ({ actions, className }) => { value: action.label, }} onChange={(selection) => onchangeHandler(selection.id, index)} - config={{ options: actions }} + config={{ options: actions as Option[] }} /> diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderAdd/ConditionBuilderAdd.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderAdd/ConditionBuilderAdd.tsx similarity index 90% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderAdd/ConditionBuilderAdd.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderAdd/ConditionBuilderAdd.tsx index 33f878d5e0..6612853c57 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderAdd/ConditionBuilderAdd.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderAdd/ConditionBuilderAdd.tsx @@ -13,6 +13,18 @@ import PropTypes from 'prop-types'; import { blockClass } from '../ConditionBuilderContext/DataConfigs'; import { useTranslations } from '../utils/useTranslations'; +interface ConditionBuilderAddProps { + className?: string; + onClick: () => void; + addConditionSubGroupHandler?: () => void; + showConditionSubGroupPreviewHandler?: () => void; + hideConditionSubGroupPreviewHandler?: () => void; + showConditionPreviewHandler?: () => void; + hideConditionPreviewHandler?: () => void; + enableSubGroup?: boolean; + buttonLabel?: string; + tabIndex?: number; +} const ConditionBuilderAdd = ({ className, onClick, @@ -24,7 +36,7 @@ const ConditionBuilderAdd = ({ enableSubGroup, buttonLabel, tabIndex, -}) => { +}: ConditionBuilderAddProps) => { const [addConditionText, addConditionRowText, addSubgroupText] = useTranslations([ 'addConditionText', diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderButton/ConditionBuilderButton.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderButton/ConditionBuilderButton.tsx similarity index 79% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderButton/ConditionBuilderButton.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderButton/ConditionBuilderButton.tsx index 2aa55d3ce3..e923080909 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderButton/ConditionBuilderButton.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderButton/ConditionBuilderButton.tsx @@ -11,9 +11,27 @@ import cx from 'classnames'; import PropTypes from 'prop-types'; import { Tooltip } from '@carbon/react'; import { blockClass } from '../ConditionBuilderContext/DataConfigs'; -import { WarningAltFilled } from '@carbon/react/icons'; +import { CarbonIconType, WarningAltFilled } from '@carbon/react/icons'; import { usePrefix } from '@carbon/react'; +interface ConditionBuilderButtonProps { + className?: string; + label: string; + hideLabel?: boolean; + tooltipAlign?: string; + renderIcon?: CarbonIconType; + onClick?: (e: React.MouseEvent) => void; + onBlur?: React.FocusEventHandler; + onFocus?: React.FocusEventHandler; + onMouseEnter?: (e: React.MouseEvent) => void; + onMouseLeave?: (e: React.MouseEvent) => void; + showToolTip?: boolean; + wrapperProps?: object; + isInvalid?: boolean; + wrapperClassName?: string; + tabIndex?: number; +} + export const ConditionBuilderButton = ({ className, label, @@ -31,13 +49,13 @@ export const ConditionBuilderButton = ({ wrapperClassName, tabIndex, ...rest -}) => { +}: ConditionBuilderButtonProps) => { const carbonPrefix = usePrefix(); const Button = () => { const dataName = rest['data-name'] ?? ''; return (
))} @@ -209,7 +232,7 @@ const ConditionBuilderContent = ({ )} @@ -217,7 +240,6 @@ const ConditionBuilderContent = ({ )} @@ -250,13 +272,13 @@ ConditionBuilderContent.propTypes = { initialState: PropTypes.shape({ groups: PropTypes.arrayOf( PropTypes.shape({ - groupOperator: PropTypes.string.isRequired, - statement: PropTypes.string.isRequired, + groupOperator: PropTypes.string, + statement: PropTypes.string, conditions: PropTypes.arrayOf( PropTypes.oneOfType([ PropTypes.shape({ - property: PropTypes.string.isRequired, - operator: PropTypes.string.isRequired, + property: PropTypes.string, + operator: PropTypes.string, value: PropTypes.oneOfType([ PropTypes.string, PropTypes.arrayOf( diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.tsx similarity index 78% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.tsx index 5e7b02849b..98fb2a3179 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderContext/ConditionBuilderProvider.tsx @@ -8,8 +8,13 @@ import React, { createContext, useState } from 'react'; import PropTypes from 'prop-types'; import uuidv4 from '../../../global/js/utils/uuidv4'; +import { + Action, + ConditionBuilderContextProps, + ConditionBuilderState, +} from '../ConditionBuilder.types'; -export const emptyState = { +export const emptyState: ConditionBuilderState = { operator: 'or', groups: [ { @@ -29,44 +34,36 @@ export const emptyState = { ], }; -export const ConditionBuilderContext = createContext(); - -// const rootReducer=(state,action)=>{ -// switch(action.type){ -// case 'update': -// ; -// return { -// ...state, -// ...action.payload -// } -// break; -// default: -// return state; -// } - -// } +export const ConditionBuilderContext = + createContext({ + rootState: { + groups: [], + }, + }); -export const ConditionBuilderProvider = (props) => { - const [rootState, setRootState] = useState({ +export const ConditionBuilderProvider: React.FC< + ConditionBuilderContextProps +> = (props) => { + const [rootState, setRootState] = useState({ groups: [], }); - const [actionState, setActionState] = useState([]); + const [actionState, setActionState] = useState([]); + + const contextValue: ConditionBuilderContextProps = { + rootState, + setRootState, + actionState, + setActionState, + inputConfig: props.inputConfig, + popOverSearchThreshold: props.popOverSearchThreshold, + getOptions: props.getOptions, + variant: props.variant, + translateWithId: props.translateWithId, + conditionBuilderRef: props.conditionBuilderRef, + }; return ( - + { // eslint-disable-next-line react/prop-types props.children @@ -84,6 +81,7 @@ ConditionBuilderProvider.propTypes = { /** * ref of condition builder */ + /**@ts-ignore */ conditionBuilderRef: PropTypes.object, /** @@ -100,6 +98,7 @@ ConditionBuilderProvider.propTypes = { * This is a mandatory prop that defines the input to the condition builder. */ + /**@ts-ignore */ inputConfig: PropTypes.shape({ properties: PropTypes.arrayOf( PropTypes.shape({ diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.tsx similarity index 82% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.tsx index 854819b3e6..5696fdf07f 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItem.tsx @@ -5,11 +5,21 @@ * LICENSE file in the root directory of this source tree. */ -import React, { useState, useRef, useEffect, useContext } from 'react'; +import React, { + useState, + useRef, + useEffect, + useContext, + PropsWithChildren, + KeyboardEvent, + ReactNode, + RefObject, + MouseEvent, +} from 'react'; import { Popover, PopoverContent, Layer } from '@carbon/react'; import PropTypes from 'prop-types'; -import { Add } from '@carbon/react/icons'; +import { Add, CarbonIconType } from '@carbon/react/icons'; import { blockClass, valueRenderers, @@ -18,7 +28,32 @@ import { ConditionBuilderButton } from '../ConditionBuilderButton/ConditionBuild import { useTranslations } from '../utils/useTranslations'; import { ConditionBuilderContext } from '../ConditionBuilderContext/ConditionBuilderProvider'; import { handleKeyDownForPopover } from '../utils/handleKeyboardEvents'; +import { + Condition, + PropertyConfig, + Action, + Option, +} from '../ConditionBuilder.types'; + +interface ConditionBuilderItemProps extends PropsWithChildren { + className?: string; + label?: string | Option | Option[]; + renderIcon?: CarbonIconType; + title?: string; + showToolTip?: boolean; + popOverClassName?: string; + type?: string; + condition?: Action & Condition; + config?: PropertyConfig; + renderChildren?: (ref: RefObject) => ReactNode; + onChange?: (val: string) => void; + tabIndex?: number; + onMouseEnter?: (e: React.MouseEvent) => void; + onMouseLeave?: (e: React.MouseEvent) => void; + onFocus?: React.FocusEventHandler; + onBlur?: React.FocusEventHandler; +} export const ConditionBuilderItem = ({ children, className, @@ -33,8 +68,8 @@ export const ConditionBuilderItem = ({ renderChildren, onChange, ...rest -}) => { - const popoverRef = useRef(null); +}: ConditionBuilderItemProps) => { + const popoverRef = useRef(null); const [open, setOpen] = useState(false); const [ @@ -91,7 +126,7 @@ export const ConditionBuilderItem = ({ } else if ( currentField == 'valueField' && type == 'option' && - condition.operator !== 'oneOf' + condition?.operator !== 'oneOf' ) { //close the current popover if the field is valueField and is a single select dropdown. For all other inputs ,popover need to be open on value changes. closePopover(); @@ -111,8 +146,9 @@ export const ConditionBuilderItem = ({ useEffect(() => { //this will focus the first input field in the popover if (open && popoverRef.current) { - const firstFocusableElement = - popoverRef.current.querySelector('input,textarea'); + const firstFocusableElement = popoverRef?.current?.querySelector( + 'input,textarea' + ) as HTMLInputElement; if (firstFocusableElement) { setTimeout(() => firstFocusableElement.focus(), 0); } @@ -142,7 +178,7 @@ export const ConditionBuilderItem = ({ } }; - const handleKeyDownHandler = (evt) => { + const handleKeyDownHandler = (evt: KeyboardEvent) => { handleKeyDownForPopover(evt, conditionBuilderRef, popoverRef); if (evt.key === 'Escape') { manageInvalidSelection(); @@ -179,10 +215,11 @@ export const ConditionBuilderItem = ({ className={className} aria-haspopup aria-expanded={open} - renderIcon={renderIcon ? renderIcon : label == undefined ? Add : null} + renderIcon={ + renderIcon ? renderIcon : label == undefined ? Add : undefined + } showToolTip={showToolTip} isInvalid={isInvalid} - condition={condition} {...rest} /> diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.tsx similarity index 87% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.tsx index b8342e9609..ad1bd29ff2 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemDate/ConditionBuilderItemDate.tsx @@ -5,22 +5,28 @@ * LICENSE file in the root directory of this source tree. */ -import React, { useRef } from 'react'; +import React, { ForwardedRef, useRef } from 'react'; import { DatePicker, DatePickerInput } from '@carbon/react'; import { pkg } from '../../../../settings'; import PropTypes from 'prop-types'; import { useTranslations } from '../../utils/useTranslations'; +import { Condition } from '../../ConditionBuilder.types'; const blockClass = `${pkg.prefix}--condition-builder`; +interface ConditionBuilderItemDate { + conditionState: Condition; + onChange: (date: string) => void; + parentRef: ForwardedRef; +} export const ConditionBuilderItemDate = ({ conditionState, onChange, parentRef, }) => { - const DatePickerInputRef = useRef(); + const DatePickerInputRef = useRef(null); const [startText, endText] = useTranslations(['startText', 'endText']); const datePickerType = conditionState.operator == 'between' ? 'range' : 'single'; diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.tsx similarity index 65% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.tsx index 56c35cfbf1..4e691ac662 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemNumber/ConditionBuilderItemNumber.tsx @@ -12,12 +12,18 @@ import { NumberInput } from '@carbon/react'; import PropTypes from 'prop-types'; import { blockClass } from '../../ConditionBuilderContext/DataConfigs'; import { useTranslations } from '../../utils/useTranslations'; +import { Condition, PropertyConfigNumber } from '../../ConditionBuilder.types'; +interface ConditionBuilderItemNumberProps { + conditionState: Condition; + config: PropertyConfigNumber['config']; + onChange: (value: string) => void; +} export const ConditionBuilderItemNumber = ({ conditionState, config, onChange, -}) => { +}: ConditionBuilderItemNumberProps) => { const [invalidNumberWarnText] = useTranslations(['invalidNumberWarnText']); const onChangeHandler = (e, { value }) => { if (value !== '' && !isNaN(value) && checkIfValid(value)) { @@ -27,24 +33,42 @@ export const ConditionBuilderItemNumber = ({ } }; const checkIfValid = (value) => { - if (value > config.max || value < config.min) { + if ( + config.max !== undefined && + config.min === undefined && + value > config.max + ) { + return false; + } + if ( + config.min !== undefined && + config.max === undefined && + value < config.min + ) { + return false; + } + if ( + config.max !== undefined && + config.min !== undefined && + (value > config.max || value < config.min) + ) { return false; } return true; }; const getDefaultValue = () => { - return conditionState.value?.split(' ')?.[0] ?? ''; + return (conditionState.value as string)?.split(' ')?.[0] ?? ''; }; return (
diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.tsx similarity index 80% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.tsx index 52677eaaaf..2e811cad39 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOption.tsx @@ -15,10 +15,23 @@ import PropTypes from 'prop-types'; import { ConditionBuilderContext } from '../../ConditionBuilderContext/ConditionBuilderProvider'; import { blockClass } from '../../ConditionBuilderContext/DataConfigs'; import { useTranslations } from '../../utils/useTranslations'; +import { PropertyConfigOption } from '../../ConditionBuilder.types'; -export const ItemOption = ({ conditionState = {}, config = {}, onChange }) => { +interface ItemOptionProps { + conditionState: { + label?: string; + value?: string; + }; + config: PropertyConfigOption['config']; + onChange: (value: string, e: Event) => void; +} +export const ItemOption = ({ + conditionState = {}, + config = {}, + onChange, +}: ItemOptionProps) => { const { popOverSearchThreshold } = useContext(ConditionBuilderContext); - const contentRef = useRef(); + const contentRef = useRef(null); const [propertyText, clearSearchText] = useTranslations([ 'propertyText', 'clearSearchText', @@ -36,8 +49,9 @@ export const ItemOption = ({ conditionState = {}, config = {}, onChange }) => { //this will focus the first input field in the popover if (contentRef.current) { - const firstFocusableElement = - contentRef.current.querySelector('input, button,li'); + const firstFocusableElement = contentRef.current?.querySelector( + 'input, button,li' + ) as HTMLInputElement; if (firstFocusableElement) { firstFocusableElement.focus(); @@ -55,11 +69,7 @@ export const ItemOption = ({ conditionState = {}, config = {}, onChange }) => { }; const getAriaLabel = () => { - return conditionState.label - ? conditionState.label - : conditionState.property - ? conditionState.property - : propertyText; + return conditionState.label ? conditionState.label : propertyText; }; if (!allOptions) { @@ -67,7 +77,7 @@ export const ItemOption = ({ conditionState = {}, config = {}, onChange }) => { } return (
- {allOptions.length > popOverSearchThreshold && ( + {popOverSearchThreshold && allOptions.length > popOverSearchThreshold && (
{ onKeyUp={() => { return false; }} - onClick={(evt) => onClickHandler(evt, option, isSelected)} + onClick={(evt) => onClickHandler(evt, option)} >
diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.tsx similarity index 84% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.tsx index e5da69c170..caf8d61298 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemOption/ItemOptionForValueField.tsx @@ -14,18 +14,30 @@ import { Checkbox, CheckboxCheckedFilled, } from '@carbon/react/icons'; +/**@ts-ignore */ import { SelectSkeleton } from '@carbon/react'; import PropTypes from 'prop-types'; import { ConditionBuilderContext } from '../../ConditionBuilderContext/ConditionBuilderProvider'; import { blockClass } from '../../ConditionBuilderContext/DataConfigs'; import { useTranslations } from '../../utils/useTranslations'; +import { + Condition, + ConditionBuilderState, + Option, + PropertyConfigOption, +} from '../../ConditionBuilder.types'; +interface ItemOptionForValueFieldProps { + conditionState: Condition & { label?: string }; + config: PropertyConfigOption['config']; + onChange: (value: any, e?: Event) => void; +} export const ItemOptionForValueField = ({ conditionState = {}, config = {}, onChange, -}) => { +}: ItemOptionForValueFieldProps) => { const multiSelectable = conditionState.operator === 'oneOf'; const { popOverSearchThreshold, getOptions, rootState } = useContext( @@ -35,10 +47,12 @@ export const ItemOptionForValueField = ({ 'propertyText', 'clearSearchText', ]); - const contentRef = useRef(); + const contentRef = useRef(null); - const [allOptions, setAllOptions] = useState(config.options); - const [searchValue, setSearchValue] = useState(''); + const [allOptions, setAllOptions] = useState( + config.options as Option[] + ); + const [searchValue, setSearchValue] = useState(''); const filteredItems = allOptions?.filter((opt) => opt.label.toLowerCase().includes(searchValue.toLowerCase()) @@ -72,7 +86,10 @@ export const ItemOptionForValueField = ({ if (!allOptions && getOptions) { const fetchData = async () => { - const response = await getOptions(rootState, conditionState); + const response = await getOptions( + rootState as ConditionBuilderState, + conditionState + ); if ( response?.length > 0 && Object.keys(response[0]).includes('label') && @@ -91,11 +108,12 @@ export const ItemOptionForValueField = ({ //this will focus the first input field in the popover if (contentRef.current) { - const firstFocusableElement = - contentRef.current.querySelector('input, button,li'); + const firstFocusableElement = contentRef.current.querySelector( + 'input, button,li' + ) as HTMLUListElement | HTMLElement; if (firstFocusableElement) { - firstFocusableElement.focus(); + firstFocusableElement?.focus(); } } }, [allOptions]); @@ -113,10 +131,12 @@ export const ItemOptionForValueField = ({ }; const onClickHandler = (evt, option, isSelected) => { - const updatedSelections = selection.filter((item) => item !== 'INVALID'); + const updatedSelections = selection.filter( + (item) => item !== 'INVALID' + ) as Option[]; if (multiSelectable) { if (isSelected) { - let items = updatedSelections.filter((v) => v.id !== option.id); + const items = updatedSelections.filter((v) => v.id !== option.id); onChange(items.length > 0 ? items : undefined); } else { onChange([...updatedSelections, option]); @@ -138,7 +158,7 @@ export const ItemOptionForValueField = ({ } return (
- {allOptions.length > popOverSearchThreshold && ( + {popOverSearchThreshold && allOptions.length > popOverSearchThreshold && (
{filteredItems?.map((option) => { const isSelected = selection - .map((option) => option.id) + .map((option) => (option as Option).id) .includes(option.id); const Icon = option.icon; diff --git a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.js b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.tsx similarity index 72% rename from packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.js rename to packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.tsx index ebd705c3d0..54d44dcf2e 100644 --- a/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.js +++ b/packages/ibm-products/src/components/ConditionBuilder/ConditionBuilderItem/ConditionBuilderItemText/ConditionBuilderItemText.tsx @@ -12,29 +12,40 @@ import { TextArea, TextInput } from '@carbon/react'; import PropTypes from 'prop-types'; import { blockClass } from '../../ConditionBuilderContext/DataConfigs'; import { checkIsValid } from '../../utils/util'; +import { + Condition, + PropertyConfigText, + PropertyConfigTextArea, +} from '../../ConditionBuilder.types'; +interface ConditionBuilderItemTextProps { + conditionState: Condition; + config: PropertyConfigText | PropertyConfigTextArea; + onChange: (value: string) => void; + type: 'textarea' | 'text'; +} export const ConditionBuilderItemText = ({ conditionState, onChange, config, type, -}) => { +}: ConditionBuilderItemTextProps) => { const inputProps = { - labelText: conditionState.property, + ...config, hideLabel: true, value: checkIsValid(conditionState.value) ? conditionState.value : '', id: conditionState.property?.replace(/\s/g, ''), onChange: (evt) => { onChange(evt.target.value); }, - ...config, + labelText: conditionState.property, }; return (
{type == 'textarea' ? ( -