import { atom } from 'jotai'; import { atomFamily, selectAtom } from 'jotai/utils'; import { atomWithKVStorage } from '../../../lib/atoms/atomWithKVStorage'; // eslint-disable-next-line @typescript-eslint/no-unused-vars export const selectedIdsFamily = atomFamily((_treeId: string) => { return atom([]); }); export const isSelectedFamily = atomFamily( ({ treeId, itemId }: { treeId: string; itemId: string }) => { return selectAtom(selectedIdsFamily(treeId), (ids) => ids.includes(itemId), Object.is); }, (a, b) => a.treeId === b.treeId && a.itemId === b.itemId, ); // eslint-disable-next-line @typescript-eslint/no-unused-vars export const focusIdsFamily = atomFamily((_treeId: string) => { return atom<{ lastId: string | null; anchorId: string | null }>({ lastId: null, anchorId: null }); }); export const isLastFocusedFamily = atomFamily( ({ treeId, itemId }: { treeId: string; itemId: string }) => selectAtom(focusIdsFamily(treeId), (v) => v.lastId === itemId, Object.is), (a, b) => a.treeId === b.treeId && a.itemId === b.itemId, ); // eslint-disable-next-line @typescript-eslint/no-unused-vars export const draggingIdsFamily = atomFamily((_treeId: string) => { return atom([]); }); // eslint-disable-next-line @typescript-eslint/no-unused-vars export const hoveredParentFamily = atomFamily((_treeId: string) => { return atom<{ index: number | null; childIndex: number | null; parentId: string | null; parentDepth: number | null; }>({ index: null, childIndex: null, parentId: null, parentDepth: null, }); }); export const isParentHoveredFamily = atomFamily( ({ treeId, parentId }: { treeId: string; parentId: string | null }) => selectAtom(hoveredParentFamily(treeId), (v) => v.parentId === parentId, Object.is), (a, b) => a.treeId === b.treeId && a.parentId === b.parentId, ); export const isAncestorHoveredFamily = atomFamily( ({ treeId, ancestorIds }: { treeId: string; ancestorIds: string[] }) => selectAtom( hoveredParentFamily(treeId), (v) => v.parentId && ancestorIds.includes(v.parentId), Object.is, ), (a, b) => a.treeId === b.treeId && a.ancestorIds.join(',') === b.ancestorIds.join(','), ); export const isIndexHoveredFamily = atomFamily( ({ treeId, index }: { treeId: string; index: number }) => selectAtom(hoveredParentFamily(treeId), (v) => v.index === index, Object.is), (a, b) => a.treeId === b.treeId && a.index === b.index, ); export const hoveredParentDepthFamily = atomFamily((treeId: string) => selectAtom( hoveredParentFamily(treeId), (s) => s.parentDepth, (a, b) => Object.is(a, b), // prevents re-render unless the value changes ), ); export const collapsedFamily = atomFamily((workspaceId: string) => { const key = ['sidebar_collapsed', workspaceId ?? 'n/a']; return atomWithKVStorage>(key, {}); }); export const isCollapsedFamily = atomFamily( ({ treeId, itemId = 'n/a' }: { treeId: string; itemId: string | undefined }) => atom( // --- getter --- (get) => !!get(collapsedFamily(treeId))[itemId], // --- setter --- (get, set, next: boolean | ((prev: boolean) => boolean)) => { const a = collapsedFamily(treeId); const prevMap = get(a); const prevValue = !!prevMap[itemId]; const value = typeof next === 'function' ? next(prevValue) : next; if (value === prevValue) return; // no-op set(a, { ...prevMap, [itemId]: value }); }, ), (a, b) => a.treeId === b.treeId && a.itemId === b.itemId, );