Merge branch 'next' into andrasbacsai/livewire-model-binding

Resolved merge conflicts between Livewire model binding refactoring and UI/CSS updates from next branch. Key integrations:

- Preserved unique HTML ID generation for form components
- Maintained wire:model bindings using $modelBinding
- Integrated new wire:dirty.class styles (border-l-warning pattern)
- Kept both syncData(true) and validateDockerComposeForInjection in StackForm
- Merged security tests and helper improvements from next

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andras BacsaiandClaude committed 2025-10-16 11:05:29 +02:00
commit 837a0f4545
74 files changed
+4012 -286

No files matched your search

@@ -98,12 +98,12 @@
{{-- Unified Input Container with Tags Inside --}}
<div @click="$refs.searchInput.focus()"
class="flex flex-wrap gap-1.5 max-h-40 overflow-y-auto scrollbar py-1.5 w-full text-sm rounded-sm border-0 ring-1 ring-inset ring-neutral-200 dark:ring-coolgray-300 bg-white dark:bg-coolgray-100 cursor-text px-1 focus-within:ring-2 focus-within:ring-coollabs dark:focus-within:ring-warning text-black dark:text-white"
class="flex flex-wrap gap-1.5 max-h-40 overflow-y-auto scrollbar py-1.5 w-full text-sm rounded-sm border-0 ring-2 ring-inset ring-neutral-200 dark:ring-coolgray-300 bg-white dark:bg-coolgray-100 cursor-text px-1 focus-within:border-l-4 focus-within:border-l-coollabs dark:focus-within:border-l-warning text-black dark:text-white"
:class="{
'opacity-50': {{ $disabled ? 'true' : 'false' }}
}"
wire:loading.class="opacity-50"
wire:dirty.class="dark:ring-warning ring-warning">
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4">
{{-- Selected Tags Inside Input --}}
<template x-for="value in selected" :key="value">
@@ -229,12 +229,12 @@
{{-- Input Container --}}
<div @click="openDropdown()"
class="flex items-center gap-2 py-1.5 w-full text-sm rounded-sm border-0 ring-1 ring-inset ring-neutral-200 dark:ring-coolgray-300 bg-white dark:bg-coolgray-100 cursor-text focus-within:ring-2 focus-within:ring-coollabs dark:focus-within:ring-warning text-black dark:text-white"
class="flex items-center gap-2 py-1.5 w-full text-sm rounded-sm border-0 ring-2 ring-inset ring-neutral-200 dark:ring-coolgray-300 bg-white dark:bg-coolgray-100 cursor-text focus-within:border-l-4 focus-within:border-l-coollabs dark:focus-within:border-l-warning text-black dark:text-white"
:class="{
'opacity-50': {{ $disabled ? 'true' : 'false' }}
}"
wire:loading.class="opacity-50"
wire:dirty.class="dark:ring-warning ring-warning">
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4">
{{-- Display Selected Value or Search Input --}}
<div class="flex-1 flex items-center min-w-0 px-1">
@@ -28,7 +28,7 @@
<input autocomplete="{{ $autocomplete }}" value="{{ $value }}"
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required)
@if ($modelBinding !== 'null') wire:model={{ $modelBinding }} @endif
wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled"
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" wire:loading.attr="disabled"
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $htmlId }}"
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
aria-placeholder="{{ $attributes->get('placeholder') }}"
@@ -39,7 +39,7 @@
<input autocomplete="{{ $autocomplete }}" @if ($value) value="{{ $value }}" @endif
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly)
@if ($modelBinding !== 'null') wire:model={{ $modelBinding }} @endif
wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled"
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" wire:loading.attr="disabled"
type="{{ $type }}" @disabled($disabled) min="{{ $attributes->get('min') }}"
max="{{ $attributes->get('max') }}" minlength="{{ $attributes->get('minlength') }}"
maxlength="{{ $attributes->get('maxlength') }}"
@@ -81,8 +81,13 @@
document.getElementById(monacoId).addEventListener('monaco-editor-focused', (event) => {
editor.focus();
});
updatePlaceholder(editor.getValue());
@if ($autofocus)
// Auto-focus the editor
setTimeout(() => editor.focus(), 100);
@endif
$watch('monacoContent', value => {
if (editor.getValue() !== value) {
@@ -99,7 +104,7 @@
}, 5);" :id="monacoId">
</div>
<div class="relative z-10 w-full h-full">
<div x-ref="monacoEditorElement" class="w-full h-96 text-md {{ $readonly ? 'opacity-65' : '' }}"></div>
<div x-ref="monacoEditorElement" class="w-full h-[calc(100vh-20rem)] min-h-96 text-md {{ $readonly ? 'opacity-65' : '' }}"></div>
<div x-ref="monacoPlaceholderElement" x-show="monacoPlaceholder" @click="monacoEditorFocus()"
:style="'font-size: ' + monacoFontSize"
class="w-full text-sm font-mono absolute z-50 text-gray-500 ml-14 -translate-x-0.5 mt-0.5 left-0 top-0"
@@ -11,7 +11,7 @@
</label>
@endif
<select {{ $attributes->merge(['class' => $defaultClass]) }} @disabled($disabled) @required($required)
wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled" name={{ $modelBinding }} id="{{ $htmlId }}"
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" wire:loading.attr="disabled" name={{ $modelBinding }} id="{{ $htmlId }}"
@if ($attributes->whereStartsWith('wire:model')->first()) {{ $attributes->whereStartsWith('wire:model')->first() }} @else wire:model={{ $modelBinding }} @endif>
{{ $slot }}
</select>
@@ -27,7 +27,7 @@
@if ($useMonacoEditor)
<x-forms.monaco-editor id="{{ $modelBinding }}" language="{{ $monacoEditorLanguage }}" name="{{ $name }}"
name="{{ $modelBinding }}" model="{{ $value ?? $modelBinding }}" wire:model="{{ $value ?? $modelBinding }}"
readonly="{{ $readonly }}" label="dockerfile" />
readonly="{{ $readonly }}" label="dockerfile" autofocus="{{ $autofocus }}" />
@else
@if ($type === 'password')
<div class="relative" x-data="{ type: 'password' }">
@@ -46,7 +46,7 @@
<input x-cloak x-show="type === 'password'" value="{{ $value }}"
{{ $attributes->merge(['class' => $defaultClassInput]) }} @required($required)
@if ($modelBinding !== 'null') wire:model={{ $modelBinding }} @endif
wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled"
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" wire:loading.attr="disabled"
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $htmlId }}"
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
aria-placeholder="{{ $attributes->get('placeholder') }}">
@@ -55,9 +55,10 @@
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $modelBinding }}"
@else
wire:model={{ $value ?? $modelBinding }}
wire:dirty.class="dark:ring-warning ring-warning" @endif
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" @endif
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}"
name="{{ $name }}" name={{ $modelBinding }}></textarea>
name="{{ $name }}" name={{ $modelBinding }}
@if ($autofocus) x-ref="autofocusInput" @endif></textarea>
</div>
@else
@@ -67,9 +68,10 @@
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $modelBinding }}"
@else
wire:model={{ $value ?? $modelBinding }}
wire:dirty.class="dark:ring-warning ring-warning" @endif
wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" @endif
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}"
name="{{ $name }}" name={{ $modelBinding }}></textarea>
name="{{ $name }}" name={{ $modelBinding }}
@if ($autofocus) x-ref="autofocusInput" @endif></textarea>
@endif
@endif
@error($modelBinding)