add utils to handle list multiselect / expand states

This commit is contained in:
jeffvli
2025-09-25 19:20:12 -07:00
parent 7a2af3d013
commit 3ed6d4b2f7
6 changed files with 638 additions and 124 deletions
@@ -0,0 +1,135 @@
import { ItemListAction, ItemListItem, ItemListState } from './item-list-state';
/**
* Action creators for item grid state management
* These can be reused across different components and contexts
*/
export const itemGridActions = {
clearAll: (): ItemListAction => ({
type: 'CLEAR_ALL',
}),
clearExpanded: (): ItemListAction => ({
type: 'CLEAR_EXPANDED',
}),
clearSelected: (): ItemListAction => ({
type: 'CLEAR_SELECTED',
}),
setExpanded: (items: ItemListItem[]): ItemListAction => ({
payload: items,
type: 'SET_EXPANDED',
}),
setSelected: (items: ItemListItem[]): ItemListAction => ({
payload: items,
type: 'SET_SELECTED',
}),
toggleExpanded: (item: ItemListItem): ItemListAction => ({
payload: item,
type: 'TOGGLE_EXPANDED',
}),
toggleSelected: (item: ItemListItem): ItemListAction => ({
payload: item,
type: 'TOGGLE_SELECTED',
}),
};
/**
* Selector functions for item grid state
* These can be reused to extract specific data from state
*/
export const itemGridSelectors = {
getExpanded: (state: ItemListState): ItemListItem[] => {
return Array.from(state.expandedItems.values());
},
getExpandedCount: (state: ItemListState): number => {
return state.expanded.size;
},
getExpandedIds: (state: ItemListState): string[] => {
return Array.from(state.expanded);
},
getSelected: (state: ItemListState): ItemListItem[] => {
return Array.from(state.selectedItems.values());
},
getSelectedCount: (state: ItemListState): number => {
return state.selected.size;
},
getSelectedIds: (state: ItemListState): string[] => {
return Array.from(state.selected);
},
getVersion: (state: ItemListState): number => {
return state.version;
},
hasAnyExpanded: (state: ItemListState): boolean => {
return state.expanded.size > 0;
},
hasAnySelected: (state: ItemListState): boolean => {
return state.selected.size > 0;
},
isExpanded: (state: ItemListState, itemId: string): boolean => {
return state.expanded.has(itemId);
},
isSelected: (state: ItemListState, itemId: string): boolean => {
return state.selected.has(itemId);
},
};
export const itemListUtils = {
/**
* Check if all items in a list are selected
*/
areAllSelected: (state: ItemListState, itemIds: string[]): boolean => {
return itemIds.every((id) => state.selected.has(id));
},
/**
* Check if any items in a list are selected
*/
areAnySelected: (state: ItemListState, itemIds: string[]): boolean => {
return itemIds.some((id) => state.selected.has(id));
},
/**
* Check if multiple items are expanded
*/
isMultiExpand: (state: ItemListState): boolean => {
return state.expanded.size > 1;
},
/**
* Check if multiple items are selected
*/
isMultiSelect: (state: ItemListState): boolean => {
return state.selected.size > 1;
},
/**
* Toggle expansion of all items in a list
*/
toggleAllExpanded: (items: ItemListItem[], currentState: ItemListState): ItemListAction => {
const allExpanded = items.every((item) => currentState.expanded.has(item.id));
return allExpanded ? itemGridActions.clearExpanded() : itemGridActions.setExpanded(items);
},
/**
* Toggle selection of all items in a list
*/
toggleAllSelected: (items: ItemListItem[], currentState: ItemListState): ItemListAction => {
const allSelected = items.every((item) => currentState.selected.has(item.id));
return allSelected ? itemGridActions.clearSelected() : itemGridActions.setSelected(items);
},
};