69 lines
1.8 KiB
JavaScript
69 lines
1.8 KiB
JavaScript
function createWorkSelection({ limit = 50, onChange = () => {} } = {}) {
|
|
const maximum = Number.isInteger(limit) && limit > 0 ? limit : 50;
|
|
let active = false;
|
|
const selected = new Set();
|
|
|
|
function identity(item) {
|
|
if (!item) return '';
|
|
const kind = item.is_review ? 'review' : (item.kind || 'work');
|
|
const number = Number.isInteger(item.number) ? item.number : '';
|
|
const notification = Number.isInteger(item.notification_id) ? item.notification_id : '';
|
|
return [kind, item.repository || '', number, notification].join(':');
|
|
}
|
|
|
|
function changed() {
|
|
const state = snapshot();
|
|
onChange(state);
|
|
return state;
|
|
}
|
|
|
|
function start() {
|
|
active = true;
|
|
selected.clear();
|
|
return changed();
|
|
}
|
|
|
|
function cancel() {
|
|
active = false;
|
|
selected.clear();
|
|
return changed();
|
|
}
|
|
|
|
function select(item) {
|
|
if (!active) return 'inactive';
|
|
const id = identity(item);
|
|
if (!id) return 'invalid';
|
|
if (selected.has(id)) return 'selected';
|
|
if (selected.size >= maximum) return 'limit';
|
|
selected.add(id);
|
|
changed();
|
|
return 'selected';
|
|
}
|
|
|
|
function toggle(item) {
|
|
if (!active) return 'inactive';
|
|
const id = identity(item);
|
|
if (!id) return 'invalid';
|
|
if (selected.has(id)) {
|
|
selected.delete(id);
|
|
changed();
|
|
return 'removed';
|
|
}
|
|
return select(item);
|
|
}
|
|
|
|
function retain(items) {
|
|
const retained = new Set((items || []).map(identity).filter(Boolean));
|
|
Array.from(selected).forEach(id => { if (!retained.has(id)) selected.delete(id); });
|
|
return changed();
|
|
}
|
|
|
|
function snapshot() {
|
|
return { active, count: selected.size, ids: Array.from(selected) };
|
|
}
|
|
|
|
return { identity, start, cancel, select, toggle, retain, snapshot, limit: maximum };
|
|
}
|
|
|
|
if (typeof module !== 'undefined' && module.exports) module.exports = createWorkSelection;
|