From 68b6c0329167bef72f162a97372fe8501ed65717 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Thu, 21 May 2026 18:35:05 -0700 Subject: [PATCH 1/2] improvement(search-replace): pass down to subblocks: --- .../components/editor/components/constants.ts | 3 +- .../checkbox-list/checkbox-list.tsx | 35 +- .../sub-block/components/code/code.tsx | 52 +- .../components/combobox/combobox.tsx | 14 +- .../condition-input/condition-input.tsx | 899 ++++++++++-------- .../credential-selector.tsx | 24 +- .../document-tag-entry/document-tag-entry.tsx | 14 +- .../components/dropdown/dropdown.tsx | 51 +- .../components/eval-input/eval-input.tsx | 117 ++- .../components/file-upload/file-upload.tsx | 39 +- .../components/filter-rule-row.tsx | 73 +- .../filter-builder/filter-builder.tsx | 49 +- .../components/formatted-text.test.tsx | 75 ++ .../sub-block/components/formatted-text.tsx | 78 +- .../grouped-checkbox-list.tsx | 71 +- .../input-mapping/input-mapping.tsx | 61 +- .../knowledge-base-selector.tsx | 72 +- .../knowledge-tag-filters.tsx | 14 +- .../components/long-input/long-input.tsx | 13 + .../mcp-dynamic-args/mcp-dynamic-args.tsx | 28 +- .../mcp-server-modal/mcp-server-selector.tsx | 18 + .../mcp-server-modal/mcp-tool-selector.tsx | 18 + .../messages-input/messages-input.tsx | 10 + .../selector-combobox/selector-combobox.tsx | 26 +- .../selector-input/selector-input.tsx | 4 + .../components/short-input/short-input.tsx | 33 +- .../components/skill-input/skill-input.tsx | 19 +- .../sort-builder/components/sort-rule-row.tsx | 52 +- .../components/sort-builder/sort-builder.tsx | 6 + .../components/starter/input-format.tsx | 92 +- .../table-selector/table-selector.tsx | 19 + .../sub-block/components/table/table.tsx | 51 +- .../components/time-input/time-input.tsx | 29 + .../components/tools/credential-selector.tsx | 22 +- .../components/tools/sub-block-renderer.tsx | 4 + .../components/tool-input/tool-input.tsx | 145 ++- .../variables-input/variables-input.tsx | 72 +- .../workflow-search-highlight.test.ts | 161 ++++ .../components/workflow-search-highlight.ts | 80 ++ .../workflow-selector-input.tsx | 4 + .../editor/components/sub-block/sub-block.tsx | 59 +- .../subflow-editor/subflow-editor.tsx | 101 +- .../panel/components/editor/editor.tsx | 52 +- .../workflow-search-replace.tsx | 57 +- .../components/time-picker/time-picker.tsx | 5 +- .../workflows/search-replace/indexer.test.ts | 480 +++++++++- .../lib/workflows/search-replace/indexer.ts | 335 ++++++- .../search-replace/replacements.test.ts | 88 ++ .../workflows/search-replace/replacements.ts | 26 +- .../search-replace/resources/registry.ts | 19 +- .../resources/resolvers.test.ts | 29 +- .../search-replace/resources/resolvers.ts | 4 +- apps/sim/stores/panel/editor/index.ts | 2 +- apps/sim/stores/panel/editor/store.ts | 46 +- apps/sim/stores/panel/index.ts | 2 +- bun.lock | 1 - 56 files changed, 3151 insertions(+), 802 deletions(-) create mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text.test.tsx create mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight.test.ts create mode 100644 apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight.ts diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/constants.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/constants.ts index 74f504d75a1..66470aec8d2 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/constants.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/constants.ts @@ -1,2 +1 @@ -export const WORKFLOW_SEARCH_HIGHLIGHT_CLASS = - 'rounded-sm bg-orange-400 shadow-[3px_0_0_#fb923c,-3px_0_0_#fb923c]' +export const WORKFLOW_SEARCH_HIGHLIGHT_CLASS = 'rounded-sm bg-orange-400 font-normal text-inherit' diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/checkbox-list/checkbox-list.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/checkbox-list/checkbox-list.tsx index 3b524cf90a5..401ee1f57a1 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/checkbox-list/checkbox-list.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/checkbox-list/checkbox-list.tsx @@ -1,6 +1,9 @@ import { Info } from 'lucide-react' import { Checkbox, Label, Tooltip } from '@/components/emcn' +import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text' +import { getWorkflowSearchLabelHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' +import type { ActiveSearchTarget } from '@/stores/panel/editor/store' interface CheckboxListOption { label: string @@ -11,18 +14,23 @@ interface CheckboxListOption { interface CheckboxListProps { blockId: string + subBlockId: string options: CheckboxListOption[] isPreview?: boolean subBlockValues?: Record disabled?: boolean + activeSearchTarget?: ActiveSearchTarget | null } interface CheckboxItemProps { blockId: string + subBlockId: string option: CheckboxListOption + index: number isPreview: boolean subBlockValues?: Record disabled: boolean + activeSearchTarget?: ActiveSearchTarget | null } /** @@ -33,8 +41,24 @@ interface CheckboxItemProps { * case we fall back to `option.defaultChecked` for the displayed state. Any * explicit boolean (including `false`) takes precedence over the default. */ -function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }: CheckboxItemProps) { +function CheckboxItem({ + blockId, + subBlockId, + option, + index, + isPreview, + subBlockValues, + disabled, + activeSearchTarget, +}: CheckboxItemProps) { const [storeValue, setStoreValue] = useSubBlockValue(blockId, option.id) + const workflowSearchHighlight = getWorkflowSearchLabelHighlight({ + activeSearchTarget, + blockId, + subBlockId, + valuePath: ['options', index], + label: option.label, + }) const previewValue = isPreview && subBlockValues ? subBlockValues[option.id]?.value : undefined const rawValue = isPreview ? previewValue : storeValue @@ -58,7 +82,7 @@ function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }: htmlFor={`${blockId}-${option.id}`} className='cursor-pointer font-medium font-sans text-[var(--text-primary)] text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50' > - {option.label} + {formatDisplayText(option.label, { workflowSearchHighlight })} {option.description && ( @@ -76,21 +100,26 @@ function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }: export function CheckboxList({ blockId, + subBlockId, options, isPreview = false, subBlockValues, disabled = false, + activeSearchTarget, }: CheckboxListProps) { return (
- {options.map((option) => ( + {options.map((option, index) => ( ))}
diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/code/code.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/code/code.tsx index ca4ec57afb1..526c0bc147d 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/code/code.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/code/code.tsx @@ -21,14 +21,20 @@ import { SYSTEM_REFERENCE_PREFIXES, splitReferenceSegment, } from '@/lib/workflows/sanitization/references' +import { WORKFLOW_SEARCH_HIGHLIGHT_CLASS } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/constants' import { checkEnvVarTrigger, EnvVarDropdown, } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/env-var-dropdown' +import { + getValidWorkflowSearchRange, + type WorkflowSearchTextHighlight, +} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text' import { checkTagTrigger, TagDropdown, } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown' +import { getActiveWorkflowSearchHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' import type { WandControlHandlers } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block' import { restoreCursorAfterInsertion } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/utils' @@ -41,6 +47,7 @@ import { createEnvVarPattern, createReferencePattern } from '@/executor/utils/re import { useTagSelection } from '@/hooks/kb/use-tag-selection' import { createShouldHighlightEnvVar, useAvailableEnvVarKeys } from '@/hooks/use-available-env-vars' import { useCodeUndoRedo } from '@/hooks/use-code-undo-redo' +import type { ActiveSearchTarget } from '@/stores/panel/editor/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' const logger = createLogger('Code') @@ -80,6 +87,16 @@ const applyDarkModeTokenStyling = (highlightedCode: string): string => { return highlightedCode } +const WORKFLOW_SEARCH_MATCH_PLACEHOLDER = '__WORKFLOW_SEARCH_MATCH__' + +const escapeHtml = (value: string): string => + value + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", ''') + /** * Type definition for code placeholders during syntax highlighting. */ @@ -99,11 +116,20 @@ interface CodePlaceholder { const createHighlightFunction = ( effectiveLanguage: 'javascript' | 'python' | 'json', shouldHighlightReference: (part: string) => boolean, - shouldHighlightEnvVar: (varName: string) => boolean + shouldHighlightEnvVar: (varName: string) => boolean, + workflowSearchHighlight?: WorkflowSearchTextHighlight | null ) => { return (codeToHighlight: string): string => { const placeholders: CodePlaceholder[] = [] let processedCode = codeToHighlight + const workflowSearchRange = getValidWorkflowSearchRange( + codeToHighlight, + workflowSearchHighlight + ) + + if (workflowSearchRange) { + processedCode = `${codeToHighlight.slice(0, workflowSearchRange.start)}${WORKFLOW_SEARCH_MATCH_PLACEHOLDER}${codeToHighlight.slice(workflowSearchRange.end)}` + } processedCode = processedCode.replace(createEnvVarPattern(), (match) => { const varName = match.slice(2, -2).trim() @@ -144,6 +170,14 @@ const createHighlightFunction = ( } }) + if (workflowSearchRange) { + const matchText = codeToHighlight.slice(workflowSearchRange.start, workflowSearchRange.end) + highlightedCode = highlightedCode.replace( + WORKFLOW_SEARCH_MATCH_PLACEHOLDER, + `${escapeHtml(matchText)}` + ) + } + return highlightedCode } } @@ -178,6 +212,7 @@ interface CodeProps { wandControlRef?: React.MutableRefObject /** Whether to hide the internal wand button (controlled by parent) */ hideInternalWand?: boolean + activeSearchTarget?: ActiveSearchTarget | null } export const Code = memo(function Code({ @@ -197,6 +232,7 @@ export const Code = memo(function Code({ wandConfig, wandControlRef, hideInternalWand = false, + activeSearchTarget, }: CodeProps) { const params = useParams() const workspaceId = params.workspaceId as string @@ -641,11 +677,21 @@ export const Code = memo(function Code({ () => createShouldHighlightEnvVar(availableEnvVars), [availableEnvVars] ) + const workflowSearchHighlight = getActiveWorkflowSearchHighlight({ + activeSearchTarget, + subBlockId, + valuePath: [], + }) const highlightCode = useMemo( () => - createHighlightFunction(effectiveLanguage, shouldHighlightReference, shouldHighlightEnvVar), - [effectiveLanguage, shouldHighlightReference, shouldHighlightEnvVar] + createHighlightFunction( + effectiveLanguage, + shouldHighlightReference, + shouldHighlightEnvVar, + workflowSearchHighlight + ), + [effectiveLanguage, shouldHighlightReference, shouldHighlightEnvVar, workflowSearchHighlight] ) const handleValueChange = useCallback( diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx index 51a1b1b40dc..e802667aa4b 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/combobox/combobox.tsx @@ -8,6 +8,7 @@ import { cn } from '@/lib/core/utils/cn' import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/subblocks/visibility' import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text' import { SubBlockInputController } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sub-block-input-controller' +import { getWorkflowSearchLabelHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes' import { getBlock } from '@/blocks/registry' @@ -15,6 +16,7 @@ import type { SubBlockConfig } from '@/blocks/types' import { getDependsOnFields } from '@/blocks/utils' import { usePermissionConfig } from '@/hooks/use-permission-config' import { getProviderFromModel } from '@/providers/utils' +import type { ActiveSearchTarget } from '@/stores/panel/editor/store' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useSubBlockStore } from '@/stores/workflows/subblock/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' @@ -68,6 +70,7 @@ interface ComboBoxProps { ) => Promise<{ label: string; id: string } | null> /** Field dependencies that trigger option refetch when changed */ dependsOn?: SubBlockConfig['dependsOn'] + activeSearchTarget?: ActiveSearchTarget | null } export const ComboBox = memo(function ComboBox({ @@ -84,6 +87,7 @@ export const ComboBox = memo(function ComboBox({ fetchOptions, fetchOptionById, dependsOn, + activeSearchTarget, }: ComboBoxProps) { // Hooks and context const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlockId) @@ -449,6 +453,13 @@ export const ComboBox = memo(function ComboBox({ const overlayContent = useMemo(() => { const SelectedIcon = selectedOptionIcon const displayLabel = inputValue + const workflowSearchHighlight = getWorkflowSearchLabelHighlight({ + activeSearchTarget, + blockId, + subBlockId, + valuePath: [], + label: displayLabel, + }) return (
{SelectedIcon && } @@ -456,11 +467,12 @@ export const ComboBox = memo(function ComboBox({ {formatDisplayText(displayLabel, { accessiblePrefixes, highlightAll: !accessiblePrefixes, + workflowSearchHighlight, })}
) - }, [inputValue, accessiblePrefixes, selectedOption, selectedOptionIcon]) + }, [activeSearchTarget, blockId, inputValue, accessiblePrefixes, selectedOptionIcon, subBlockId]) const ctrlOnChangeRef = useRef< ((e: React.ChangeEvent) => void) | null diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/condition-input/condition-input.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/condition-input/condition-input.tsx index b6e173949bb..edcebec5324 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/condition-input/condition-input.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/condition-input/condition-input.tsx @@ -21,14 +21,21 @@ import { SYSTEM_REFERENCE_PREFIXES, splitReferenceSegment, } from '@/lib/workflows/sanitization/references' +import { WORKFLOW_SEARCH_HIGHLIGHT_CLASS } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/constants' import { checkEnvVarTrigger, EnvVarDropdown, } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/env-var-dropdown' +import { + formatDisplayText, + getValidWorkflowSearchRange, + type WorkflowSearchTextHighlight, +} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text' import { checkTagTrigger, TagDropdown, } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown' +import { getActiveWorkflowSearchHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight' import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value' import { restoreCursorAfterInsertion } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/utils' import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes' @@ -36,6 +43,7 @@ import { normalizeName } from '@/executor/constants' import { createEnvVarPattern, createReferencePattern } from '@/executor/utils/reference-validation' import { useTagSelection } from '@/hooks/kb/use-tag-selection' import { createShouldHighlightEnvVar, useAvailableEnvVarKeys } from '@/hooks/use-available-env-vars' +import type { ActiveSearchTarget } from '@/stores/panel/editor/store' import { useWorkflowStore } from '@/stores/workflows/workflow/store' const logger = createLogger('ConditionInput') @@ -49,6 +57,15 @@ const ROUTER_DEFAULT_HEIGHT_PX = 100 * Minimum height for router textareas in pixels */ const ROUTER_MIN_HEIGHT_PX = 80 +const WORKFLOW_SEARCH_MATCH_PLACEHOLDER = '__WORKFLOW_SEARCH_MATCH__' + +const escapeHtml = (value: string): string => + value + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", ''') /** * Represents a single conditional block (if/else if/else). @@ -88,6 +105,7 @@ interface ConditionInputProps { disabled?: boolean /** Mode: 'condition' for code editor, 'router' for text input */ mode?: 'condition' | 'router' + activeSearchTarget?: ActiveSearchTarget | null } /** @@ -116,6 +134,7 @@ export function ConditionInput({ previewValue, disabled = false, mode = 'condition', + activeSearchTarget, }: ConditionInputProps) { const isRouterMode = mode === 'router' const params = useParams() @@ -132,6 +151,7 @@ export function ConditionInput({ const containerRef = useRef(null) const inputRefs = useRef>(new Map()) + const overlayRefs = useRef>(new Map()) /** * Determines if a reference string should be highlighted in the editor. @@ -169,6 +189,68 @@ export function ConditionInput({ return accessiblePrefixes.has(normalizedPrefix) } + + const createHighlightFunction = ( + workflowSearchHighlight?: WorkflowSearchTextHighlight | null + ) => { + return (codeToHighlight: string) => { + const placeholders: { + placeholder: string + original: string + type: 'var' | 'env' + shouldHighlight: boolean + }[] = [] + let processedCode = codeToHighlight + const workflowSearchRange = getValidWorkflowSearchRange( + codeToHighlight, + workflowSearchHighlight + ) + + if (workflowSearchRange) { + processedCode = `${codeToHighlight.slice(0, workflowSearchRange.start)}${WORKFLOW_SEARCH_MATCH_PLACEHOLDER}${codeToHighlight.slice(workflowSearchRange.end)}` + } + + processedCode = processedCode.replace(createEnvVarPattern(), (match) => { + const varName = match.slice(2, -2).trim() + if (shouldHighlightEnvVar(varName)) { + const placeholder = `__ENV_VAR_${placeholders.length}__` + placeholders.push({ placeholder, original: match, type: 'env', shouldHighlight: true }) + return placeholder + } + return match + }) + + processedCode = processedCode.replace(createReferencePattern(), (match) => { + const shouldHighlight = shouldHighlightReference(match) + if (shouldHighlight) { + const placeholder = `__VAR_REF_${placeholders.length}__` + placeholders.push({ placeholder, original: match, type: 'var', shouldHighlight: true }) + return placeholder + } + return match + }) + + let highlightedCode = highlight(processedCode, languages.javascript, 'javascript') + + placeholders.forEach(({ placeholder, original, type, shouldHighlight }) => { + if (!shouldHighlight) return + + highlightedCode = highlightedCode.replace( + placeholder, + `${type === 'env' ? original : escapeHtml(original)}` + ) + }) + + if (workflowSearchRange) { + highlightedCode = highlightedCode.replace( + WORKFLOW_SEARCH_MATCH_PLACEHOLDER, + `${escapeHtml(codeToHighlight.slice(workflowSearchRange.start, workflowSearchRange.end))}` + ) + } + + return highlightedCode + } + } const [visualLineHeights, setVisualLineHeights] = useState<{ [key: string]: number[] }>({}) @@ -819,9 +901,13 @@ export function ConditionInput({ // Update the textarea height directly for smooth resizing const textarea = inputRefs.current.get(blockId) + const overlay = overlayRefs.current.get(blockId) if (textarea) { textarea.style.height = `${newHeight}px` } + if (overlay) { + overlay.style.height = `${newHeight}px` + } // Update state to keep track setRouterHeights((prev) => ({ ...prev, [blockId]: newHeight })) @@ -848,448 +934,425 @@ export function ConditionInput({ return (
- {conditionalBlocks.map((block, index) => ( -
+ {conditionalBlocks.map((block, index) => { + const workflowSearchHighlight = getActiveWorkflowSearchHighlight({ + activeSearchTarget, + blockId, + subBlockId, + valuePath: [index, 'value'], + }) + return (
- - {isRouterMode ? `Route ${index + 1}` : block.title} - -
- - - - - Add Block - - - - - - - Move Up - - - - - - - Move Down - - - - - - - - {isRouterMode ? 'Delete Route' : 'Delete Condition'} - - -
-
- {/* Router mode: show description textarea with tag/env var support */} - {isRouterMode && (
e.preventDefault()} - onDrop={(e) => handleDrop(block.id, e)} + className={cn( + 'flex items-center justify-between overflow-hidden bg-transparent px-2.5 py-[5px]', + isRouterMode + ? 'rounded-t-[4px] border-[var(--border-1)] border-b' + : block.title === 'else' + ? 'rounded-sm border-0' + : 'rounded-t-[4px] border-[var(--border-1)] border-b' + )} > -