/** * LEDMatrix Date Picker Widget * * Date selection with optional min/max constraints. * * Schema example: * { * "startDate": { * "type": "string", * "format": "date", * "x-widget": "date-picker", * "x-options": { * "min": "2024-01-01", * "max": "2025-12-31", * "placeholder": "Select date", * "clearable": true * } * } * } * * @module DatePickerWidget */ (function() { 'use strict'; const base = window.BaseWidget ? new window.BaseWidget('DatePicker', '1.0.0') : null; function escapeHtml(text) { if (base) return base.escapeHtml(text); const div = document.createElement('div'); div.textContent = String(text); return div.innerHTML.replace(/"/g, '"').replace(/'/g, '''); } function sanitizeId(id) { if (base) return base.sanitizeId(id); return String(id).replace(/[^a-zA-Z0-9_-]/g, '_'); } function triggerChange(fieldId, value) { if (base) { base.triggerChange(fieldId, value); } else { const event = new CustomEvent('widget-change', { detail: { fieldId, value }, bubbles: true, cancelable: true }); document.dispatchEvent(event); } } window.LEDMatrixWidgets.register('date-picker', { name: 'Date Picker Widget', version: '1.0.0', render: function(container, config, value, options) { const fieldId = sanitizeId(options.fieldId || container.id || 'date_picker'); const xOptions = config['x-options'] || config['x_options'] || {}; const min = xOptions.min || config.minimum || ''; const max = xOptions.max || config.maximum || ''; const placeholder = xOptions.placeholder || ''; const clearable = xOptions.clearable === true; const disabled = xOptions.disabled === true; const required = xOptions.required === true; const currentValue = value || ''; let html = `
`; html += '
'; html += `
`; if (clearable && !disabled) { html += ` `; } html += '
'; // Date constraint info if (min || max) { let constraintText = ''; if (min && max) { constraintText = `${min} to ${max}`; } else if (min) { constraintText = `From ${min}`; } else { constraintText = `Until ${max}`; } html += `
${escapeHtml(constraintText)}
`; } // Error message area html += ``; html += '
'; container.innerHTML = html; }, getValue: function(fieldId) { const safeId = sanitizeId(fieldId); const input = document.getElementById(`${safeId}_input`); return input ? input.value : ''; }, setValue: function(fieldId, value) { const safeId = sanitizeId(fieldId); const input = document.getElementById(`${safeId}_input`); const clearBtn = document.getElementById(`${safeId}_clear`); if (input) { input.value = value || ''; } if (clearBtn) { clearBtn.classList.toggle('hidden', !value); } }, validate: function(fieldId) { const safeId = sanitizeId(fieldId); const input = document.getElementById(`${safeId}_input`); const errorEl = document.getElementById(`${safeId}_error`); if (!input) return { valid: true, errors: [] }; const isValid = input.checkValidity(); if (errorEl) { if (!isValid) { errorEl.textContent = input.validationMessage; errorEl.classList.remove('hidden'); input.classList.add('border-red-500'); } else { errorEl.classList.add('hidden'); input.classList.remove('border-red-500'); } } return { valid: isValid, errors: isValid ? [] : [input.validationMessage] }; }, handlers: { onChange: function(fieldId) { const widget = window.LEDMatrixWidgets.get('date-picker'); const safeId = sanitizeId(fieldId); const clearBtn = document.getElementById(`${safeId}_clear`); const value = widget.getValue(fieldId); if (clearBtn) { clearBtn.classList.toggle('hidden', !value); } widget.validate(fieldId); triggerChange(fieldId, value); }, onClear: function(fieldId) { const widget = window.LEDMatrixWidgets.get('date-picker'); widget.setValue(fieldId, ''); triggerChange(fieldId, ''); } } }); console.log('[DatePickerWidget] Date picker widget registered'); })();