116 lines
4.1 KiB
JavaScript
116 lines
4.1 KiB
JavaScript
(function (root, factory) {
|
|
if (typeof module === 'object' && module.exports) module.exports = factory;
|
|
else root.createMobileTaskDock = factory;
|
|
})(typeof self !== 'undefined' ? self : this, function createMobileTaskDock(options) {
|
|
const nav = options.nav;
|
|
const buttons = options.buttons;
|
|
const overlays = options.overlays || [];
|
|
let launcher = null;
|
|
let wasHidden = false;
|
|
|
|
function select(name) {
|
|
if (!buttons[name]) return false;
|
|
Object.entries(buttons).forEach(([key, button]) => {
|
|
if (key === name) button.setAttribute('aria-current', 'page');
|
|
else button.removeAttribute('aria-current');
|
|
});
|
|
return true;
|
|
}
|
|
|
|
function refreshVisibility() {
|
|
const hidden = overlays.some(overlay => overlay.open || overlay.classList.contains('open'));
|
|
nav.hidden = hidden;
|
|
if (options.sessionHud) {
|
|
if (hidden) options.sessionHud.setAttribute('data-overlay-hidden', 'true');
|
|
else options.sessionHud.removeAttribute('data-overlay-hidden');
|
|
}
|
|
if (wasHidden && !hidden && launcher) launcher.focus();
|
|
wasHidden = hidden;
|
|
}
|
|
|
|
function openQueues() {
|
|
if (!options.queueSheet || options.queueSheet.open) return;
|
|
options.queueSheet.showModal();
|
|
}
|
|
|
|
function closeQueues() {
|
|
options.queueSheet?.open && options.queueSheet.close();
|
|
}
|
|
|
|
function start() {
|
|
Object.entries(buttons).forEach(([name, button]) => {
|
|
button.addEventListener('click', event => {
|
|
launcher = event.currentTarget;
|
|
select(name);
|
|
name === 'queues' && options.queueSheet ? openQueues() : options.actions[name]();
|
|
});
|
|
});
|
|
if (options.queueSheet) {
|
|
options.queueClose?.addEventListener('click', closeQueues);
|
|
options.queueSheet.addEventListener('cancel', event => {
|
|
event.preventDefault();
|
|
closeQueues();
|
|
});
|
|
options.queueSheet.addEventListener('close', () => buttons.queues?.focus());
|
|
Object.entries(options.queueRows || {}).forEach(([name, row]) => {
|
|
row.addEventListener('click', () => {
|
|
closeQueues();
|
|
options.onSelectQueue?.(name, row);
|
|
});
|
|
});
|
|
}
|
|
options.observe(refreshVisibility, overlays);
|
|
refreshVisibility();
|
|
}
|
|
|
|
function updateWork(mode) {
|
|
const labels = {
|
|
continue: ['Continue', 'Continue Today'],
|
|
resume: ['Resume', 'Resume Today'],
|
|
start: ['Start', 'Start Today'],
|
|
plan: ['Plan', 'Plan Today'],
|
|
find: ['Find', 'Find work'],
|
|
work: ['Work', 'Work'],
|
|
};
|
|
const workMode = labels[mode] ? mode : 'work';
|
|
if (options.workLabel) options.workLabel.textContent = labels[workMode][0];
|
|
if (buttons.work) {
|
|
buttons.work.setAttribute('aria-label', labels[workMode][1]);
|
|
}
|
|
}
|
|
|
|
function updateAttention(count) {
|
|
const total = Math.max(0, Number(count) || 0);
|
|
const visible = total > 0;
|
|
if (options.attentionBadge) {
|
|
options.attentionBadge.textContent = String(total);
|
|
options.attentionBadge.hidden = !visible;
|
|
}
|
|
if (buttons.attention) {
|
|
buttons.attention.hidden = !visible;
|
|
buttons.attention.setAttribute('aria-label', 'Attention, ' + total + ' items');
|
|
}
|
|
if (visible) nav.setAttribute('data-attention', 'true');
|
|
else nav.removeAttribute('data-attention');
|
|
}
|
|
|
|
function updateQueues(counts) {
|
|
const names = 'today agenda attention update later draft'.split(' ');
|
|
const normalized = Object.fromEntries(names.map(name => [name, Math.max(0, Number(counts?.[name]) || 0)]));
|
|
const total = ['today', 'attention', 'later', 'draft'].reduce((sum, name) => sum + normalized[name], 0);
|
|
Object.entries(options.queueCounts || {}).forEach(([name, element]) => {
|
|
element.textContent = String(normalized[name] || 0);
|
|
});
|
|
options.queueRows?.update?.setAttribute(
|
|
'aria-label', 'Updates, ' + normalized.update + ' unread conversations'
|
|
);
|
|
if (options.queueBadge) {
|
|
options.queueBadge.textContent = String(total);
|
|
options.queueBadge.hidden = total === 0;
|
|
}
|
|
buttons.queues?.setAttribute('aria-label', 'Queues, ' + total + ' items');
|
|
}
|
|
|
|
return {start, select, refreshVisibility, updateAttention, updateQueues, updateWork};
|
|
});
|