diff --git a/plugins/woocommerce-beta-tester/changelog/update-dev-tools-expression-evaluation b/plugins/woocommerce-beta-tester/changelog/update-dev-tools-expression-evaluation new file mode 100644 index 00000000000..81868de608c --- /dev/null +++ b/plugins/woocommerce-beta-tester/changelog/update-dev-tools-expression-evaluation @@ -0,0 +1,4 @@ +Significance: minor +Type: update + +Product Editor Dev Tools: Improve expression evaluation tooling support. diff --git a/plugins/woocommerce-beta-tester/src/product-editor-dev-tools/expression-field.tsx b/plugins/woocommerce-beta-tester/src/product-editor-dev-tools/expression-field.tsx new file mode 100644 index 00000000000..1bde26fa16d --- /dev/null +++ b/plugins/woocommerce-beta-tester/src/product-editor-dev-tools/expression-field.tsx @@ -0,0 +1,137 @@ +/** + * External dependencies + */ +import { Button } from '@wordpress/components'; +import { useEffect, useRef, useState } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { check, closeSmall, edit, trash } from '@wordpress/icons'; +import { evaluate } from '@woocommerce/expression-evaluation'; + +/** + * Internal dependencies + */ +import { ExpressionResult } from './expression-result'; +import { ExpressionTextArea } from './expression-text-area'; + +function evaluateExpression( + expression: string, + evaluationContext: object | undefined +) { + let result; + let error; + + try { + result = evaluate( expression, evaluationContext ); + } catch ( e ) { + error = e; + } + + return { + result, + error, + }; +} + +type ExpressionFieldProps = { + expression?: string; + evaluationContext?: object; + mode?: 'view' | 'edit'; + onEnterEdit?: () => void; + onUpdate?: ( expression: string ) => void; + onCancel?: () => void; + onRemove?: () => void; + updateLabel?: string; +}; + +export function ExpressionField( { + expression = '', + evaluationContext, + mode = 'view', + onEnterEdit, + onUpdate, + onCancel, + onRemove, + updateLabel = __( 'Update', 'woocommerce' ), +}: ExpressionFieldProps ) { + const textAreaRef = useRef< HTMLTextAreaElement >( null ); + + const [ editedExpression, setEditedExpression ] = useState( expression ); + + useEffect( () => setEditedExpression( expression ), [ expression ] ); + + const { result, error } = evaluateExpression( + editedExpression, + evaluationContext + ); + + function handleOnClickEdit() { + const textArea = textAreaRef.current; + + if ( textArea ) { + textArea.focus(); + textArea.setSelectionRange( + textArea.value.length, + textArea.value.length + ); + } + + onEnterEdit?.(); + } + + function handleOnClickCancel() { + setEditedExpression( expression ); + onCancel?.(); + } + + return ( +