Refine calendar icon picker
This commit is contained in:
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -805,7 +805,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -864,7 +864,7 @@
|
|||||||
"offset1week": "1 semana antes",
|
"offset1week": "1 semana antes",
|
||||||
"offset2weeks": "2 semanas antes",
|
"offset2weeks": "2 semanas antes",
|
||||||
"offsetCustom": "Personalizado...",
|
"offsetCustom": "Personalizado...",
|
||||||
"customAmountLabel": "Quantidade",
|
"customAmountLabel": "Número",
|
||||||
"customUnitLabel": "Unidade",
|
"customUnitLabel": "Unidade",
|
||||||
"customMinutes": "Minutos",
|
"customMinutes": "Minutos",
|
||||||
"customHours": "Horas",
|
"customHours": "Horas",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -805,7 +805,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -863,7 +863,7 @@
|
|||||||
"offset1week": "1 week before",
|
"offset1week": "1 week before",
|
||||||
"offset2weeks": "2 weeks before",
|
"offset2weeks": "2 weeks before",
|
||||||
"offsetCustom": "Custom...",
|
"offsetCustom": "Custom...",
|
||||||
"customAmountLabel": "Amount",
|
"customAmountLabel": "Number",
|
||||||
"customUnitLabel": "Unit",
|
"customUnitLabel": "Unit",
|
||||||
"customMinutes": "Minutes",
|
"customMinutes": "Minutes",
|
||||||
"customHours": "Hours",
|
"customHours": "Hours",
|
||||||
|
|||||||
@@ -991,6 +991,48 @@ function openEventModal({ mode, event = null, date = null, reminder = null }) {
|
|||||||
|
|
||||||
bindDateInputs(panel);
|
bindDateInputs(panel);
|
||||||
|
|
||||||
|
const iconInput = panel.querySelector('#modal-icon');
|
||||||
|
const iconTrigger = panel.querySelector('#modal-icon-trigger');
|
||||||
|
const iconGrid = panel.querySelector('#modal-icon-grid');
|
||||||
|
const selectIcon = (icon) => {
|
||||||
|
const nextIcon = eventIconName(icon);
|
||||||
|
if (iconInput) iconInput.value = nextIcon;
|
||||||
|
if (iconTrigger) {
|
||||||
|
iconTrigger.dataset.icon = nextIcon;
|
||||||
|
const iconEl = iconTrigger.querySelector('[data-lucide]');
|
||||||
|
iconEl?.setAttribute('data-lucide', nextIcon);
|
||||||
|
}
|
||||||
|
iconGrid?.querySelectorAll('.event-icon-picker__option').forEach((btn) => {
|
||||||
|
const active = btn.dataset.icon === nextIcon;
|
||||||
|
btn.classList.toggle('event-icon-picker__option--active', active);
|
||||||
|
btn.setAttribute('aria-checked', active ? 'true' : 'false');
|
||||||
|
});
|
||||||
|
if (window.lucide) lucide.createIcons();
|
||||||
|
};
|
||||||
|
|
||||||
|
iconTrigger?.addEventListener('click', () => {
|
||||||
|
if (!iconGrid) return;
|
||||||
|
iconGrid.hidden = !iconGrid.hidden;
|
||||||
|
iconTrigger.setAttribute('aria-expanded', iconGrid.hidden ? 'false' : 'true');
|
||||||
|
});
|
||||||
|
iconGrid?.addEventListener('click', (e) => {
|
||||||
|
const btn = e.target.closest('.event-icon-picker__option');
|
||||||
|
if (!btn) return;
|
||||||
|
selectIcon(btn.dataset.icon);
|
||||||
|
iconGrid.hidden = true;
|
||||||
|
iconTrigger?.setAttribute('aria-expanded', 'false');
|
||||||
|
iconTrigger?.focus();
|
||||||
|
});
|
||||||
|
document.addEventListener('click', function closeIconPicker(e) {
|
||||||
|
if (!panel.isConnected) {
|
||||||
|
document.removeEventListener('click', closeIconPicker);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (iconGrid?.hidden || iconGrid?.contains(e.target) || iconTrigger?.contains(e.target)) return;
|
||||||
|
iconGrid.hidden = true;
|
||||||
|
iconTrigger?.setAttribute('aria-expanded', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
const reminderOffset = panel.querySelector('#modal-reminder-offset');
|
const reminderOffset = panel.querySelector('#modal-reminder-offset');
|
||||||
const reminderCustom = panel.querySelector('#modal-reminder-custom');
|
const reminderCustom = panel.querySelector('#modal-reminder-custom');
|
||||||
reminderOffset?.addEventListener('change', () => {
|
reminderOffset?.addEventListener('change', () => {
|
||||||
@@ -1021,8 +1063,16 @@ function buildEventModalContent({ mode, event, date, reminder = null }) {
|
|||||||
const endTime = isEdit && event.end_datetime && event.end_datetime.length > 10
|
const endTime = isEdit && event.end_datetime && event.end_datetime.length > 10
|
||||||
? localTime(event.end_datetime) : '10:00';
|
? localTime(event.end_datetime) : '10:00';
|
||||||
const selectedIcon = eventIconName(isEdit ? event.icon : 'calendar');
|
const selectedIcon = eventIconName(isEdit ? event.icon : 'calendar');
|
||||||
const iconOpts = EVENT_ICONS.map((icon) =>
|
const iconButtons = EVENT_ICONS.map((icon) =>
|
||||||
`<option value="${icon.value}" ${selectedIcon === icon.value ? 'selected' : ''}>${esc(icon.label)}</option>`
|
`<button type="button"
|
||||||
|
class="event-icon-picker__option ${selectedIcon === icon.value ? 'event-icon-picker__option--active' : ''}"
|
||||||
|
data-icon="${icon.value}"
|
||||||
|
role="radio"
|
||||||
|
aria-checked="${selectedIcon === icon.value ? 'true' : 'false'}"
|
||||||
|
aria-label="${esc(icon.label)}"
|
||||||
|
title="${esc(icon.label)}">
|
||||||
|
<i data-lucide="${icon.value}" aria-hidden="true"></i>
|
||||||
|
</button>`
|
||||||
).join('');
|
).join('');
|
||||||
|
|
||||||
const userOpts = [
|
const userOpts = [
|
||||||
@@ -1033,16 +1083,28 @@ function buildEventModalContent({ mode, event, date, reminder = null }) {
|
|||||||
].join('');
|
].join('');
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="modal-grid modal-grid--event-title">
|
<div class="event-title-picker">
|
||||||
<div class="form-group">
|
<div class="form-group event-icon-picker">
|
||||||
|
<label class="form-label" for="modal-icon-trigger">${t('calendar.iconLabel')}</label>
|
||||||
|
<input type="hidden" id="modal-icon" value="${selectedIcon}">
|
||||||
|
<button type="button"
|
||||||
|
class="event-icon-picker__trigger"
|
||||||
|
id="modal-icon-trigger"
|
||||||
|
data-icon="${selectedIcon}"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-label="${t('calendar.iconLabel')}">
|
||||||
|
<i data-lucide="${selectedIcon}" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-group event-title-picker__title">
|
||||||
<label class="form-label" for="modal-title">${t('calendar.titleLabel')}</label>
|
<label class="form-label" for="modal-title">${t('calendar.titleLabel')}</label>
|
||||||
<input type="text" class="form-input" id="modal-title"
|
<input type="text" class="form-input" id="modal-title"
|
||||||
placeholder="${t('calendar.titlePlaceholder')}" value="${esc(isEdit ? event.title : '')}">
|
placeholder="${t('calendar.titlePlaceholder')}" value="${esc(isEdit ? event.title : '')}">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label class="form-label" for="modal-icon">${t('calendar.iconLabel')}</label>
|
<div class="event-icon-picker__grid" id="modal-icon-grid" role="radiogroup" aria-label="${t('calendar.iconLabel')}" hidden>
|
||||||
<select class="form-input" id="modal-icon">${iconOpts}</select>
|
${iconButtons}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|||||||
@@ -544,14 +544,104 @@
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-grid--event-title {
|
.event-title-picker {
|
||||||
grid-template-columns: minmax(0, 1fr) 160px;
|
display: grid;
|
||||||
|
grid-template-columns: 72px minmax(0, 1fr);
|
||||||
|
gap: var(--space-3);
|
||||||
|
align-items: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-title-picker__title {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__trigger {
|
||||||
|
width: 52px;
|
||||||
|
height: 44px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
background: var(--color-surface);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color var(--transition-fast), background-color var(--transition-fast), transform var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__trigger:hover,
|
||||||
|
.event-icon-picker__trigger:focus-visible {
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
background: var(--color-accent-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__trigger:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__trigger i {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
|
||||||
|
gap: var(--space-2);
|
||||||
|
margin: calc(var(--space-2) * -1) 0 var(--space-4) 0;
|
||||||
|
padding: var(--space-3);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
background: var(--color-surface-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__grid[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__option {
|
||||||
|
height: 42px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
background: var(--color-surface);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color var(--transition-fast), color var(--transition-fast), background-color var(--transition-fast), transform var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__option:hover,
|
||||||
|
.event-icon-picker__option:focus-visible {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
border-color: var(--color-border);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__option--active {
|
||||||
|
color: var(--color-accent);
|
||||||
|
border-color: var(--color-accent);
|
||||||
|
background: var(--color-accent-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-picker__option i {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reminder-custom {
|
.reminder-custom {
|
||||||
margin-top: var(--space-3);
|
margin-top: var(--space-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reminder-custom[hidden] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.agenda-event__meta {
|
.agenda-event__meta {
|
||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
@@ -706,7 +796,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.modal-grid--event-title {
|
.event-title-picker {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -13,10 +13,10 @@
|
|||||||
* → bypassCacheUntil (in-memory + Cache API für SW-Restart-Robustheit)
|
* → bypassCacheUntil (in-memory + Cache API für SW-Restart-Robustheit)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const SHELL_CACHE = 'oikos-shell-v57';
|
const SHELL_CACHE = 'oikos-shell-v58';
|
||||||
const PAGES_CACHE = 'oikos-pages-v52';
|
const PAGES_CACHE = 'oikos-pages-v53';
|
||||||
const LOCALES_CACHE = 'oikos-locales-v4';
|
const LOCALES_CACHE = 'oikos-locales-v5';
|
||||||
const ASSETS_CACHE = 'oikos-assets-v52';
|
const ASSETS_CACHE = 'oikos-assets-v53';
|
||||||
const BYPASS_CACHE = 'oikos-bypass-flag';
|
const BYPASS_CACHE = 'oikos-bypass-flag';
|
||||||
const ALL_CACHES = [SHELL_CACHE, PAGES_CACHE, LOCALES_CACHE, ASSETS_CACHE];
|
const ALL_CACHES = [SHELL_CACHE, PAGES_CACHE, LOCALES_CACHE, ASSETS_CACHE];
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user