Skip to content

Commit 41799e7

Browse files
committed
subblock sweep
1 parent 837f035 commit 41799e7

9 files changed

Lines changed: 1222 additions & 18 deletions

File tree

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/eval-input/eval-input.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/compon
1010
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
1111
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
1212
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
13+
import type { ActiveSearchTarget } from '@/stores/panel/editor/store'
1314

1415
interface EvalMetric {
1516
id: string
@@ -27,8 +28,12 @@ interface EvalInputProps {
2728
isPreview?: boolean
2829
previewValue?: EvalMetric[] | null
2930
disabled?: boolean
31+
activeSearchTarget?: ActiveSearchTarget | null
3032
}
3133

34+
const WORKFLOW_SEARCH_HIGHLIGHT_CLASS =
35+
'rounded-sm bg-orange-400 shadow-[3px_0_0_#fb923c,-3px_0_0_#fb923c]'
36+
3237
// Default values
3338
const createDefaultMetric = (): EvalMetric => ({
3439
id: generateId(),
@@ -43,6 +48,7 @@ export function EvalInput({
4348
isPreview = false,
4449
previewValue,
4550
disabled = false,
51+
activeSearchTarget,
4652
}: EvalInputProps) {
4753
const [storeValue, setStoreValue] = useSubBlockValue<EvalMetric[]>(blockId, subBlockId)
4854
const accessiblePrefixes = useAccessibleReferencePrefixes(blockId)
@@ -67,6 +73,17 @@ export function EvalInput({
6773
const defaultMetric = useMemo(() => createDefaultMetric(), [])
6874
const metrics: EvalMetric[] = value || [defaultMetric]
6975

76+
const isNestedSearchHighlighted = (metricIndex: number, metricPath: Array<string | number>) =>
77+
activeSearchTarget?.subBlockId === subBlockId &&
78+
activeSearchTarget.valuePath[0] === metricIndex &&
79+
metricPath.every((segment, index) => activeSearchTarget.valuePath[index + 1] === segment)
80+
81+
const renderFieldLabel = (label: string, highlighted: boolean) => (
82+
<Label className='text-small'>
83+
{highlighted ? <mark className={WORKFLOW_SEARCH_HIGHLIGHT_CLASS}>{label}</mark> : label}
84+
</Label>
85+
)
86+
7087
const addMetric = () => {
7188
if (isPreview || disabled) return
7289

@@ -176,7 +193,7 @@ export function EvalInput({
176193

177194
<div className='flex flex-col gap-2 border-[var(--border-1)] px-2.5 pt-1.5 pb-2.5'>
178195
<div key={`name-${metric.id}`} className='flex flex-col gap-1.5'>
179-
<Label className='text-small'>Name</Label>
196+
{renderFieldLabel('Name', isNestedSearchHighlighted(index, ['name']))}
180197
<Input
181198
name='name'
182199
value={metric.name}
@@ -187,7 +204,7 @@ export function EvalInput({
187204
</div>
188205

189206
<div key={`description-${metric.id}`} className='flex flex-col gap-1.5'>
190-
<Label className='text-small'>Description</Label>
207+
{renderFieldLabel('Description', isNestedSearchHighlighted(index, ['description']))}
191208
<div className='relative'>
192209
{(() => {
193210
const fieldState = inputController.fieldHelpers.getFieldState(metric.id)
@@ -259,7 +276,7 @@ export function EvalInput({
259276

260277
<div key={`range-${metric.id}`} className='grid grid-cols-2 gap-2'>
261278
<div className='flex flex-col gap-1.5'>
262-
<Label className='text-small'>Min Value</Label>
279+
{renderFieldLabel('Min Value', isNestedSearchHighlighted(index, ['range', 'min']))}
263280
<Input
264281
type='text'
265282
value={metric.range.min}
@@ -272,7 +289,7 @@ export function EvalInput({
272289
/>
273290
</div>
274291
<div className='flex flex-col gap-1.5'>
275-
<Label className='text-small'>Max Value</Label>
292+
{renderFieldLabel('Max Value', isNestedSearchHighlighted(index, ['range', 'max']))}
276293
<Input
277294
type='text'
278295
value={metric.range.max}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/starter/input-format.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/compon
2525
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
2626
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
2727
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
28+
import type { ActiveSearchTarget } from '@/stores/panel/editor/store'
2829

2930
interface Field {
3031
id: string
@@ -49,8 +50,12 @@ interface FieldFormatProps {
4950
valuePlaceholder?: string
5051
descriptionPlaceholder?: string
5152
config?: any
53+
activeSearchTarget?: ActiveSearchTarget | null
5254
}
5355

56+
const WORKFLOW_SEARCH_HIGHLIGHT_CLASS =
57+
'rounded-sm bg-orange-400 shadow-[3px_0_0_#fb923c,-3px_0_0_#fb923c]'
58+
5459
/**
5560
* Type options for field type selection
5661
*/
@@ -103,6 +108,7 @@ export function FieldFormat({
103108
showDescription = false,
104109
valuePlaceholder = 'Enter default value',
105110
descriptionPlaceholder = 'Describe this field',
111+
activeSearchTarget,
106112
}: FieldFormatProps) {
107113
const [storeValue, setStoreValue] = useSubBlockValue<Field[]>(blockId, subBlockId)
108114
const valueInputRefs = useRef<Record<string, HTMLInputElement | HTMLTextAreaElement>>({})
@@ -127,6 +133,17 @@ export function FieldFormat({
127133
const fields: Field[] = Array.isArray(value) && value.length > 0 ? value : [createDefaultField()]
128134
const isReadOnly = isPreview || disabled
129135

136+
const isNestedSearchHighlighted = (fieldIndex: number, fieldKey: keyof Field) =>
137+
activeSearchTarget?.subBlockId === subBlockId &&
138+
activeSearchTarget.valuePath[0] === fieldIndex &&
139+
activeSearchTarget.valuePath.at(-1) === fieldKey
140+
141+
const renderFieldLabel = (label: string, highlighted: boolean) => (
142+
<Label className='text-small'>
143+
{highlighted ? <mark className={WORKFLOW_SEARCH_HIGHLIGHT_CLASS}>{label}</mark> : label}
144+
</Label>
145+
)
146+
130147
/**
131148
* Adds a new field to the list
132149
*/
@@ -555,13 +572,13 @@ export function FieldFormat({
555572
<ExpandableContent>
556573
<div className='flex flex-col gap-2 rounded-b-[4px] border-[var(--border-1)] border-t bg-[var(--surface-2)] px-2.5 pt-1.5 pb-2.5'>
557574
<div className='flex flex-col gap-1.5'>
558-
<Label className='text-small'>Name</Label>
575+
{renderFieldLabel('Name', isNestedSearchHighlighted(index, 'name'))}
559576
<div className='relative'>{renderNameInput(field)}</div>
560577
</div>
561578

562579
{showType && (
563580
<div className='flex flex-col gap-1.5'>
564-
<Label className='text-small'>Type</Label>
581+
{renderFieldLabel('Type', isNestedSearchHighlighted(index, 'type'))}
565582
<Combobox
566583
options={TYPE_OPTIONS}
567584
value={field.type}
@@ -573,7 +590,10 @@ export function FieldFormat({
573590

574591
{showDescription && (
575592
<div className='flex flex-col gap-1.5'>
576-
<Label className='text-small'>Description</Label>
593+
{renderFieldLabel(
594+
'Description',
595+
isNestedSearchHighlighted(index, 'description')
596+
)}
577597
<Input
578598
value={field.description ?? ''}
579599
onChange={(e) => updateField(field.id, 'description', e.target.value)}
@@ -585,7 +605,7 @@ export function FieldFormat({
585605

586606
{showValue && (
587607
<div className='flex flex-col gap-1.5'>
588-
<Label className='text-small'>Value</Label>
608+
{renderFieldLabel('Value', isNestedSearchHighlighted(index, 'value'))}
589609
<div className='relative'>{renderValueInput(field)}</div>
590610
</div>
591611
)}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import { MODAL_REGISTRY } from '@/app/workspace/[workspaceId]/w/[workflowId]/com
5454
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
5555
import type { SubBlockConfig } from '@/blocks/types'
5656
import { useWebhookManagement } from '@/hooks/use-webhook-management'
57+
import type { ActiveSearchTarget } from '@/stores/panel/editor/store'
5758

5859
const SLACK_OVERRIDES: SelectorOverrides = {
5960
transformContext: (context, deps) => {
@@ -75,6 +76,18 @@ const FOLDER_OVERRIDES: SelectorOverrides = {
7576
const WORKFLOW_SEARCH_HIGHLIGHT_CLASS =
7677
'rounded-sm bg-orange-400 shadow-[3px_0_0_#fb923c,-3px_0_0_#fb923c]'
7778

79+
function hasNestedWorkflowSearchHighlight(
80+
config: SubBlockConfig,
81+
activeSearchTarget?: ActiveSearchTarget | null
82+
) {
83+
if (!activeSearchTarget || activeSearchTarget.valuePath.length === 0) return false
84+
return (
85+
config.type === 'input-format' ||
86+
config.type === 'response-format' ||
87+
config.type === 'eval-input'
88+
)
89+
}
90+
7891
/**
7992
* Interface for wand control handlers exposed by sub-block inputs
8093
*/
@@ -107,6 +120,7 @@ interface SubBlockProps {
107120
/** Provides sibling values for dependency resolution in non-preview contexts (e.g. tool-input) */
108121
dependencyContext?: Record<string, unknown>
109122
isSearchHighlighted?: boolean
123+
activeSearchTarget?: ActiveSearchTarget | null
110124
}
111125

112126
/**
@@ -446,6 +460,7 @@ const arePropsEqual = (prevProps: SubBlockProps, nextProps: SubBlockProps): bool
446460
canonicalToggleEqual &&
447461
prevProps.labelSuffix === nextProps.labelSuffix &&
448462
prevProps.isSearchHighlighted === nextProps.isSearchHighlighted &&
463+
prevProps.activeSearchTarget === nextProps.activeSearchTarget &&
449464
prevProps.dependencyContext === nextProps.dependencyContext
450465
)
451466
}
@@ -463,6 +478,7 @@ const arePropsEqual = (prevProps: SubBlockProps, nextProps: SubBlockProps): bool
463478
* @param labelSuffix - Additional content rendered after the label text
464479
* @param dependencyContext - Sibling values for dependency resolution in non-preview contexts (e.g. tool-input)
465480
* @param isSearchHighlighted - Whether workflow search should highlight this field
481+
* @param activeSearchTarget - Active workflow search target for nested field highlighting
466482
*/
467483
function SubBlockComponent({
468484
blockId,
@@ -475,6 +491,7 @@ function SubBlockComponent({
475491
labelSuffix,
476492
dependencyContext,
477493
isSearchHighlighted,
494+
activeSearchTarget,
478495
}: SubBlockProps): JSX.Element {
479496
const params = useParams()
480497
const workspaceId = params.workspaceId as string
@@ -887,6 +904,7 @@ function SubBlockComponent({
887904
isPreview={isPreview}
888905
previewValue={previewValue as any}
889906
disabled={isDisabled}
907+
activeSearchTarget={activeSearchTarget}
890908
/>
891909
)
892910

@@ -1015,6 +1033,7 @@ function SubBlockComponent({
10151033
disabled={isDisabled}
10161034
config={config}
10171035
showValue={true}
1036+
activeSearchTarget={activeSearchTarget}
10181037
/>
10191038
)
10201039

@@ -1050,6 +1069,7 @@ function SubBlockComponent({
10501069
previewValue={previewValue}
10511070
config={config}
10521071
disabled={isDisabled}
1072+
activeSearchTarget={activeSearchTarget}
10531073
/>
10541074
)
10551075

@@ -1176,6 +1196,9 @@ function SubBlockComponent({
11761196
}
11771197
}
11781198

1199+
const highlightParentLabel =
1200+
isSearchHighlighted && !hasNestedWorkflowSearchHighlight(config, activeSearchTarget)
1201+
11791202
return (
11801203
<div
11811204
onMouseDown={handleMouseDown}
@@ -1209,7 +1232,7 @@ function SubBlockComponent({
12091232
onCopy: handleCopy,
12101233
},
12111234
labelSuffix,
1212-
isSearchHighlighted,
1235+
highlightParentLabel,
12131236
externalLink
12141237
)}
12151238
{renderInput()}

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/editor.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ export function Editor() {
625625
activeSearchTarget.canonicalSubBlockId ===
626626
(subBlock.canonicalParamId ?? subBlock.id))
627627
}
628+
activeSearchTarget={activeSearchTarget}
628629
canonicalToggle={
629630
isCanonicalSwap && canonicalMode && canonicalId
630631
? {
@@ -699,6 +700,7 @@ export function Editor() {
699700
activeSearchTarget.canonicalSubBlockId ===
700701
(subBlock.canonicalParamId ?? subBlock.id))
701702
}
703+
activeSearchTarget={activeSearchTarget}
702704
/>
703705
{index < advancedOnlySubBlocks.length - 1 && (
704706
<FieldDivider subblockMarker />

0 commit comments

Comments
 (0)