Created
September 20, 2021 00:53
-
-
Save cednore/3fd0f777704106dd0a3c658020d11fbe to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div | |
x-data="{ | |
query: '', | |
showDropdown: false, | |
currentHighlightedKey: Infinity, | |
options: {}, | |
wireProp: @entangle($name).defer, | |
flags: {}, | |
initFlags() { | |
for (const key of Object.keys(this.options)) { | |
this.flags[key] = this.wireProp.split(',').includes(key); | |
} | |
}, | |
onClickOption(key) { | |
this.flags[key] = ! this.flags[key]; | |
this.updateInputValue(); | |
}, | |
onBackspace() { | |
if (! this.query) { | |
const lastTrueFlagKey = Object.keys(this.flags).reverse().find(key => this.flags[key]); | |
this.flags[lastTrueFlagKey] = false; | |
this.updateInputValue(); | |
} | |
}, | |
updateInputValue() { | |
this.wireProp = this.trueKeys().join(); | |
}, | |
filteredKeys() { | |
return Object.keys(this.options) | |
.filter(key => this.options[key].label.toLowerCase().includes(this.query.toLowerCase())); | |
}, | |
trueKeys() { | |
return Object.keys(this.flags).filter(key => this.flags[key]); | |
}, | |
}" | |
x-init='options = @json($options); initFlags();' | |
> | |
@if($label) | |
<div class="flex items-center space-x-1"> | |
<label for="{{ $name }}" class="{{ style('inputs.label') }}">{{ $label }}</label> | |
@if($required) | |
<x-app.inputs.required-dot /> | |
@endif | |
</div> | |
@endif | |
<div class="{{ style('inputs.input_div_wrapper') }}"> | |
<input | |
{{ $attributes }} | |
x-model="wireProp" | |
name="{{ $name }}" | |
type="hidden" | |
id="{{ $id }}" | |
{{ $disabled ? 'disabled' : '' }} | |
{{ $disabled ? 'readonly' : '' }} | |
> | |
<div class="flex flex-wrap space-x-2 space-y-1 items-center w-full rounded border border-gray-300 px-1 py-2"> | |
<template x-for="key in trueKeys()" :key="key"> | |
<div | |
class="flex items-center space-x-1 px-2 py-1 rounded bg-green-100 text-sm text-green-800 cursor-pointer" | |
@if(! $disabled) @click="onClickOption(key)" @endif | |
> | |
<span x-text="options[key].label"></span> | |
<span class="px-1 font-bold">X</span> | |
</div> | |
</template> | |
<input | |
class="flex-1 border-0 focus:outline-none focus:border-0 focus:ring-0 p-0" | |
type="text" | |
x-model="query" | |
x-ref="tagquery" | |
@if(! $disabled) | |
@click="showDropdown = ! showDropdown;" | |
@click.away="showDropdown = false;" | |
@keydown="showDropdown = true;" | |
@keydown.escape.stop="showDropdown = false;" | |
@keydown.backspace="onBackspace" | |
@endif | |
{{ $disabled ? 'disabled' : '' }} | |
{{ $disabled ? 'readonly' : '' }} | |
{!! $placeholder ? "placeholder='$placeholder'" : '' !!} | |
> | |
</div> | |
<div x-show="showDropdown" class="absolute mt-1 w-full rounded-md bg-white shadow-lg z-50"> | |
<ul tabindex="-1" role="listbox" class="max-h-56 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"> | |
<template | |
x-show="filteredKeys().length" | |
x-for="key in filteredKeys()" | |
:key="key" | |
> | |
<li | |
@if(! $disabled) @click.prevent.stop="onClickOption(key)" @endif | |
x-bind:id="'tag-option-' + key" | |
role="option" | |
class="text-gray-900 cursor-default select-none relative py-2 pl-3 pr-9 hover:text-white hover:bg-blue-500" | |
> | |
<div class="flex items-center"> | |
<img | |
x-bind:src="options[key].image" | |
alt="" | |
class="flex-shrink-0 h-6 w-6 rounded-full" | |
> | |
<span | |
x-text="options[key].label" | |
class="ml-3 block font-normal truncate hover:font-semibold" | |
></span> | |
</div> | |
<span | |
class="absolute inset-y-0 right-0 flex items-center pr-4" | |
x-show="flags[key]" | |
> | |
<svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> | |
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" /> | |
</svg> | |
</span> | |
</li> | |
</template> | |
<li | |
x-show="! filteredKeys().length" | |
class="text-gray-600 select-none py-2 pl-3 pr-9" | |
><span>{{ __('general.no-matching-results') }}</span></li> | |
</ul> | |
</div> | |
@error($name) | |
<div class="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none"> | |
<svg class="h-5 w-5 text-red-500" fill="currentColor" viewBox="0 0 20 20"> | |
<path fill-rule="evenodd" | |
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" | |
clip-rule="evenodd"></path> | |
</svg> | |
</div> | |
@enderror | |
</div> | |
@error($name) | |
<p class="{!! style('inputs.input_error_text') !!}">{{ $message }}</p> | |
@enderror | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment