feat(frontend): pure helpers for cross-subject plot interactions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
// Pure helpers for the cross-subject metrics plot interactions. No React, no I/O.
|
||||
|
||||
// Sort a Recharts tooltip payload by numeric value descending, dropping entries
|
||||
// whose value is null/undefined. Returns a NEW array (does not mutate input).
|
||||
export function sortPayloadByValueDesc(payload) {
|
||||
if (!Array.isArray(payload)) return [];
|
||||
return payload
|
||||
.filter((p) => p && p.value != null)
|
||||
.sort((a, b) => b.value - a.value);
|
||||
}
|
||||
|
||||
// Toggle an id's membership in a Set, returning a NEW Set.
|
||||
export function toggleInSet(set, id) {
|
||||
const next = new Set(set);
|
||||
if (next.has(id)) next.delete(id);
|
||||
else next.add(id);
|
||||
return next;
|
||||
}
|
||||
|
||||
// Add (hidden=true) or remove (hidden=false) a list of ids from a hidden-set.
|
||||
// Returns a NEW Set.
|
||||
export function setIdsHidden(set, ids, hidden) {
|
||||
const next = new Set(set);
|
||||
for (const id of ids) {
|
||||
if (hidden) next.add(id);
|
||||
else next.delete(id);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
// Tri-state for a group checkbox given which subject ids are hidden.
|
||||
// 'all' = all visible, 'none' = all hidden, 'some' = mixed.
|
||||
export function groupVisibilityState(subjectIds, hiddenSet) {
|
||||
if (subjectIds.length === 0) return 'none';
|
||||
const hiddenCount = subjectIds.filter((id) => hiddenSet.has(id)).length;
|
||||
if (hiddenCount === 0) return 'all';
|
||||
if (hiddenCount === subjectIds.length) return 'none';
|
||||
return 'some';
|
||||
}
|
||||
|
||||
// Group chart "lines" by their .group field, preserving first-seen group order
|
||||
// and line order within each group. Returns [{ group, subjects: [line...] }].
|
||||
export function groupLines(lines) {
|
||||
const order = [];
|
||||
const byGroup = new Map();
|
||||
for (const line of lines) {
|
||||
const g = line.group ?? '—';
|
||||
if (!byGroup.has(g)) { byGroup.set(g, []); order.push(g); }
|
||||
byGroup.get(g).push(line);
|
||||
}
|
||||
return order.map((group) => ({ group, subjects: byGroup.get(group) }));
|
||||
}
|
||||
Reference in New Issue
Block a user