trans2 / ui /lib /stores /selectionStore.ts
Mayo
refactor(ui): backend-as-truth state layer (ops / io / stores / events)
e5d8e6a unverified
'use client'
import { create } from 'zustand'
/**
* Page + node selection. Multi-select via `nodeIds: Set<string>`; the Navigator
* and hotkeys read `pageId`; component interactions read `nodeIds`.
*/
type SelectionState = {
pageId: string | null
nodeIds: Set<string>
setPage: (id: string | null) => void
select: (id: string, additive?: boolean) => void
selectMany: (ids: string[]) => void
deselect: (id: string) => void
clear: () => void
isSelected: (id: string) => boolean
}
export const useSelectionStore = create<SelectionState>((set, get) => ({
pageId: null,
nodeIds: new Set(),
setPage: (id) =>
set(() => ({
pageId: id,
// Clear selection when the page changes — node ids are page-scoped.
nodeIds: new Set(),
})),
select: (id, additive) =>
set((state) => {
if (additive) {
const next = new Set(state.nodeIds)
if (next.has(id)) next.delete(id)
else next.add(id)
return { nodeIds: next }
}
return { nodeIds: new Set([id]) }
}),
selectMany: (ids) => set(() => ({ nodeIds: new Set(ids) })),
deselect: (id) =>
set((state) => {
if (!state.nodeIds.has(id)) return state
const next = new Set(state.nodeIds)
next.delete(id)
return { nodeIds: next }
}),
clear: () => set({ nodeIds: new Set() }),
isSelected: (id) => get().nodeIds.has(id),
}))