File size: 2,532 Bytes
f0743f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { useState, useId } from 'react';
import { PlusCircle } from 'lucide-react';
import * as Menu from '@ariakit/react/menu';
import { useFormContext } from 'react-hook-form';
import { DropdownPopup } from '@librechat/client';
import { specialVariables } from 'librechat-data-provider';
import type { TSpecialVarLabel } from 'librechat-data-provider';
import { useLocalize } from '~/hooks';

interface VariableOption {
  label: TSpecialVarLabel;
  value: string;
}

const variableOptions: VariableOption[] = Object.keys(specialVariables).map((key) => ({
  label: `com_ui_special_var_${key}` as TSpecialVarLabel,
  value: `{{${key}}}`,
}));

interface VariablesDropdownProps {
  fieldName?: string;
  className?: string;
}

export default function VariablesDropdown({
  fieldName = 'prompt',
  className = '',
}: VariablesDropdownProps) {
  const menuId = useId();
  const localize = useLocalize();
  const methods = useFormContext();
  const { setValue, getValues } = methods;

  const [isMenuOpen, setIsMenuOpen] = useState(false);

  const handleAddVariable = (label: TSpecialVarLabel, value: string) => {
    const currentText = getValues(fieldName) || '';
    const spacer = currentText.length > 0 ? '\n\n' : '';
    const prefix = localize(label);
    setValue(fieldName, currentText + spacer + prefix + ': ' + value);
    setIsMenuOpen(false);
  };

  return (
    <div
      className={className}
      title={`${localize('com_ui_add')} ${localize('com_ui_special_variables')}`}
    >
      <DropdownPopup
        portal={true}
        mountByState={true}
        unmountOnHide={true}
        preserveTabOrder={true}
        isOpen={isMenuOpen}
        setIsOpen={setIsMenuOpen}
        trigger={
          <Menu.MenuButton
            id="variables-menu-button"
            aria-label={`${localize('com_ui_add')} ${localize('com_ui_special_variables')}`}
            className="flex h-8 items-center gap-1 rounded-md border border-border-medium bg-surface-secondary px-2 py-0 text-sm text-text-primary transition-colors duration-200 hover:bg-surface-tertiary"
          >
            <PlusCircle className="mr-1 h-3 w-3 text-text-secondary" aria-hidden={true} />
            {localize('com_ui_special_variables')}
          </Menu.MenuButton>
        }
        items={variableOptions.map((option) => ({
          label: localize(option.label) || option.label,
          onClick: () => handleAddVariable(option.label, option.value),
        }))}
        menuId={menuId}
        className="z-30"
      />
    </div>
  );
}