Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
getCodeEditorProps,
highlight,
languages,
Textarea,
Tooltip,
} from '@sim/emcn'
import { ChevronDown, ChevronsUpDown, ChevronUp, Plus, Trash } from '@sim/emcn/icons'
Expand All @@ -31,6 +30,7 @@ import {
getValidWorkflowSearchRange,
type WorkflowSearchTextHighlight,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
import { MirroredTextarea } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mirrored-field/mirrored-field'
import {
checkTagTrigger,
TagDropdown,
Expand Down Expand Up @@ -1044,7 +1044,7 @@ export function ConditionInput({
onDragOver={(e) => e.preventDefault()}
onDrop={(e) => handleDrop(block.id, e)}
>
<Textarea
<MirroredTextarea
ref={(el) => {
if (el) inputRefs.current.set(block.id, el)
}}
Expand Down Expand Up @@ -1093,43 +1093,26 @@ export function ConditionInput({
)
}, 150)
}}
onScroll={(e) => {
const overlay = overlayRefs.current.get(block.id)
if (overlay) {
overlay.scrollTop = e.currentTarget.scrollTop
overlay.scrollLeft = e.currentTarget.scrollLeft
}
}}
placeholder='Describe when this route should be taken...'
disabled={disabled || isPreview}
className='min-h-[100px] resize-none rounded-none border-0 px-3 py-2 text-sm text-transparent caret-foreground [letter-spacing:inherit] placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
className='min-h-[100px] resize-none rounded-none border-0 px-3 py-2 text-sm placeholder:text-muted-foreground/50 focus-visible:ring-0 focus-visible:ring-offset-0'
rows={4}
style={{ height: `${getRouterHeight(block.id)}px` }}
/>
<div
ref={(el) => {
if (el) {
overlayRefs.current.set(block.id, el)
} else {
overlayRefs.current.delete(block.id)
}
overlayRef={(el) => {
if (el) overlayRefs.current.set(block.id, el)
else overlayRefs.current.delete(block.id)
}}
className={cn(
'pointer-events-none absolute inset-0 box-border overflow-auto whitespace-pre-wrap break-words border border-transparent bg-transparent px-3 py-2 font-sans text-sm',
overlayClassName={cn(
'pointer-events-none absolute inset-0 box-border overflow-auto whitespace-pre-wrap break-words border border-transparent bg-transparent px-3 py-2 text-sm [font-family:inherit] [line-height:inherit]',
(isPreview || disabled) && 'opacity-50'
)}
style={{
fontFamily: 'inherit',
lineHeight: 'inherit',
height: `${getRouterHeight(block.id)}px`,
}}
>
{formatDisplayText(block.value, {
overlayStyle={{ height: `${getRouterHeight(block.id)}px` }}
overlay={formatDisplayText(block.value, {
accessiblePrefixes,
highlightAll: !accessiblePrefixes,
workflowSearchHighlight,
})}
</div>
/>

{/* Custom resize handle */}
{!isPreview && !disabled && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Combobox,
type ComboboxOption,
cn,
Input,
Label,
OverflowText,
Trash,
Expand All @@ -17,6 +16,7 @@ import { Plus } from '@sim/emcn/icons'
import { generateId } from '@sim/utils/id'
import { FIELD_TYPE_LABELS, getPlaceholderForFieldType } from '@/lib/knowledge/constants'
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
import { MirroredInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mirrored-field/mirrored-field'
import { 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 { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
Expand Down Expand Up @@ -203,11 +203,6 @@ export function DocumentTagEntry({
/**
* Syncs scroll position between input and overlay
*/
const syncOverlayScroll = (tagId: string, scrollLeft: number) => {
const overlay = overlayRefs.current[tagId]
if (overlay) overlay.scrollLeft = scrollLeft
}

if (isPreview) {
const tagCount = tags.filter((t) => t.tagName?.trim()).length
return (
Expand Down Expand Up @@ -301,7 +296,7 @@ export function DocumentTagEntry({

return (
<div className='relative'>
<Input
<MirroredInput
ref={(el) => {
if (el) valueInputRefs.current[cellKey] = el
}}
Expand All @@ -311,36 +306,28 @@ export function DocumentTagEntry({
onDrop={handlers.onDrop}
onDragOver={handlers.onDragOver}
onFocus={handlers.onFocus}
onScroll={(e) => syncOverlayScroll(cellKey, e.currentTarget.scrollLeft)}
onPaste={() =>
setTimeout(() => {
const input = valueInputRefs.current[cellKey]
input && syncOverlayScroll(cellKey, input.scrollLeft)
}, 0)
}
disabled={isReadOnly}
autoComplete='off'
placeholder={placeholder}
className='allow-scroll w-full overflow-auto text-transparent caret-foreground [letter-spacing:inherit]'
/>
<div
ref={(el) => {
className='allow-scroll w-full overflow-auto'
overlayRef={(el) => {
if (el) overlayRefs.current[cellKey] = el
}}
className={cn(
overlayClassName={cn(
'absolute inset-0 flex items-center overflow-x-auto bg-transparent px-2 py-1.5 font-sans text-sm',
!isReadOnly && 'pointer-events-none'
)}
>
<div className='w-full whitespace-pre' style={{ minWidth: 'fit-content' }}>
{formatDisplayText(
fieldValue,
accessiblePrefixes
? { accessiblePrefixes, workflowSearchHighlight }
: { highlightAll: true, workflowSearchHighlight }
)}
</div>
</div>
overlay={
<div className='w-full whitespace-pre' style={{ minWidth: 'fit-content' }}>
{formatDisplayText(
fieldValue,
accessiblePrefixes
? { accessiblePrefixes, workflowSearchHighlight }
: { highlightAll: true, workflowSearchHighlight }
)}
</div>
}
/>
{fieldState.showTags && (
<TagDropdown
visible={fieldState.showTags}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { useMemo, useRef } from 'react'
import { Button, cn, Input, Label, Textarea, Tooltip } from '@sim/emcn'
import { Button, cn, Label, Tooltip } from '@sim/emcn'
import { Plus, Trash } from '@sim/emcn/icons'
import { generateId } from '@sim/utils/id'
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
import {
MirroredInput,
MirroredTextarea,
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/mirrored-field/mirrored-field'
import { 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 { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
Expand Down Expand Up @@ -47,7 +51,6 @@ export function EvalInput({
const [storeValue, setStoreValue] = useSubBlockValue<EvalMetric[]>(blockId, subBlockId)
const accessiblePrefixes = useAccessibleReferencePrefixes(blockId)
const descriptionInputRefs = useRef<Record<string, HTMLTextAreaElement>>({})
const descriptionOverlayRefs = useRef<Record<string, HTMLDivElement>>({})

// Use the extended hook for field-level management
const inputController = useSubBlockInput({
Expand Down Expand Up @@ -188,28 +191,27 @@ export function EvalInput({
<div key={`name-${metric.id}`} className='flex flex-col gap-1.5'>
{renderFieldLabel('Name')}
<div className='relative'>
<Input
<MirroredInput
name='name'
value={metric.name}
onChange={(e) => updateMetric(metric.id, 'name', e.target.value)}
placeholder='Accuracy'
disabled={isPreview || disabled}
className='text-transparent caret-foreground [letter-spacing:inherit] placeholder:text-muted-foreground/50'
/>
<div
className={cn(
className='placeholder:text-muted-foreground/50'
overlayClassName={cn(
'pointer-events-none absolute inset-0 flex items-center overflow-hidden px-3 text-sm',
(isPreview || disabled) && 'opacity-50'
)}
>
<span className='truncate'>
{formatDisplayText(metric.name || '', {
accessiblePrefixes,
highlightAll: !accessiblePrefixes,
workflowSearchHighlight: getMetricSearchHighlight(index, ['name']),
})}
</span>
</div>
overlay={
<span className='truncate'>
{formatDisplayText(metric.name || '', {
accessiblePrefixes,
highlightAll: !accessiblePrefixes,
workflowSearchHighlight: getMetricSearchHighlight(index, ['name']),
})}
</span>
}
/>
</div>
</div>

Expand All @@ -231,7 +233,7 @@ export function EvalInput({

return (
<>
<Textarea
<MirroredTextarea
ref={(el) => {
if (el) descriptionInputRefs.current[metric.id] = el
}}
Expand All @@ -243,30 +245,24 @@ export function EvalInput({
onFocus={handlers.onFocus}
placeholder='How accurate is the response?'
disabled={isPreview || disabled}
className={cn(
'min-h-[80px] whitespace-pre-wrap text-transparent caret-foreground [letter-spacing:inherit]'
)}
className='min-h-[80px] whitespace-pre-wrap'
rows={3}
/>
<div
ref={(el) => {
if (el) descriptionOverlayRefs.current[metric.id] = el
}}
className={cn(
overlayClassName={cn(
'absolute inset-0 overflow-auto bg-transparent px-2 py-2 font-sans text-[var(--code-foreground)] text-sm',
!(isPreview || disabled) && 'pointer-events-none'
)}
>
<div className='whitespace-pre-wrap'>
{formatDisplayText(metric.description || '', {
accessiblePrefixes,
highlightAll: !accessiblePrefixes,
workflowSearchHighlight: getMetricSearchHighlight(index, [
'description',
]),
})}
</div>
</div>
overlay={
<div className='whitespace-pre-wrap'>
{formatDisplayText(metric.description || '', {
accessiblePrefixes,
highlightAll: !accessiblePrefixes,
workflowSearchHighlight: getMetricSearchHighlight(index, [
'description',
]),
})}
</div>
}
/>
{fieldState.showTags && (
<TagDropdown
visible={fieldState.showTags}
Expand All @@ -291,7 +287,7 @@ export function EvalInput({
<div className='flex flex-col gap-1.5'>
{renderFieldLabel('Min Value')}
<div className='relative'>
<Input
<MirroredInput
type='text'
value={metric.range.min ?? ''}
onChange={(e) => updateRange(metric.id, 'min', e.target.value)}
Expand All @@ -300,19 +296,17 @@ export function EvalInput({
autoComplete='off'
data-form-type='other'
name='eval-range-min'
className='text-transparent caret-foreground [letter-spacing:inherit]'
/>
<div className='pointer-events-none absolute inset-0 flex items-center truncate px-2 py-1.5 font-sans text-sm'>
{formatDisplayText(String(metric.range.min ?? ''), {
overlayClassName='pointer-events-none absolute inset-0 flex items-center truncate px-2 py-1.5 font-sans text-sm'
overlay={formatDisplayText(String(metric.range.min ?? ''), {
workflowSearchHighlight: getMetricSearchHighlight(index, ['range', 'min']),
})}
</div>
/>
</div>
</div>
<div className='flex flex-col gap-1.5'>
{renderFieldLabel('Max Value')}
<div className='relative'>
<Input
<MirroredInput
type='text'
value={metric.range.max ?? ''}
onChange={(e) => updateRange(metric.id, 'max', e.target.value)}
Expand All @@ -321,13 +315,11 @@ export function EvalInput({
autoComplete='off'
data-form-type='other'
name='eval-range-max'
className='text-transparent caret-foreground [letter-spacing:inherit]'
/>
<div className='pointer-events-none absolute inset-0 flex items-center truncate px-2 py-1.5 font-sans text-sm'>
{formatDisplayText(String(metric.range.max ?? ''), {
overlayClassName='pointer-events-none absolute inset-0 flex items-center truncate px-2 py-1.5 font-sans text-sm'
overlay={formatDisplayText(String(metric.range.max ?? ''), {
workflowSearchHighlight: getMetricSearchHighlight(index, ['range', 'max']),
})}
</div>
/>
</div>
</div>
</div>
Expand Down
Loading
Loading