mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-10 04:30:25 +02:00
enforce data order in list selection
This commit is contained in:
@@ -8,7 +8,7 @@ import {
|
|||||||
* Action creators for item grid state management
|
* Action creators for item grid state management
|
||||||
* These can be reused across different components and contexts
|
* These can be reused across different components and contexts
|
||||||
*/
|
*/
|
||||||
export const itemGridActions = {
|
export const itemListActions = {
|
||||||
clearAll: (): ItemListAction => ({
|
clearAll: (): ItemListAction => ({
|
||||||
type: 'CLEAR_ALL',
|
type: 'CLEAR_ALL',
|
||||||
}),
|
}),
|
||||||
@@ -71,7 +71,7 @@ export const itemGridActions = {
|
|||||||
* Selector functions for item grid state
|
* Selector functions for item grid state
|
||||||
* These can be reused to extract specific data from state
|
* These can be reused to extract specific data from state
|
||||||
*/
|
*/
|
||||||
export const itemGridSelectors = {
|
export const itemListSelectors = {
|
||||||
getDragging: (state: ItemListState): unknown[] => {
|
getDragging: (state: ItemListState): unknown[] => {
|
||||||
return Array.from(state.draggingItems.values());
|
return Array.from(state.draggingItems.values());
|
||||||
},
|
},
|
||||||
@@ -179,8 +179,8 @@ export const itemListUtils = {
|
|||||||
return rowId ? currentState.expanded.has(rowId) : false;
|
return rowId ? currentState.expanded.has(rowId) : false;
|
||||||
});
|
});
|
||||||
return allExpanded
|
return allExpanded
|
||||||
? itemGridActions.clearExpanded()
|
? itemListActions.clearExpanded()
|
||||||
: itemGridActions.setExpanded(items, extractRowId);
|
: itemListActions.setExpanded(items, extractRowId);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -196,7 +196,7 @@ export const itemListUtils = {
|
|||||||
return rowId ? currentState.selected.has(rowId) : false;
|
return rowId ? currentState.selected.has(rowId) : false;
|
||||||
});
|
});
|
||||||
return allSelected
|
return allSelected
|
||||||
? itemGridActions.clearSelected()
|
? itemListActions.clearSelected()
|
||||||
: itemGridActions.setSelected(items, extractRowId);
|
: itemListActions.setSelected(items, extractRowId);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,36 @@
|
|||||||
import { useCallback, useMemo, useReducer } from 'react';
|
import { useCallback, useMemo, useReducer } from 'react';
|
||||||
|
|
||||||
import { itemGridSelectors } from '/@/renderer/components/item-list/helpers/item-list-reducer-utils';
|
import { itemListSelectors } from '/@/renderer/components/item-list/helpers/item-list-reducer-utils';
|
||||||
import { LibraryItem } from '/@/shared/types/domain-types';
|
import { LibraryItem } from '/@/shared/types/domain-types';
|
||||||
|
|
||||||
|
const sortByDataOrder = <T>(
|
||||||
|
items: T[],
|
||||||
|
data: unknown[],
|
||||||
|
extractRowId: (item: unknown) => string | undefined,
|
||||||
|
isIdArray: boolean,
|
||||||
|
): T[] => {
|
||||||
|
const rowIdToIndex = new Map<string, number>();
|
||||||
|
|
||||||
|
// Create a map of rowId to index in the data array
|
||||||
|
data.forEach((item, index) => {
|
||||||
|
if (item && typeof item === 'object') {
|
||||||
|
const itemRowId = extractRowId(item);
|
||||||
|
if (itemRowId) {
|
||||||
|
rowIdToIndex.set(itemRowId, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort items by their index in the data array (create new array to avoid mutation)
|
||||||
|
return [...items].sort((a, b) => {
|
||||||
|
const rowIdA = isIdArray ? (a as string) : extractRowId(a as unknown);
|
||||||
|
const rowIdB = isIdArray ? (b as string) : extractRowId(b as unknown);
|
||||||
|
const indexA = rowIdA ? (rowIdToIndex.get(rowIdA) ?? Infinity) : Infinity;
|
||||||
|
const indexB = rowIdB ? (rowIdToIndex.get(rowIdB) ?? Infinity) : Infinity;
|
||||||
|
return indexA - indexB;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export type ItemListAction =
|
export type ItemListAction =
|
||||||
| {
|
| {
|
||||||
extractRowId: (item: unknown) => string | undefined;
|
extractRowId: (item: unknown) => string | undefined;
|
||||||
@@ -330,29 +358,31 @@ export const useItemListState = (
|
|||||||
|
|
||||||
const isExpanded = useCallback(
|
const isExpanded = useCallback(
|
||||||
(rowId: string) => {
|
(rowId: string) => {
|
||||||
return itemGridSelectors.isExpanded(state, rowId);
|
return itemListSelectors.isExpanded(state, rowId);
|
||||||
},
|
},
|
||||||
[state],
|
[state],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isSelected = useCallback(
|
const isSelected = useCallback(
|
||||||
(rowId: string) => {
|
(rowId: string) => {
|
||||||
return itemGridSelectors.isSelected(state, rowId);
|
return itemListSelectors.isSelected(state, rowId);
|
||||||
},
|
},
|
||||||
[state],
|
[state],
|
||||||
);
|
);
|
||||||
|
|
||||||
const getExpanded = useCallback(() => {
|
const getExpanded = useCallback(() => {
|
||||||
return itemGridSelectors.getExpanded(state);
|
return itemListSelectors.getExpanded(state);
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
const getDragging = useCallback(() => {
|
const getDragging = useCallback(() => {
|
||||||
return itemGridSelectors.getDragging(state);
|
return itemListSelectors.getDragging(state);
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
const getSelected = useCallback(() => {
|
const getSelected = useCallback(() => {
|
||||||
return itemGridSelectors.getSelected(state);
|
const selectedItems = itemListSelectors.getSelected(state);
|
||||||
}, [state]);
|
const data = getDataFn ? getDataFn() : [];
|
||||||
|
return sortByDataOrder(selectedItems, data, extractRowIdFn, false);
|
||||||
|
}, [state, getDataFn, extractRowIdFn]);
|
||||||
|
|
||||||
const getDraggingIds = useCallback(() => {
|
const getDraggingIds = useCallback(() => {
|
||||||
return Array.from(state.dragging);
|
return Array.from(state.dragging);
|
||||||
@@ -363,8 +393,10 @@ export const useItemListState = (
|
|||||||
}, [state.expanded]);
|
}, [state.expanded]);
|
||||||
|
|
||||||
const getSelectedIds = useCallback(() => {
|
const getSelectedIds = useCallback(() => {
|
||||||
return Array.from(state.selected);
|
const selectedIds = Array.from(state.selected);
|
||||||
}, [state.selected]);
|
const data = getDataFn ? getDataFn() : [];
|
||||||
|
return sortByDataOrder(selectedIds, data, extractRowIdFn, true);
|
||||||
|
}, [state.selected, getDataFn, extractRowIdFn]);
|
||||||
|
|
||||||
const clearExpanded = useCallback(() => {
|
const clearExpanded = useCallback(() => {
|
||||||
dispatch({ type: 'CLEAR_EXPANDED' });
|
dispatch({ type: 'CLEAR_EXPANDED' });
|
||||||
@@ -383,24 +415,24 @@ export const useItemListState = (
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const getVersion = useCallback(() => {
|
const getVersion = useCallback(() => {
|
||||||
return itemGridSelectors.getVersion(state);
|
return itemListSelectors.getVersion(state);
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
const hasExpanded = useCallback(() => {
|
const hasExpanded = useCallback(() => {
|
||||||
return itemGridSelectors.hasAnyExpanded(state);
|
return itemListSelectors.hasAnyExpanded(state);
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
const hasDragging = useCallback(() => {
|
const hasDragging = useCallback(() => {
|
||||||
return itemGridSelectors.hasAnyDragging(state);
|
return itemListSelectors.hasAnyDragging(state);
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
const hasSelected = useCallback(() => {
|
const hasSelected = useCallback(() => {
|
||||||
return itemGridSelectors.hasAnySelected(state);
|
return itemListSelectors.hasAnySelected(state);
|
||||||
}, [state]);
|
}, [state]);
|
||||||
|
|
||||||
const isDragging = useCallback(
|
const isDragging = useCallback(
|
||||||
(rowId: string) => {
|
(rowId: string) => {
|
||||||
return itemGridSelectors.isDragging(state, rowId);
|
return itemListSelectors.isDragging(state, rowId);
|
||||||
},
|
},
|
||||||
[state],
|
[state],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user