Remove useTemplating prop (#184)

This commit is contained in:
Gregory Schier
2025-03-18 05:34:38 -07:00
committed by GitHub
parent f42f3d0e27
commit b9ed554aca
20 changed files with 134 additions and 231 deletions

View File

@@ -1,80 +0,0 @@
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models';
import { Input } from './core/Input';
import { VStack } from './core/Stacks';
interface Props<T> {
request: T;
}
export function BasicAuth<T extends HttpRequest | GrpcRequest>({ request }: Props<T>) {
const updateHttpRequest = useUpdateAnyHttpRequest();
const updateGrpcRequest = useUpdateAnyGrpcRequest();
return (
<VStack className="py-2 overflow-y-auto h-full" space={2}>
<Input
useTemplating
autocompleteVariables
stateKey={`basic.username.${request.id}`}
forceUpdateKey={request.id}
placeholder="username"
label="Username"
name="username"
size="sm"
defaultValue={`${request.authentication.username}`}
onChange={(username: string) => {
if (request.model === 'http_request') {
updateHttpRequest.mutate({
id: request.id,
update: (r: HttpRequest) => ({
...r,
authentication: { password: r.authentication.password, username },
}),
});
} else {
updateGrpcRequest.mutate({
id: request.id,
update: (r: GrpcRequest) => ({
...r,
authentication: { password: r.authentication.password, username },
}),
});
}
}}
/>
<Input
useTemplating
autocompleteVariables
forceUpdateKey={request?.id}
stateKey={`basic.password.${request.id}`}
placeholder="password"
label="Password"
name="password"
size="sm"
type="password"
defaultValue={`${request.authentication.password}`}
onChange={(password: string) => {
if (request.model === 'http_request') {
updateHttpRequest.mutate({
id: request.id,
update: (r: HttpRequest) => ({
...r,
authentication: { username: r.authentication.username, password },
}),
});
} else {
updateGrpcRequest.mutate({
id: request.id,
update: (r: GrpcRequest) => ({
...r,
authentication: { username: r.authentication.username, password },
}),
});
}
}}
/>
</VStack>
);
}

View File

@@ -1,49 +0,0 @@
import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest';
import { useUpdateAnyHttpRequest } from '../hooks/useUpdateAnyHttpRequest';
import type { GrpcRequest, HttpRequest } from '@yaakapp-internal/models';
import { Input } from './core/Input';
import { VStack } from './core/Stacks';
interface Props<T> {
request: T;
}
export function BearerAuth<T extends HttpRequest | GrpcRequest>({ request }: Props<T>) {
const updateHttpRequest = useUpdateAnyHttpRequest();
const updateGrpcRequest = useUpdateAnyGrpcRequest();
return (
<VStack className="my-2" space={2}>
<Input
useTemplating
autocompleteVariables
placeholder="token"
stateKey={`bearer.${request.id}`}
type="password"
label="Token"
name="token"
size="sm"
defaultValue={`${request.authentication.token}`}
onChange={(token: string) => {
if (request.model === 'http_request') {
updateHttpRequest.mutate({
id: request.id ?? null,
update: (r: HttpRequest) => ({
...r,
authentication: { token },
}),
});
} else {
updateGrpcRequest.mutate({
id: request.id ?? null,
update: (r: GrpcRequest) => ({
...r,
authentication: { token },
}),
});
}
}}
/>
</VStack>
);
}

View File

@@ -34,7 +34,7 @@ interface Props<T> {
inputs: FormInput[] | undefined | null;
onChange: (value: T) => void;
data: T;
useTemplating?: boolean;
autocompleteFunctions?: boolean;
autocompleteVariables?: boolean;
stateKey: string;
disabled?: boolean;
@@ -44,8 +44,8 @@ export function DynamicForm<T extends Record<string, JsonPrimitive>>({
inputs,
data,
onChange,
useTemplating,
autocompleteVariables,
autocompleteFunctions,
stateKey,
disabled,
}: Props<T>) {
@@ -62,7 +62,7 @@ export function DynamicForm<T extends Record<string, JsonPrimitive>>({
inputs={inputs}
setDataAttr={setDataAttr}
stateKey={stateKey}
useTemplating={useTemplating}
autocompleteFunctions={autocompleteFunctions}
autocompleteVariables={autocompleteVariables}
data={data}
/>
@@ -71,13 +71,16 @@ export function DynamicForm<T extends Record<string, JsonPrimitive>>({
function FormInputs<T extends Record<string, JsonPrimitive>>({
inputs,
autocompleteFunctions,
autocompleteVariables,
stateKey,
useTemplating,
setDataAttr,
data,
disabled,
}: Pick<Props<T>, 'inputs' | 'useTemplating' | 'autocompleteVariables' | 'stateKey' | 'data'> & {
}: Pick<
Props<T>,
'inputs' | 'autocompleteFunctions' | 'autocompleteVariables' | 'stateKey' | 'data'
> & {
setDataAttr: (name: string, value: JsonPrimitive) => void;
disabled?: boolean;
}) {
@@ -112,7 +115,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
key={i}
stateKey={stateKey}
arg={input}
useTemplating={useTemplating || false}
autocompleteFunctions={autocompleteFunctions || false}
autocompleteVariables={autocompleteVariables || false}
onChange={(v) => setDataAttr(input.name, v)}
value={
@@ -126,7 +129,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
key={i}
stateKey={stateKey}
arg={input}
useTemplating={useTemplating || false}
autocompleteFunctions={autocompleteFunctions || false}
autocompleteVariables={autocompleteVariables || false}
onChange={(v) => setDataAttr(input.name, v)}
value={
@@ -175,7 +178,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
inputs={input.inputs}
setDataAttr={setDataAttr}
stateKey={stateKey}
useTemplating={useTemplating}
autocompleteFunctions={autocompleteFunctions || false}
autocompleteVariables={autocompleteVariables}
/>
</div>
@@ -195,7 +198,7 @@ function FormInputs<T extends Record<string, JsonPrimitive>>({
inputs={input.inputs}
setDataAttr={setDataAttr}
stateKey={stateKey}
useTemplating={useTemplating}
autocompleteFunctions={autocompleteFunctions || false}
autocompleteVariables={autocompleteVariables}
/>
</Banner>
@@ -212,14 +215,14 @@ function TextArg({
arg,
onChange,
value,
useTemplating,
autocompleteFunctions,
autocompleteVariables,
stateKey,
}: {
arg: FormInputText;
value: string;
onChange: (v: string) => void;
useTemplating: boolean;
autocompleteFunctions: boolean;
autocompleteVariables: boolean;
stateKey: string;
}) {
@@ -237,7 +240,7 @@ function TextArg({
hideLabel={arg.label == null}
placeholder={arg.placeholder ?? undefined}
autocomplete={arg.completionOptions ? { options: arg.completionOptions } : undefined}
useTemplating={useTemplating}
autocompleteFunctions={autocompleteFunctions}
autocompleteVariables={autocompleteVariables}
stateKey={stateKey}
forceUpdateKey={stateKey}
@@ -249,14 +252,14 @@ function EditorArg({
arg,
onChange,
value,
useTemplating,
autocompleteFunctions,
autocompleteVariables,
stateKey,
}: {
arg: FormInputEditor;
value: string;
onChange: (v: string) => void;
useTemplating: boolean;
autocompleteFunctions: boolean;
autocompleteVariables: boolean;
stateKey: string;
}) {
@@ -290,7 +293,7 @@ function EditorArg({
heightMode="auto"
defaultValue={value === DYNAMIC_FORM_NULL_ARG ? arg.defaultValue : value}
placeholder={arg.placeholder ?? undefined}
useTemplating={useTemplating}
autocompleteFunctions={autocompleteFunctions}
autocompleteVariables={autocompleteVariables}
stateKey={stateKey}
forceUpdateKey={forceUpdateKey}

View File

@@ -116,7 +116,7 @@ export const EnvironmentEditDialog = function ({ initialEnvironment }: Props) {
};
const EnvironmentEditor = function ({
environment,
environment: activeEnvironment,
className,
}: {
environment: Environment;
@@ -127,8 +127,8 @@ const EnvironmentEditor = function ({
key: 'environmentValueVisibility',
fallback: true,
});
const { subEnvironments } = useEnvironments();
const updateEnvironment = useUpdateEnvironment(environment?.id ?? null);
const { allEnvironments } = useEnvironments();
const updateEnvironment = useUpdateEnvironment(activeEnvironment?.id ?? null);
const handleChange = useCallback<PairEditorProps['onChange']>(
(variables) => updateEnvironment.mutate({ variables }),
[updateEnvironment],
@@ -136,26 +136,28 @@ const EnvironmentEditor = function ({
// Gather a list of env names from other environments, to help the user get them aligned
const nameAutocomplete = useMemo<GenericCompletionConfig>(() => {
const allVariableNames =
environment == null
? [] // Nothing to autocomplete if we're in the base environment
: subEnvironments
.filter((e) => e.environmentId != null)
.flatMap((e) => e.variables.map((v) => v.name));
const options: GenericCompletionOption[] = [];
const isBaseEnv = activeEnvironment.environmentId == null;
if (isBaseEnv) {
return { options };
}
// Filter out empty strings and variables that already exist
const variableNames = allVariableNames.filter(
(name) => name != '' && !environment.variables.find((v) => v.name === name),
);
const uniqueVariableNames = [...new Set(variableNames)];
const options = uniqueVariableNames.map(
(name): GenericCompletionOption => ({
const allVariables = allEnvironments.flatMap((e) => e?.variables);
const allVariableNames = new Set(allVariables.map((v) => v?.name));
for (const name of allVariableNames) {
const containingEnvs = allEnvironments.filter((e) =>
e.variables.some((v) => v.name === name),
);
const isAlreadyInActive = containingEnvs.find((e) => e.id === activeEnvironment.id);
if (isAlreadyInActive) continue;
options.push({
label: name,
type: 'constant',
}),
);
detail: containingEnvs.map((e) => e.name).join(', '),
});
}
return { options };
}, [subEnvironments, environment]);
}, [activeEnvironment.environmentId, activeEnvironment.id, allEnvironments]);
const validateName = useCallback((name: string) => {
// Empty just means the variable doesn't have a name yet, and is unusable
@@ -167,7 +169,7 @@ const EnvironmentEditor = function ({
<VStack space={4} className={classNames(className, 'pl-4')}>
<HStack space={2} className="justify-between">
<Heading className="w-full flex items-center gap-1">
<div>{environment?.name}</div>
<div>{activeEnvironment?.name}</div>
<IconButton
size="sm"
icon={valueVisibility.value ? 'eye' : 'eye_closed'}
@@ -183,15 +185,15 @@ const EnvironmentEditor = function ({
allowMultilineValues
preferenceName="environment"
nameAutocomplete={nameAutocomplete}
nameAutocompleteVariables={false}
namePlaceholder="VAR_NAME"
nameValidate={validateName}
valueType={valueVisibility.value ? 'text' : 'password'}
valueAutocompleteVariables={true}
forceUpdateKey={environment.id}
pairs={environment.variables}
valueAutocompleteVariables
valueAutocompleteFunctions
forceUpdateKey={activeEnvironment.id}
pairs={activeEnvironment.variables}
onChange={handleChange}
stateKey={`environment.${environment.id}`}
stateKey={`environment.${activeEnvironment.id}`}
/>
</div>
</VStack>

View File

@@ -40,8 +40,10 @@ export function FormMultipartEditor({ request, forceUpdateKey, onChange }: Props
return (
<PairEditor
valueAutocompleteFunctions
valueAutocompleteVariables
nameAutocompleteVariables
nameAutocompleteFunctions
allowFileValues
allowMultilineValues
pairs={pairs}

View File

@@ -31,7 +31,9 @@ export function FormUrlencodedEditor({ request, forceUpdateKey, onChange }: Prop
<PairOrBulkEditor
allowMultilineValues
preferenceName="form_urlencoded"
valueAutocompleteFunctions
valueAutocompleteVariables
nameAutocompleteFunctions
nameAutocompleteVariables
namePlaceholder="entry_name"
valuePlaceholder="Value"

View File

@@ -183,7 +183,7 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
onChange={handleChangeVariables}
placeholder="{}"
stateKey={'graphql_vars.' + request.id}
useTemplating
autocompleteFunctions
autocompleteVariables
{...extraEditorProps}
/>

View File

@@ -181,8 +181,8 @@ export function GrpcEditor({
<div className="h-full w-full grid grid-cols-1 grid-rows-[minmax(0,100%)_auto_auto_minmax(0,auto)]">
<Editor
language="json"
autocompleteFunctions
autocompleteVariables
useTemplating
forceUpdateKey={request.id}
defaultValue={request.message}
heightMode="auto"

View File

@@ -21,7 +21,9 @@ export function HeadersEditor({ stateKey, headers, onChange, forceUpdateKey }: P
<PairOrBulkEditor
preferenceName="headers"
stateKey={stateKey}
valueAutocompleteFunctions
valueAutocompleteVariables
nameAutocompleteFunctions
nameAutocompleteVariables
pairs={headers}
onChange={onChange}

View File

@@ -75,7 +75,7 @@ export function HttpAuthenticationEditor({ request }: Props) {
<DynamicForm
disabled={request.authentication.disabled}
autocompleteVariables
useTemplating
autocompleteFunctions
stateKey={`auth.${request.id}.${request.authenticationType}`}
inputs={authConfig.data.args}
data={request.authentication}

View File

@@ -411,7 +411,7 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
{activeRequest.bodyType === BODY_TYPE_JSON ? (
<Editor
forceUpdateKey={forceUpdateKey}
useTemplating
autocompleteFunctions
autocompleteVariables
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
@@ -423,7 +423,7 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
) : activeRequest.bodyType === BODY_TYPE_XML ? (
<Editor
forceUpdateKey={forceUpdateKey}
useTemplating
autocompleteFunctions
autocompleteVariables
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}
@@ -462,7 +462,7 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }:
) : typeof activeRequest.bodyType === 'string' ? (
<Editor
forceUpdateKey={forceUpdateKey}
useTemplating
autocompleteFunctions
autocompleteVariables
language={languageFromContentType(contentType)}
placeholder="..."

View File

@@ -68,12 +68,12 @@ export const UrlBar = memo(function UrlBar({
<form onSubmit={handleSubmit} className={classNames('x-theme-urlBar', className)}>
<Input
ref={inputRef}
autocompleteFunctions
autocompleteVariables
stateKey={stateKey}
size="sm"
wrapLines={isFocused}
hideLabel
useTemplating
language="url"
className="px-1.5 py-0.5"
label="Enter URL"

View File

@@ -35,12 +35,14 @@ export function UrlParametersEditor({ pairs, forceUpdateKey, onChange, stateKey
ref={pairEditor}
allowMultilineValues
forceUpdateKey={forceUpdateKey + urlParametersKey}
nameAutocompleteFunctions
nameAutocompleteVariables
namePlaceholder="param_name"
onChange={onChange}
pairs={pairs}
preferenceName="url_parameters"
stateKey={stateKey}
valueAutocompleteFunctions
valueAutocompleteVariables
valuePlaceholder="Value"
/>

View File

@@ -301,7 +301,7 @@ export function WebsocketRequestPane({ style, fullHeight, className, activeReque
<TabContent value={TAB_MESSAGE}>
<Editor
forceUpdateKey={forceUpdateKey}
useTemplating
autocompleteFunctions
autocompleteVariables
placeholder="..."
heightMode={fullHeight ? 'full' : 'auto'}

View File

@@ -33,7 +33,7 @@ export function BulkPairEditor({
return (
<Editor
useTemplating
autocompleteFunctions
autocompleteVariables
stateKey={`bulk_pair.${stateKey}`}
forceUpdateKey={forceUpdateKey}

View File

@@ -55,36 +55,36 @@ const keymapExtensions: Record<EditorKeymap, Extension> = {
};
export interface EditorProps {
id?: string;
readOnly?: boolean;
disabled?: boolean;
type?: 'text' | 'password';
className?: string;
heightMode?: 'auto' | 'full';
language?: EditorLanguage | 'pairs' | 'url';
forceUpdateKey?: string | number;
actions?: ReactNode;
autoFocus?: boolean;
autoSelect?: boolean;
autocomplete?: GenericCompletionConfig;
autocompleteFunctions?: boolean;
autocompleteVariables?: boolean;
className?: string;
defaultValue?: string | null;
placeholder?: string;
tooltipContainer?: HTMLElement;
useTemplating?: boolean;
disableTabIndent?: boolean;
disabled?: boolean;
extraExtensions?: Extension[];
forceUpdateKey?: string | number;
format?: (v: string) => Promise<string>;
heightMode?: 'auto' | 'full';
hideGutter?: boolean;
id?: string;
language?: EditorLanguage | 'pairs' | 'url';
onBlur?: () => void;
onChange?: (value: string) => void;
onFocus?: () => void;
onKeyDown?: (e: KeyboardEvent) => void;
onPaste?: (value: string) => void;
onPasteOverwrite?: (e: ClipboardEvent, value: string) => void;
onFocus?: () => void;
onBlur?: () => void;
onKeyDown?: (e: KeyboardEvent) => void;
placeholder?: string;
readOnly?: boolean;
singleLine?: boolean;
wrapLines?: boolean;
disableTabIndent?: boolean;
format?: (v: string) => Promise<string>;
autocomplete?: GenericCompletionConfig;
autocompleteVariables?: boolean;
extraExtensions?: Extension[];
actions?: ReactNode;
hideGutter?: boolean;
stateKey: string | null;
tooltipContainer?: HTMLElement;
type?: 'text' | 'password';
wrapLines?: boolean;
}
const stateFields = { history: historyField, folds: foldState };
@@ -94,34 +94,34 @@ const emptyExtension: Extension = [];
export const Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
{
readOnly,
type,
heightMode,
language,
actions,
autoFocus,
autoSelect,
placeholder,
useTemplating,
autocomplete,
autocompleteFunctions,
autocompleteVariables,
className,
defaultValue,
disableTabIndent,
disabled,
extraExtensions,
forceUpdateKey,
format,
heightMode,
hideGutter,
language,
onBlur,
onChange,
onFocus,
onKeyDown,
onPaste,
onPasteOverwrite,
onFocus,
onBlur,
onKeyDown,
className,
disabled,
placeholder,
readOnly,
singleLine,
format,
autocomplete,
extraExtensions,
autocompleteVariables,
actions,
wrapLines,
disableTabIndent,
hideGutter,
stateKey,
type,
wrapLines,
}: EditorProps,
ref,
) {
@@ -129,6 +129,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
const allEnvironmentVariables = useActiveEnvironmentVariables();
const environmentVariables = autocompleteVariables ? allEnvironmentVariables : emptyVariables;
const useTemplating = !!(autocompleteFunctions || autocompleteVariables || autocomplete);
if (settings && wrapLines === undefined) {
wrapLines = settings.editorSoftWrap;
@@ -340,16 +341,19 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
[focusParamValue],
);
const completionOptions = useTemplateFunctionCompletionOptions(onClickFunction);
const completionOptions = useTemplateFunctionCompletionOptions(
onClickFunction,
!!autocompleteFunctions,
);
// Update the language extension when the language changes
useEffect(() => {
if (cm.current === null) return;
const { view, languageCompartment } = cm.current;
const ext = getLanguageExtension({
useTemplating,
language,
environmentVariables,
useTemplating,
autocomplete,
completionOptions,
onClickVariable,
@@ -360,13 +364,13 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
}, [
language,
autocomplete,
useTemplating,
environmentVariables,
onClickFunction,
onClickVariable,
onClickMissingVariable,
onClickPathParameter,
completionOptions,
useTemplating,
]);
// Initialize the editor when ref mounts
@@ -381,8 +385,8 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
try {
const languageCompartment = new Compartment();
const langExt = getLanguageExtension({
language,
useTemplating,
language,
completionOptions,
autocomplete,
environmentVariables,

View File

@@ -91,8 +91,8 @@ const syntaxExtensions: Record<NonNullable<EditorProps['language']>, LanguageSup
const closeBracketsFor: (keyof typeof syntaxExtensions)[] = ['json', 'javascript', 'graphql'];
export function getLanguageExtension({
useTemplating,
language = 'text',
useTemplating = false,
environmentVariables,
autocomplete,
onClickVariable,
@@ -100,12 +100,13 @@ export function getLanguageExtension({
onClickPathParameter,
completionOptions,
}: {
useTemplating: boolean;
environmentVariables: EnvironmentVariable[];
onClickVariable: (option: EnvironmentVariable, tagValue: string, startPos: number) => void;
onClickMissingVariable: (name: string, tagValue: string, startPos: number) => void;
onClickPathParameter: (name: string) => void;
completionOptions: TwigCompletionOption[];
} & Pick<EditorProps, 'language' | 'useTemplating' | 'autocomplete'>) {
} & Pick<EditorProps, 'language' | 'autocomplete'>) {
const extraExtensions: Extension[] = [];
if (language === 'url') {

View File

@@ -13,13 +13,13 @@ import { HStack } from './Stacks';
export type InputProps = Pick<
EditorProps,
| 'language'
| 'useTemplating'
| 'autocomplete'
| 'forceUpdateKey'
| 'disabled'
| 'autoFocus'
| 'autoSelect'
| 'autocompleteVariables'
| 'autocompleteFunctions'
| 'onKeyDown'
| 'readOnly'
> & {

View File

@@ -43,6 +43,7 @@ export type PairEditorProps = {
className?: string;
forceUpdateKey?: string;
nameAutocomplete?: GenericCompletionConfig;
nameAutocompleteFunctions?: boolean;
nameAutocompleteVariables?: boolean;
namePlaceholder?: string;
nameValidate?: InputProps['validate'];
@@ -51,6 +52,7 @@ export type PairEditorProps = {
pairs: Pair[];
stateKey: InputProps['stateKey'];
valueAutocomplete?: (name: string) => GenericCompletionConfig | undefined;
valueAutocompleteFunctions?: boolean;
valueAutocompleteVariables?: boolean;
valuePlaceholder?: string;
valueType?: 'text' | 'password';
@@ -82,6 +84,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
className,
forceUpdateKey,
nameAutocomplete,
nameAutocompleteFunctions,
nameAutocompleteVariables,
namePlaceholder,
nameValidate,
@@ -89,6 +92,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
onChange,
pairs: originalPairs,
valueAutocomplete,
valueAutocompleteFunctions,
valueAutocompleteVariables,
valuePlaceholder,
valueType,
@@ -237,6 +241,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
index={i}
isLast={isLast}
nameAutocomplete={nameAutocomplete}
nameAutocompleteFunctions={nameAutocompleteFunctions}
nameAutocompleteVariables={nameAutocompleteVariables}
namePlaceholder={namePlaceholder}
nameValidate={nameValidate}
@@ -248,6 +253,7 @@ export const PairEditor = forwardRef<PairEditorRef, PairEditorProps>(function Pa
pair={p}
stateKey={stateKey}
valueAutocomplete={valueAutocomplete}
valueAutocompleteFunctions={valueAutocompleteFunctions}
valueAutocompleteVariables={valueAutocompleteVariables}
valuePlaceholder={valuePlaceholder}
valueType={valueType}
@@ -291,8 +297,10 @@ type PairEditorRowProps = {
| 'nameAutocompleteVariables'
| 'namePlaceholder'
| 'nameValidate'
| 'nameAutocompleteFunctions'
| 'stateKey'
| 'valueAutocomplete'
| 'valueAutocompleteFunctions'
| 'valueAutocompleteVariables'
| 'valuePlaceholder'
| 'valueType'
@@ -309,9 +317,10 @@ function PairEditorRow({
index,
isLast,
nameAutocomplete,
nameAutocompleteVariables,
namePlaceholder,
nameValidate,
nameAutocompleteFunctions,
nameAutocompleteVariables,
onChange,
onDelete,
onEnd,
@@ -320,6 +329,7 @@ function PairEditorRow({
pair,
stateKey,
valueAutocomplete,
valueAutocompleteFunctions,
valueAutocompleteVariables,
valuePlaceholder,
valueType,
@@ -486,7 +496,6 @@ function PairEditorRow({
<Input
ref={nameInputRef}
hideLabel
useTemplating
stateKey={`name.${pair.id}.${stateKey}`}
wrapLines={false}
readOnly={pair.readOnlyName}
@@ -503,6 +512,7 @@ function PairEditorRow({
placeholder={namePlaceholder ?? 'name'}
autocomplete={nameAutocomplete}
autocompleteVariables={nameAutocompleteVariables}
autocompleteFunctions={nameAutocompleteFunctions}
/>
)}
<div className="w-full grid grid-cols-[minmax(0,1fr)_auto] gap-1 items-center">
@@ -534,7 +544,6 @@ function PairEditorRow({
<Input
ref={valueInputRef}
hideLabel
useTemplating
stateKey={`value.${pair.id}.${stateKey}`}
wrapLines={false}
size="sm"
@@ -549,6 +558,7 @@ function PairEditorRow({
type={isLast ? 'text' : valueType}
placeholder={valuePlaceholder ?? 'value'}
autocomplete={valueAutocomplete?.(pair.name)}
autocompleteFunctions={valueAutocompleteFunctions}
autocompleteVariables={valueAutocompleteVariables}
/>
)}
@@ -695,7 +705,7 @@ function MultilineEditDialog({
language={language}
onChange={setValue}
stateKey={null}
useTemplating
autocompleteFunctions
autocompleteVariables
/>
<div>

View File

@@ -11,9 +11,13 @@ const templateFunctionsAtom = atom<TemplateFunction[]>([]);
export function useTemplateFunctionCompletionOptions(
onClick: (fn: TemplateFunction, ragTag: string, pos: number) => void,
enabled: boolean,
) {
const templateFunctions = useAtomValue(templateFunctionsAtom);
return useMemo<TwigCompletionOption[]>(() => {
if (!enabled) {
return [];
}
return (
templateFunctions.map((fn) => {
const NUM_ARGS = 2;
@@ -35,7 +39,7 @@ export function useTemplateFunctionCompletionOptions(
};
}) ?? []
);
}, [onClick, templateFunctions]);
}, [enabled, onClick, templateFunctions]);
}
export function useSubscribeTemplateFunctions() {