+ ? { ...file, collapsed: !file.collapsed }
+ : file);
+
+const toggleSelected = (state: CollectionPanelFilesState, id: string) =>
+ toggleAncestors(toggleDescendants(state, id), id);
+
+const toggleDescendants = (state: CollectionPanelFilesState, id: string) => {
+ const ids = getDescendants(state)({ id }).map(file => file.id);
+ if (ids.length > 0) {
+ const selected = !state.find(f => f.id === ids[0])!.selected;
+ return state.map(file => ids.some(id => file.id === id) ? { ...file, selected } : file);
+ }
+ return state;
+};
+
+const toggleAncestors = (state: CollectionPanelFilesState, id: string): CollectionPanelFile[] => {
+ const file = state.find(f => f.id === id);
+ if (file) {
+ const selected = state
+ .filter(f => f.parentId === file.parentId)
+ .every(f => f.selected);
+ if (!selected) {
+ const newState = state.map(f => f.id === file.parentId ? { ...f, selected } : f);
+ return toggleAncestors(newState, file.parentId || "");
+ }
+ }
+ return state;
+};
+
+const getDescendants = (state: CollectionPanelFilesState) => ({ id }: { id: string }): CollectionPanelFile[] => {
+ const root = state.find(f => f.id === id);
+ if (root) {
+ return [root].concat(...state.filter(f => f.parentId === id).map(getDescendants(state)));
+ } else { return []; }
+};
+