Skip to content

Instantly share code, notes, and snippets.

@codemonkey76
Created December 7, 2022 06:16
Show Gist options
  • Save codemonkey76/e8c38ac67ab0f54936753ad4e8b2a09a to your computer and use it in GitHub Desktop.
Save codemonkey76/e8c38ac67ab0f54936753ad4e8b2a09a to your computer and use it in GitHub Desktop.
<div x-cloak x-data="{
hourOptions: [...Array(12+1).keys()].slice(1),
minuteOptions: [...Array(60).keys()],
isHourHighlighted: function(option) { return this.hourHighlighted === option },
isHourSelected: function(option) { return this.hourValue === option },
isMinuteHighlighted: function(option) { return this.minuteHighlighted === option },
isMinuteSelected: function(option) { return this.minuteValue === option },
highlightHourOption: function(option) { this.hourHighlighted = option },
unHighlightHourOption: function(option) { this.hourHighlighted = null },
highlightMinuteOption: function(option) { this.minuteHighlighted = option },
unHighlightMinuteOption: function(option) { this.minuteHighlighted = null },
hourHighlighted: null,
minuteHighlighted: null,
hourOpen: false,
minuteOpen: false,
hourValue: 9,
minuteValue: 0,
isAm: true,
selectHour(option) { this.hourValue = option },
selectMinute(option) { this.minuteValue = option },
onInternalValueChanged() {
this.value = ((this.hourValue + (this.isAm ? 0 : 12)) * 60 * 60) + (this.minuteValue * 60)
},
onExternalValueChanged() {
this.minuteValue = (this.value % (60*60)) / 60
let hour24 = (this.value - (this.minuteValue*60))/(60*60)
this.hourValue = hour24>12 ? hour24-12 : hour24
this.isAm = hour24<13
},
value: @entangle($attributes->wire('model'))
}" x-init="() => {
onExternalValueChanged()
$watch('hourValue', () => { onInternalValueChanged() })
$watch('minuteValue', () => { onInternalValueChanged() })
$watch('isAm', () => { onInternalValueChanged() })
$watch('value', () => { onExternalValueChanged() })
}" class="flex space-x-1 items-center">
<label>
<div class="relative">
<button @click="hourOpen = !hourOpen" @click.away="hourOpen = false" type="button"
class="relative w-full cursor-default rounded-md border border-gray-300 bg-white py-1 pl-3 pr-6 text-left shadow-sm focus:border-cyan-500 focus:outline-none focus:ring-1 focus:ring-cyan-500 sm:text-sm">
<span class="block truncate w-6" x-text="hourValue"></span>
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<!-- Heroicon name: mini/chevron-up-down -->
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z"
clip-rule="evenodd"/>
</svg>
</span>
</button>
<ul x-show="hourOpen"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm" tabindex="-1" role="listbox">
<template x-for="option in hourOptions">
<li @click="selectHour(option)"
:class="isHourHighlighted(option) ? 'text-white bg-cyan-600' : (isHourSelected(option) ? 'bg-gray-200 text-gray-900' : 'text-gray-900')"
@mouseenter="highlightHourOption(option)"
@mouseleave="unHighlightHourOption(option)"
class="relative cursor-default select-none py-1 pl-3 pr-3" :id="'hour-option-' + option" role="option">
<span
:class="isHourSelected(option) ? 'font-bold' : 'font-normal'"
class="block truncate" x-text="option"></span>
</li>
</template>
</ul>
</div>
</label>
<label>
<div class="relative">
<button @click="minuteOpen = !minuteOpen" @click.away="minuteOpen = false" type="button"
class="relative w-full cursor-default rounded-md border border-gray-300 bg-white py-1 pl-3 pr-8 text-left shadow-sm focus:border-cyan-500 focus:outline-none focus:ring-1 focus:ring-cyan-500 sm:text-sm">
<span class="block truncate w-6" x-text="String(minuteValue).padStart(2, '0')"></span>
<span class="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<!-- Heroicon name: mini/chevron-up-down -->
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M10 3a.75.75 0 01.55.24l3.25 3.5a.75.75 0 11-1.1 1.02L10 4.852 7.3 7.76a.75.75 0 01-1.1-1.02l3.25-3.5A.75.75 0 0110 3zm-3.76 9.2a.75.75 0 011.06.04l2.7 2.908 2.7-2.908a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 01.04-1.06z"
clip-rule="evenodd"/>
</svg>
</span>
</button>
<ul x-show="minuteOpen"
x-transition:leave="transition ease-in duration-100"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm" tabindex="-1" role="listbox">
<template x-for="option in minuteOptions">
<li
@click="selectMinute(option)"
@mouseenter="highlightMinuteOption(option)"
@mouseleave="unHighlightMinuteOption(option)"
:class="isMinuteHighlighted(option) ? 'text-white bg-cyan-600' : (isMinuteSelected(option) ? 'bg-gray-200 text-gray-900' : 'text-gray-900')"
class="relative cursor-default select-none py-1 pl-3 pr-3" :id="'minute-option-' + option" role="option">
<span
:class="isMinuteSelected(option) ? 'font-bold' : 'font-normal'"
class="block truncate" x-text="String(option).padStart(2, '0')"></span>
</li>
</template>
</ul>
</div>
</label>
<div class="flex items-center"><button
@click="isAm = !isAm"
type="button"
:class="isAm ? 'bg-cyan-700' : 'bg-cyan-900'"
class="relative inline-flex h-6 w-14 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none"
role="switch">
<span
:class="isAm ? 'translate-x-0' : 'translate-x-8'"
class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out">
</span>
<div class="absolute inset-0 flex items-center font-bold text-xs text-white p-1" :class="isAm ? 'justify-end' : 'justify-start'">
<span x-show="isAm">AM</span>
<span x-show="!isAm">PM</span>
</div>
</button>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment