fix: prevent divide-by-zero in env-var autocomplete navigation

Fixes a critical bug in the environment variable autocomplete component
where arrow key navigation could cause divide-by-zero errors when the
suggestions array is empty.

Changes:
- Add early guard in handleKeydown to check for empty suggestions array
  before performing modulo operations
- Remove unreachable "No suggestions" template that could never display
- Add validation to hide dropdown when user types third brace ({{{)
- Refactor add.blade.php to use @if directives instead of x-show for
  better performance and cleaner code

The fix ensures arrow keys do nothing when suggestions are empty,
preventing JavaScript errors while maintaining all existing functionality
including the scoped empty state messages with helpful links.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai 2025-11-25 10:55:37 +01:00
parent 4147cfa537
commit 92dff0c0c7
2 changed files with 16 additions and 14 deletions

View file

@ -47,6 +47,11 @@
return;
}
if (lastBraceIndex > 0 && textBeforeCursor[lastBraceIndex - 1] === '{') {
this.showDropdown = false;
return;
}
const textAfterBrace = textBeforeCursor.substring(lastBraceIndex);
const closeBraces = '}' + '}';
if (textAfterBrace.includes(closeBraces)) {
@ -156,6 +161,7 @@
handleKeydown(event) {
if (!this.showDropdown) return;
if (!this.suggestions || this.suggestions.length === 0) return;
if (event.key === 'ArrowDown') {
event.preventDefault();
@ -225,12 +231,6 @@ class="text-coollabs dark:text-warning hover:underline text-xs mt-1 inline-block
</div>
</template>
<template x-if="suggestions.length === 0 && !currentScope">
<div class="px-3 py-2 text-sm text-neutral-500 dark:text-neutral-400">
No suggestions
</div>
</template>
<div x-show="suggestions.length > 0"
x-ref="dropdownList"
class="max-h-48 overflow-y-scroll"

View file

@ -1,14 +1,16 @@
<form class="flex flex-col w-full gap-2 rounded-sm" wire:submit='submit'>
<x-forms.input placeholder="NODE_ENV" id="key" label="Name" required />
<x-forms.textarea x-show="$wire.is_multiline === true" x-cloak id="value" label="Value" required />
<x-forms.env-var-input x-show="$wire.is_multiline === false" x-cloak placeholder="production" id="value"
x-bind:label="$wire.is_multiline === false && 'Value'" required
:availableVars="$shared ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')" />
@if ($is_multiline)
<x-forms.textarea id="value" label="Value" required />
@else
<x-forms.env-var-input placeholder="production" id="value" label="Value" required
:availableVars="$shared ? [] : $this->availableSharedVariables"
:projectUuid="data_get($parameters, 'project_uuid')"
:environmentUuid="data_get($parameters, 'environment_uuid')" />
@endif
@if (!$shared)
<div x-show="$wire.is_multiline === false" x-cloak class="text-xs text-neutral-500 dark:text-neutral-400 -mt-1">
@if (!$shared && !$is_multiline)
<div class="text-xs text-neutral-500 dark:text-neutral-400 -mt-1">
Tip: Type <span class="font-mono dark:text-warning text-coollabs">{{</span> to reference a shared environment
variable
</div>