| 528 | |
| 529 | // Helper function to detect and render variables in input value (for URL only) |
| 530 | const _renderUrlVariables = (value, onVariableClick, size = "md") => { |
| 531 | if (!value) return null; |
| 532 | |
| 533 | const variableRegex = /\{\{([^}]+)\}\}/g; |
| 534 | const parts = []; |
| 535 | let lastIndex = 0; |
| 536 | let match; |
| 537 | |
| 538 | while ((match = variableRegex.exec(value)) !== null) { |
| 539 | // Add text before the variable |
| 540 | if (match.index > lastIndex) { |
| 541 | parts.push(value.substring(lastIndex, match.index)); |
| 542 | } |
| 543 | |
| 544 | // Add the variable as a clickable chip |
| 545 | parts.push({ |
| 546 | type: "variable", |
| 547 | variable: match[1].trim(), |
| 548 | placeholder: match[0], |
| 549 | index: match.index |
| 550 | }); |
| 551 | |
| 552 | lastIndex = match.index + match[0].length; |
| 553 | } |
| 554 | |
| 555 | // Add remaining text |
| 556 | if (lastIndex < value.length) { |
| 557 | parts.push(value.substring(lastIndex)); |
| 558 | } |
| 559 | |
| 560 | return parts.map((part, index) => { |
| 561 | if (typeof part === "string") { |
| 562 | return <span key={index}>{part}</span>; |
| 563 | } else if (part.type === "variable") { |
| 564 | return ( |
| 565 | <Chip |
| 566 | key={index} |
| 567 | variant="soft" |
| 568 | color="accent" |
| 569 | size="sm" |
| 570 | className={`cursor-pointer mx-1 ${size === "sm" ? "text-xs" : ""}`} |
| 571 | onClick={() => onVariableClick(part)} |
| 572 | > |
| 573 | {part.placeholder} |
| 574 | </Chip> |
| 575 | ); |
| 576 | } |
| 577 | return null; |
| 578 | }); |
| 579 | }; |
| 580 | |
| 581 | const blockMenuSwitch = saveLoading || requestLoading; |
| 582 | |