Skip to content

Commit 68b6c03

Browse files
committed
improvement(search-replace): pass down to subblocks:
1 parent 4002242 commit 68b6c03

56 files changed

Lines changed: 3151 additions & 802 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
export const WORKFLOW_SEARCH_HIGHLIGHT_CLASS =
2-
'rounded-sm bg-orange-400 shadow-[3px_0_0_#fb923c,-3px_0_0_#fb923c]'
1+
export const WORKFLOW_SEARCH_HIGHLIGHT_CLASS = 'rounded-sm bg-orange-400 font-normal text-inherit'

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

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { Info } from 'lucide-react'
22
import { Checkbox, Label, Tooltip } from '@/components/emcn'
3+
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
4+
import { getWorkflowSearchLabelHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight'
35
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
6+
import type { ActiveSearchTarget } from '@/stores/panel/editor/store'
47

58
interface CheckboxListOption {
69
label: string
@@ -11,18 +14,23 @@ interface CheckboxListOption {
1114

1215
interface CheckboxListProps {
1316
blockId: string
17+
subBlockId: string
1418
options: CheckboxListOption[]
1519
isPreview?: boolean
1620
subBlockValues?: Record<string, any>
1721
disabled?: boolean
22+
activeSearchTarget?: ActiveSearchTarget | null
1823
}
1924

2025
interface CheckboxItemProps {
2126
blockId: string
27+
subBlockId: string
2228
option: CheckboxListOption
29+
index: number
2330
isPreview: boolean
2431
subBlockValues?: Record<string, any>
2532
disabled: boolean
33+
activeSearchTarget?: ActiveSearchTarget | null
2634
}
2735

2836
/**
@@ -33,8 +41,24 @@ interface CheckboxItemProps {
3341
* case we fall back to `option.defaultChecked` for the displayed state. Any
3442
* explicit boolean (including `false`) takes precedence over the default.
3543
*/
36-
function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }: CheckboxItemProps) {
44+
function CheckboxItem({
45+
blockId,
46+
subBlockId,
47+
option,
48+
index,
49+
isPreview,
50+
subBlockValues,
51+
disabled,
52+
activeSearchTarget,
53+
}: CheckboxItemProps) {
3754
const [storeValue, setStoreValue] = useSubBlockValue<boolean>(blockId, option.id)
55+
const workflowSearchHighlight = getWorkflowSearchLabelHighlight({
56+
activeSearchTarget,
57+
blockId,
58+
subBlockId,
59+
valuePath: ['options', index],
60+
label: option.label,
61+
})
3862

3963
const previewValue = isPreview && subBlockValues ? subBlockValues[option.id]?.value : undefined
4064
const rawValue = isPreview ? previewValue : storeValue
@@ -58,7 +82,7 @@ function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }:
5882
htmlFor={`${blockId}-${option.id}`}
5983
className='cursor-pointer font-medium font-sans text-[var(--text-primary)] text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50'
6084
>
61-
{option.label}
85+
{formatDisplayText(option.label, { workflowSearchHighlight })}
6286
</Label>
6387
{option.description && (
6488
<Tooltip.Root>
@@ -76,21 +100,26 @@ function CheckboxItem({ blockId, option, isPreview, subBlockValues, disabled }:
76100

77101
export function CheckboxList({
78102
blockId,
103+
subBlockId,
79104
options,
80105
isPreview = false,
81106
subBlockValues,
82107
disabled = false,
108+
activeSearchTarget,
83109
}: CheckboxListProps) {
84110
return (
85111
<div className='flex flex-col gap-y-2.5 pt-1'>
86-
{options.map((option) => (
112+
{options.map((option, index) => (
87113
<CheckboxItem
88114
key={option.id}
89115
blockId={blockId}
116+
subBlockId={subBlockId}
90117
option={option}
118+
index={index}
91119
isPreview={isPreview}
92120
subBlockValues={subBlockValues}
93121
disabled={disabled}
122+
activeSearchTarget={activeSearchTarget}
94123
/>
95124
))}
96125
</div>

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

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,20 @@ import {
2121
SYSTEM_REFERENCE_PREFIXES,
2222
splitReferenceSegment,
2323
} from '@/lib/workflows/sanitization/references'
24+
import { WORKFLOW_SEARCH_HIGHLIGHT_CLASS } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/constants'
2425
import {
2526
checkEnvVarTrigger,
2627
EnvVarDropdown,
2728
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/env-var-dropdown'
29+
import {
30+
getValidWorkflowSearchRange,
31+
type WorkflowSearchTextHighlight,
32+
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
2833
import {
2934
checkTagTrigger,
3035
TagDropdown,
3136
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
37+
import { getActiveWorkflowSearchHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight'
3238
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
3339
import type { WandControlHandlers } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/sub-block'
3440
import { restoreCursorAfterInsertion } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/utils'
@@ -41,6 +47,7 @@ import { createEnvVarPattern, createReferencePattern } from '@/executor/utils/re
4147
import { useTagSelection } from '@/hooks/kb/use-tag-selection'
4248
import { createShouldHighlightEnvVar, useAvailableEnvVarKeys } from '@/hooks/use-available-env-vars'
4349
import { useCodeUndoRedo } from '@/hooks/use-code-undo-redo'
50+
import type { ActiveSearchTarget } from '@/stores/panel/editor/store'
4451
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
4552

4653
const logger = createLogger('Code')
@@ -80,6 +87,16 @@ const applyDarkModeTokenStyling = (highlightedCode: string): string => {
8087
return highlightedCode
8188
}
8289

90+
const WORKFLOW_SEARCH_MATCH_PLACEHOLDER = '__WORKFLOW_SEARCH_MATCH__'
91+
92+
const escapeHtml = (value: string): string =>
93+
value
94+
.replaceAll('&', '&amp;')
95+
.replaceAll('<', '&lt;')
96+
.replaceAll('>', '&gt;')
97+
.replaceAll('"', '&quot;')
98+
.replaceAll("'", '&#39;')
99+
83100
/**
84101
* Type definition for code placeholders during syntax highlighting.
85102
*/
@@ -99,11 +116,20 @@ interface CodePlaceholder {
99116
const createHighlightFunction = (
100117
effectiveLanguage: 'javascript' | 'python' | 'json',
101118
shouldHighlightReference: (part: string) => boolean,
102-
shouldHighlightEnvVar: (varName: string) => boolean
119+
shouldHighlightEnvVar: (varName: string) => boolean,
120+
workflowSearchHighlight?: WorkflowSearchTextHighlight | null
103121
) => {
104122
return (codeToHighlight: string): string => {
105123
const placeholders: CodePlaceholder[] = []
106124
let processedCode = codeToHighlight
125+
const workflowSearchRange = getValidWorkflowSearchRange(
126+
codeToHighlight,
127+
workflowSearchHighlight
128+
)
129+
130+
if (workflowSearchRange) {
131+
processedCode = `${codeToHighlight.slice(0, workflowSearchRange.start)}${WORKFLOW_SEARCH_MATCH_PLACEHOLDER}${codeToHighlight.slice(workflowSearchRange.end)}`
132+
}
107133

108134
processedCode = processedCode.replace(createEnvVarPattern(), (match) => {
109135
const varName = match.slice(2, -2).trim()
@@ -144,6 +170,14 @@ const createHighlightFunction = (
144170
}
145171
})
146172

173+
if (workflowSearchRange) {
174+
const matchText = codeToHighlight.slice(workflowSearchRange.start, workflowSearchRange.end)
175+
highlightedCode = highlightedCode.replace(
176+
WORKFLOW_SEARCH_MATCH_PLACEHOLDER,
177+
`<mark class="${WORKFLOW_SEARCH_HIGHLIGHT_CLASS}">${escapeHtml(matchText)}</mark>`
178+
)
179+
}
180+
147181
return highlightedCode
148182
}
149183
}
@@ -178,6 +212,7 @@ interface CodeProps {
178212
wandControlRef?: React.MutableRefObject<WandControlHandlers | null>
179213
/** Whether to hide the internal wand button (controlled by parent) */
180214
hideInternalWand?: boolean
215+
activeSearchTarget?: ActiveSearchTarget | null
181216
}
182217

183218
export const Code = memo(function Code({
@@ -197,6 +232,7 @@ export const Code = memo(function Code({
197232
wandConfig,
198233
wandControlRef,
199234
hideInternalWand = false,
235+
activeSearchTarget,
200236
}: CodeProps) {
201237
const params = useParams()
202238
const workspaceId = params.workspaceId as string
@@ -641,11 +677,21 @@ export const Code = memo(function Code({
641677
() => createShouldHighlightEnvVar(availableEnvVars),
642678
[availableEnvVars]
643679
)
680+
const workflowSearchHighlight = getActiveWorkflowSearchHighlight({
681+
activeSearchTarget,
682+
subBlockId,
683+
valuePath: [],
684+
})
644685

645686
const highlightCode = useMemo(
646687
() =>
647-
createHighlightFunction(effectiveLanguage, shouldHighlightReference, shouldHighlightEnvVar),
648-
[effectiveLanguage, shouldHighlightReference, shouldHighlightEnvVar]
688+
createHighlightFunction(
689+
effectiveLanguage,
690+
shouldHighlightReference,
691+
shouldHighlightEnvVar,
692+
workflowSearchHighlight
693+
),
694+
[effectiveLanguage, shouldHighlightReference, shouldHighlightEnvVar, workflowSearchHighlight]
649695
)
650696

651697
const handleValueChange = useCallback(

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import { cn } from '@/lib/core/utils/cn'
88
import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/subblocks/visibility'
99
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
1010
import { SubBlockInputController } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/sub-block-input-controller'
11+
import { getWorkflowSearchLabelHighlight } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/workflow-search-highlight'
1112
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
1213
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
1314
import { getBlock } from '@/blocks/registry'
1415
import type { SubBlockConfig } from '@/blocks/types'
1516
import { getDependsOnFields } from '@/blocks/utils'
1617
import { usePermissionConfig } from '@/hooks/use-permission-config'
1718
import { getProviderFromModel } from '@/providers/utils'
19+
import type { ActiveSearchTarget } from '@/stores/panel/editor/store'
1820
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
1921
import { useSubBlockStore } from '@/stores/workflows/subblock/store'
2022
import { useWorkflowStore } from '@/stores/workflows/workflow/store'
@@ -68,6 +70,7 @@ interface ComboBoxProps {
6870
) => Promise<{ label: string; id: string } | null>
6971
/** Field dependencies that trigger option refetch when changed */
7072
dependsOn?: SubBlockConfig['dependsOn']
73+
activeSearchTarget?: ActiveSearchTarget | null
7174
}
7275

7376
export const ComboBox = memo(function ComboBox({
@@ -84,6 +87,7 @@ export const ComboBox = memo(function ComboBox({
8487
fetchOptions,
8588
fetchOptionById,
8689
dependsOn,
90+
activeSearchTarget,
8791
}: ComboBoxProps) {
8892
// Hooks and context
8993
const [storeValue, setStoreValue] = useSubBlockValue<string>(blockId, subBlockId)
@@ -449,18 +453,26 @@ export const ComboBox = memo(function ComboBox({
449453
const overlayContent = useMemo(() => {
450454
const SelectedIcon = selectedOptionIcon
451455
const displayLabel = inputValue
456+
const workflowSearchHighlight = getWorkflowSearchLabelHighlight({
457+
activeSearchTarget,
458+
blockId,
459+
subBlockId,
460+
valuePath: [],
461+
label: displayLabel,
462+
})
452463
return (
453464
<div className='flex w-full items-center truncate [scrollbar-width:none]'>
454465
{SelectedIcon && <SelectedIcon className='mr-2 size-3 flex-shrink-0' />}
455466
<div className='truncate'>
456467
{formatDisplayText(displayLabel, {
457468
accessiblePrefixes,
458469
highlightAll: !accessiblePrefixes,
470+
workflowSearchHighlight,
459471
})}
460472
</div>
461473
</div>
462474
)
463-
}, [inputValue, accessiblePrefixes, selectedOption, selectedOptionIcon])
475+
}, [activeSearchTarget, blockId, inputValue, accessiblePrefixes, selectedOptionIcon, subBlockId])
464476

465477
const ctrlOnChangeRef = useRef<
466478
((e: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => void) | null

0 commit comments

Comments
 (0)