wip: replace flatpickr
This commit is contained in:
1 parent
e902a5e298
commit
2cc9269236
5 files changed
+80
-58
No files matched your search
@@ -1,56 +1,70 @@
|
||||
import { Controller } from '@hotwired/stimulus'
|
||||
import flatpickr from 'flatpickr';
|
||||
import { German } from 'flatpickr/dist/l10n/de';
|
||||
import { Calendar } from 'vanilla-calendar-pro'
|
||||
|
||||
/* stimulusFetch: 'lazy' */
|
||||
export default class extends Controller {
|
||||
|
||||
static targets = [ 'field' ]
|
||||
static targets = ['field', 'hiddenField']
|
||||
static values = {
|
||||
minDate: String,
|
||||
maxDate: String,
|
||||
disableWeekends: Boolean,
|
||||
}
|
||||
|
||||
initialize() {
|
||||
flatpickr.localize(German)
|
||||
disabledDates: Array,
|
||||
}
|
||||
|
||||
connect() {
|
||||
const minDate = this.minDateValue
|
||||
const maxDate = this.maxDateValue
|
||||
const options = {
|
||||
dateFormat: 'Y-m-d',
|
||||
altFormat: 'd.m.Y',
|
||||
minDate,
|
||||
maxDate,
|
||||
altInput: true,
|
||||
allowInput: true,
|
||||
onClose(dates, currentdatestring, instance) {
|
||||
instance.setDate(instance.altInput.value, true, instance.config.altFormat)
|
||||
this.element.dispatchEvent(new CustomEvent('datepicker:closed'))
|
||||
},
|
||||
onChange(dates, currentdatestring, instance) {
|
||||
inputMode: true,
|
||||
locale: 'de-DE',
|
||||
selectedTheme: 'light',
|
||||
selectedDates: this.hiddenFieldTarget.value ? [this.hiddenFieldTarget.value] : [],
|
||||
onClickDate: (self) => {
|
||||
const iso = self.context.selectedDates[0] ?? null
|
||||
this.hiddenFieldTarget.value = iso ?? ''
|
||||
if (iso) {
|
||||
const [year, month, day] = iso.split('-')
|
||||
this.fieldTarget.value = `${day}.${month}.${year}`
|
||||
} else {
|
||||
this.fieldTarget.value = ''
|
||||
}
|
||||
this.element.dispatchEvent(new CustomEvent('datepicker:picked', {
|
||||
detail: {
|
||||
date: instance.altInput.value
|
||||
}
|
||||
detail: { date: this.fieldTarget.value }
|
||||
}))
|
||||
},
|
||||
onHide: () => {
|
||||
this.element.dispatchEvent(new CustomEvent('datepicker:closed'))
|
||||
},
|
||||
}
|
||||
|
||||
if (true === this.disableWeekendsValue) {
|
||||
options['disable'] = [
|
||||
function(date) {
|
||||
return (date.getDay() === 0 || date.getDay() === 6);
|
||||
if (this.minDateValue) options.dateMin = this.minDateValue
|
||||
if (this.maxDateValue) options.dateMax = this.maxDateValue
|
||||
if (this.disableWeekendsValue) options.disableWeekdays = [0, 6]
|
||||
if (this.disabledDatesValue.length) options.disableDates = this.disabledDatesValue
|
||||
|
||||
this.picker = new Calendar(this.fieldTarget, options)
|
||||
this.picker.init()
|
||||
|
||||
this.handleManualInput = () => {
|
||||
const value = this.fieldTarget.value.trim()
|
||||
if (!value) {
|
||||
this.hiddenFieldTarget.value = ''
|
||||
this.picker.set({ selectedDates: [] }, { dates: true })
|
||||
} else {
|
||||
const match = value.match(/^(\d{1,2})\.(\d{1,2})\.(\d{4})$/)
|
||||
if (match) {
|
||||
const [, day, month, year] = match
|
||||
const iso = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`
|
||||
this.hiddenFieldTarget.value = iso
|
||||
this.picker.set({ selectedDates: [iso] }, { dates: true })
|
||||
}
|
||||
]
|
||||
}
|
||||
this.element.dispatchEvent(new CustomEvent('datepicker:closed'))
|
||||
}
|
||||
|
||||
this.picker = flatpickr(this.fieldTarget, options)
|
||||
this.fieldTarget.addEventListener('change', this.handleManualInput)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.fieldTarget.removeEventListener('change', this.handleManualInput)
|
||||
this.picker.destroy()
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,7 @@
|
||||
@import "flatpickr/dist/flatpickr.css";
|
||||
@import "vanilla-calendar-pro/styles/index.css";
|
||||
@import "vanilla-calendar-pro/styles/themes/light.css";
|
||||
|
||||
.flatpickr-day.selected,
|
||||
.flatpickr-day.selected:hover,
|
||||
.flatpickr-day.selected:focus {
|
||||
[data-vc-theme=light] .vc-date[data-vc-date-selected] .vc-date__btn,
|
||||
[data-vc-theme=light] .vc-date[data-vc-date-selected] .vc-date__btn:hover {
|
||||
background-color: theme('colors.secondary');
|
||||
border-color: theme('colors.secondary');
|
||||
}
|
||||
|
||||
.flatpickr-monthDropdown-months,
|
||||
.flatpickr-current-month .flatpickr-monthDropdown-months {
|
||||
@apply form-select pt-0 pb-0 focus:outline-none focus:shadow-none;
|
||||
}
|
||||
Generated
+12
-8
@@ -8,9 +8,9 @@
|
||||
"license": "WTFPL",
|
||||
"dependencies": {
|
||||
"@trevoreyre/autocomplete-js": "^3.0.3",
|
||||
"flatpickr": "^4.6.13",
|
||||
"sortablejs": "^1.15.7",
|
||||
"stimulus-use": "^0.52.3"
|
||||
"stimulus-use": "^0.52.3",
|
||||
"vanilla-calendar-pro": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.0",
|
||||
@@ -4393,12 +4393,6 @@
|
||||
"flat": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/flatpickr": {
|
||||
"version": "4.6.13",
|
||||
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
|
||||
"integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/forever-agent": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||
@@ -8563,6 +8557,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vanilla-calendar-pro": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vanilla-calendar-pro/-/vanilla-calendar-pro-3.1.0.tgz",
|
||||
"integrity": "sha512-yXDtCaedcKz6i5OOdWGwui0C8MAmjXjj7JzKZyjDlkczSRqnhI8BDGFygqT2K+qL1uY7R2fLYlTlxA6oyFs2yg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://buymeacoffee.com/uvarov"
|
||||
}
|
||||
},
|
||||
"node_modules/verror": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@trevoreyre/autocomplete-js": "^3.0.3",
|
||||
"flatpickr": "^4.6.13",
|
||||
"vanilla-calendar-pro": "^3.1.0",
|
||||
"sortablejs": "^1.15.7",
|
||||
"stimulus-use": "^0.52.3"
|
||||
}
|
||||
|
||||
@@ -162,21 +162,31 @@
|
||||
{%- block datepicker_widget -%}
|
||||
{%- set minDate = form.vars.min_date ? form.vars.min_date | date('Y-m-d') : null -%}
|
||||
{%- set maxDate = form.vars.max_date ? form.vars.max_date | date('Y-m-d') : null -%}
|
||||
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset text-sm')|trim }) -%}
|
||||
{%- set displayValue = value ? value|date('d.m.Y') : '' -%}
|
||||
{%- set inputClass = 'block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset text-sm' -%}
|
||||
{%- if errors|length -%}
|
||||
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder:red-500 focus:ring-red-500' }) -%}
|
||||
{% else %}
|
||||
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-gray-900 focus:ring-primary' }) -%}
|
||||
{%- set inputClass = inputClass ~ ' ring-red-500 placeholder:red-500 focus:ring-red-500' -%}
|
||||
{%- else -%}
|
||||
{%- set inputClass = inputClass ~ ' placeholder:text-gray-900 focus:ring-primary' -%}
|
||||
{%- endif -%}
|
||||
{%- if disabled is defined and disabled == true -%}
|
||||
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
|
||||
{%- set inputClass = inputClass ~ ' cursor-not-allowed' -%}
|
||||
{%- endif -%}
|
||||
<div {{ stimulus_controller('datepicker', { 'minDate': minDate, 'maxDate': maxDate, 'disableWeekends': form.vars.disable_weekends }) }}>
|
||||
<input type="text" name="{{ form.vars.full_name }}" value="{{ value }}" {{ block('widget_attributes') }} {{ stimulus_target('datepicker', 'field') }} />
|
||||
<input type="text"
|
||||
id="{{ id }}"
|
||||
class="{{ inputClass }}"
|
||||
value="{{ displayValue }}"
|
||||
{% if attr.placeholder is defined %}placeholder="{{ attr.placeholder }}"{% endif %}
|
||||
{% if attr['aria-describedby'] is defined %}aria-describedby="{{ attr['aria-describedby'] }}"{% endif %}
|
||||
{% if required %}required{% endif %}
|
||||
{% if disabled is defined and disabled %}disabled{% endif %}
|
||||
{{ stimulus_target('datepicker', 'field') }} />
|
||||
<input type="hidden"
|
||||
name="{{ form.vars.full_name }}"
|
||||
value="{{ value }}"
|
||||
{{ stimulus_target('datepicker', 'hiddenField') }} />
|
||||
</div>
|
||||
{%- if disabled is defined and disabled == true -%}
|
||||
<input type="hidden" name="{{ form.vars.full_name }}" value="{{ value }}">
|
||||
{%- endif -%}
|
||||
{%- endblock datepicker_widget %}
|
||||
|
||||
{%- block autocomplete_widget -%}
|
||||
|
||||
Reference in new issue
Block a user