diff --git a/src/internalState/normalizeExpanded.ts b/src/internalState/normalizeExpanded.ts new file mode 100644 index 0000000..d2363cb --- /dev/null +++ b/src/internalState/normalizeExpanded.ts @@ -0,0 +1,44 @@ +import { useEffect } from 'react'; +import { Store } from 'schummar-state/react'; +import { getAncestors } from '../misc/helpers'; +import { InternalTableState } from '../types'; + +export function normalizeExpanded(table: Store>): void { + useEffect( + () => + table.addReaction( + (state) => [state.props.expandOnlyOne, state.expanded, state.itemsById] as const, + ([expandOnlyOne, , itemsById], state) => { + let expanded = state.expanded; + let last, lastItem; + let hasChanged = false; + + // If only one branch may be expanded, check if there are more and close if necessary + if (expandOnlyOne && (last = [...expanded][expanded.size - 1]) && (lastItem = itemsById.get(last))) { + const ancestors = getAncestors(itemsById, lastItem); + if ([...expanded].slice(0, -1).some((id) => !ancestors.has(id))) { + expanded = state.expanded = new Set([...ancestors].concat(last)); + hasChanged = true; + } + } else { + for (const id of expanded) { + const item = itemsById.get(id); + const ancestors = item && getAncestors(itemsById, item); + for (const ancestor of ancestors ?? []) { + if (!expanded.has(ancestor)) { + expanded.add(ancestor); + hasChanged = true; + } + } + } + } + + if (hasChanged) { + state.props.onExpandedChange?.(new Set(expanded)); + } + }, + { runNow: true }, + ), + [table], + ); +} diff --git a/src/internalState/useTableState.ts b/src/internalState/useTableState.ts index aee8b0c..4cae427 100644 --- a/src/internalState/useTableState.ts +++ b/src/internalState/useTableState.ts @@ -6,6 +6,7 @@ import { calcItems } from './calcItems'; import { calcProps } from './calcProps'; import { cleanupState } from './cleanupState'; import { filterColumns } from './filterColumns'; +import { normalizeExpanded } from './normalizeExpanded'; import { syncSelections } from './syncSelections'; export function useTableState(_props: TableProps): Store> { @@ -38,6 +39,7 @@ export function useTableState(_props: TableProps): Store