@ui5/webcomponents-react
Version:
React Wrapper for UI5 Web Components and additional components
194 lines (192 loc) • 5.08 kB
JavaScript
import { useCallback, useMemo } from 'react';
import { useGetLatest, actions, useMountedLayoutEffect, makePropGetter, ensurePluginOrder } from '../publicUtils.js';
import { expandRows } from '../utils.js';
// Actions
actions.resetExpanded = 'resetExpanded';
actions.toggleRowExpanded = 'toggleRowExpanded';
actions.toggleAllRowsExpanded = 'toggleAllRowsExpanded';
export const useExpanded = hooks => {
hooks.getToggleAllRowsExpandedProps = [defaultGetToggleAllRowsExpandedProps];
hooks.getToggleRowExpandedProps = [defaultGetToggleRowExpandedProps];
hooks.stateReducers.push(reducer);
hooks.useInstance.push(useInstance);
hooks.prepareRow.push(prepareRow);
};
useExpanded.pluginName = 'useExpanded';
const defaultGetToggleAllRowsExpandedProps = (props, {
instance
}) => [props, {
onClick: () => {
instance.toggleAllRowsExpanded();
},
style: {
cursor: 'pointer'
},
title: 'Toggle All Rows Expanded'
}];
const defaultGetToggleRowExpandedProps = (props, {
row
}) => [props, {
onClick: () => {
row.toggleRowExpanded();
},
style: {
cursor: 'pointer'
},
title: 'Toggle Row Expanded'
}];
function reducer(state, action, _previousState, instance) {
if (action.type === actions.init) {
return {
expanded: {},
...state
};
}
if (action.type === actions.resetExpanded) {
return {
...state,
expanded: instance.initialState.expanded || {}
};
}
if (action.type === actions.toggleAllRowsExpanded) {
const {
value
} = action;
const {
rowsById
} = instance;
const isAllRowsExpanded = Object.keys(rowsById).length === Object.keys(state.expanded).length;
const expandAll = typeof value !== 'undefined' ? value : !isAllRowsExpanded;
if (expandAll) {
const expanded = {};
Object.keys(rowsById).forEach(rowId => {
expanded[rowId] = true;
});
return {
...state,
expanded
};
}
return {
...state,
expanded: {}
};
}
if (action.type === actions.toggleRowExpanded) {
const {
id,
value: setExpanded
} = action;
const exists = state.expanded[id];
const shouldExist = typeof setExpanded !== 'undefined' ? setExpanded : !exists;
if (!exists && shouldExist) {
return {
...state,
expanded: {
...state.expanded,
[id]: true
}
};
} else if (exists && !shouldExist) {
const {
[id]: _,
...rest
} = state.expanded;
return {
...state,
expanded: rest
};
} else {
return state;
}
}
}
function useInstance(instance) {
const {
data,
rows,
rowsById,
manualExpandedKey = 'expanded',
paginateExpandedRows = true,
expandSubRows = true,
autoResetExpanded = true,
getHooks,
plugins,
state: {
expanded
},
dispatch
} = instance;
ensurePluginOrder(plugins, ['useSortBy', 'useGroupBy', 'usePivotColumns', 'useGlobalFilter'], 'useExpanded');
const getAutoResetExpanded = useGetLatest(autoResetExpanded);
let isAllRowsExpanded = Boolean(Object.keys(rowsById).length && Object.keys(expanded).length);
if (isAllRowsExpanded) {
if (Object.keys(rowsById).some(id => !expanded[id])) {
isAllRowsExpanded = false;
}
}
// Bypass any effects from firing when this changes
useMountedLayoutEffect(() => {
if (getAutoResetExpanded()) {
dispatch({
type: actions.resetExpanded
});
}
}, [dispatch, data]);
const toggleRowExpanded = useCallback((id, value) => {
dispatch({
type: actions.toggleRowExpanded,
id,
value
});
}, [dispatch]);
const toggleAllRowsExpanded = useCallback(value => dispatch({
type: actions.toggleAllRowsExpanded,
value
}), [dispatch]);
const expandedRows = useMemo(() => {
if (paginateExpandedRows) {
return expandRows(rows, {
manualExpandedKey,
expanded,
expandSubRows
});
}
return rows;
}, [paginateExpandedRows, rows, manualExpandedKey, expanded, expandSubRows]);
const expandedDepth = useMemo(() => findExpandedDepth(expanded), [expanded]);
const getInstance = useGetLatest(instance);
const getToggleAllRowsExpandedProps = makePropGetter(getHooks().getToggleAllRowsExpandedProps, {
instance: getInstance()
});
Object.assign(instance, {
preExpandedRows: rows,
expandedRows,
rows: expandedRows,
expandedDepth,
isAllRowsExpanded,
toggleRowExpanded,
toggleAllRowsExpanded,
getToggleAllRowsExpandedProps
});
}
function prepareRow(row, {
instance: {
getHooks
},
instance
}) {
row.toggleRowExpanded = set => instance.toggleRowExpanded(row.id, set);
row.getToggleRowExpandedProps = makePropGetter(getHooks().getToggleRowExpandedProps, {
instance,
row
});
}
function findExpandedDepth(expanded) {
let maxDepth = 0;
Object.keys(expanded).forEach(id => {
const splitId = id.split('.');
maxDepth = Math.max(maxDepth, splitId.length);
});
return maxDepth;
}