feat: default record group table (#8397)

This PR is preparing states to we'll be able to handle view groups
correctly with table data.
RowIds are now stores in 2 component states, one storing ids by view
group and another storing all the rowIds.
We're doing that because some other state like focus, or select must not
be scoped by view group id.
This commit is contained in:
Jérémy M
2024-11-18 15:36:40 +01:00
committed by GitHub
parent 0125d58ba8
commit fb0221b4c1
32 changed files with 654 additions and 177 deletions

View File

@@ -3,8 +3,10 @@ import { renderHook } from '@testing-library/react';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { mocks } from '@/auth/hooks/__mocks__/useAuth'; import { mocks } from '@/auth/hooks/__mocks__/useAuth';
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLoadRecordIndexTable'; import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance'; import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper'; import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
const recordTableId = 'people'; const recordTableId = 'people';
@@ -23,12 +25,18 @@ const Wrapper = ({ children }: { children: ReactNode }) => {
return ( return (
<HookMockWrapper> <HookMockWrapper>
<ObjectNamePluralSetter> <ObjectNamePluralSetter>
<ViewComponentInstanceContext.Provider
value={{ instanceId: 'instanceId' }}
>
<RecordTableComponentInstance <RecordTableComponentInstance
recordTableId={recordTableId} recordTableId={recordTableId}
onColumnsChange={onColumnsChange} onColumnsChange={onColumnsChange}
> >
<RecordGroupContext.Provider value={{ recordGroupId: 'default' }}>
{children} {children}
</RecordGroupContext.Provider>
</RecordTableComponentInstance> </RecordTableComponentInstance>
</ViewComponentInstanceContext.Provider>
</ObjectNamePluralSetter> </ObjectNamePluralSetter>
</HookMockWrapper> </HookMockWrapper>
); );

View File

@@ -0,0 +1,37 @@
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
import { hasRecordGroupDefinitionsComponentSelector } from '@/object-record/record-group/states/hasRecordGroupDefinitionsComponentSelector';
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useContext, useMemo } from 'react';
export const useCurrentRecordGroupDefinition = (recordTableId?: string) => {
const context = useContext(RecordGroupContext);
const hasRecordGroups = useRecoilComponentValueV2(
hasRecordGroupDefinitionsComponentSelector,
recordTableId,
);
const recordGroupDefinitions = useRecoilComponentValueV2(
recordGroupDefinitionsComponentState,
recordTableId,
);
const recordGroupDefinition = useMemo(() => {
if (!hasRecordGroups) {
return undefined;
}
if (!context) {
throw new Error(
'useCurrentRecordGroupDefinition must be used within a RecordGroupContextProvider.',
);
}
return recordGroupDefinitions.find(
({ id }) => id === context.recordGroupId,
);
}, [context, hasRecordGroups, recordGroupDefinitions]);
return recordGroupDefinition;
};

View File

@@ -0,0 +1,20 @@
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
import { useContext } from 'react';
export const useCurrentRecordGroupId = () => {
const context = useContext(RecordGroupContext);
if (!context) {
throw new Error(
'useCurrentRecordGroupId must be used within a RecordGroupContextProvider.',
);
}
if (!context.recordGroupId) {
throw new Error(
'RecordGroupContext is malformed. recordGroupId is missing.',
);
}
return context.recordGroupId;
};

View File

@@ -23,7 +23,7 @@ export const useRecordGroupReorder = ({
); );
const { visibleRecordGroups } = useRecordGroups({ const { visibleRecordGroups } = useRecordGroups({
objectNameSingular, objectNameSingular: objectNameSingular,
}); });
const { saveViewGroups } = useSaveCurrentViewGroups(viewBarId); const { saveViewGroups } = useSaveCurrentViewGroups(viewBarId);

View File

@@ -0,0 +1,9 @@
import { createContext } from 'react';
export type RecordGroupContextProps = {
recordGroupId: string;
};
export const RecordGroupContext = createContext<RecordGroupContextProps>(
{} as RecordGroupContextProps,
);

View File

@@ -0,0 +1,21 @@
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
export const hasRecordGroupDefinitionsComponentSelector =
createComponentSelectorV2<boolean>({
key: 'hasRecordGroupDefinitionsComponentSelector',
componentInstanceContext: ViewComponentInstanceContext,
get:
({ instanceId }) =>
({ get }) => {
const recordGroupDefinitions = get(
recordGroupDefinitionsComponentState.atomFamily({
instanceId,
}),
);
return recordGroupDefinitions.length > 0;
},
});

View File

@@ -6,6 +6,7 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy'; import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter'; import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
import { useCurrentRecordGroupDefinition } from '@/object-record/record-group/hooks/useCurrentRecordGroupDefinition';
import { useRecordTableRecordGqlFields } from '@/object-record/record-index/hooks/useRecordTableRecordGqlFields'; import { useRecordTableRecordGqlFields } from '@/object-record/record-index/hooks/useRecordTableRecordGqlFields';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState'; import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState';
@@ -14,6 +15,8 @@ import { tableViewFilterGroupsComponentState } from '@/object-record/record-tabl
import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/SignInBackgroundMockCompanies'; import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/SignInBackgroundMockCompanies';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isNull } from '@sniptt/guards'; import { isNull } from '@sniptt/guards';
import { useMemo } from 'react';
import { isDefined } from 'twenty-ui';
import { WorkspaceActivationStatus } from '~/generated/graphql'; import { WorkspaceActivationStatus } from '~/generated/graphql';
export const useFindManyParams = ( export const useFindManyParams = (
@@ -24,6 +27,9 @@ export const useFindManyParams = (
objectNameSingular, objectNameSingular,
}); });
const currentRecordGroupDefinition =
useCurrentRecordGroupDefinition(recordTableId);
const tableViewFilterGroups = useRecoilComponentValueV2( const tableViewFilterGroups = useRecoilComponentValueV2(
tableViewFilterGroupsComponentState, tableViewFilterGroupsComponentState,
recordTableId, recordTableId,
@@ -37,15 +43,45 @@ export const useFindManyParams = (
recordTableId, recordTableId,
); );
const filter = computeViewRecordGqlOperationFilter( const stateFilter = computeViewRecordGqlOperationFilter(
tableFilters, tableFilters,
objectMetadataItem?.fields ?? [], objectMetadataItem?.fields ?? [],
tableViewFilterGroups, tableViewFilterGroups,
); );
const recordGroupFilter = useMemo(() => {
if (isDefined(currentRecordGroupDefinition)) {
const fieldMetadataItem = objectMetadataItem?.fields.find(
(fieldMetadataItem) =>
fieldMetadataItem.id === currentRecordGroupDefinition.fieldMetadataId,
);
if (!fieldMetadataItem) {
return {};
}
return {
[fieldMetadataItem.name]: {
eq: currentRecordGroupDefinition.value,
},
};
}
// TODO: Handle case when value is nullable
return {};
}, [objectMetadataItem.fields, currentRecordGroupDefinition]);
const orderBy = turnSortsIntoOrderBy(objectMetadataItem, tableSorts); const orderBy = turnSortsIntoOrderBy(objectMetadataItem, tableSorts);
return { objectNameSingular, filter, orderBy }; return {
objectNameSingular,
filter: {
...stateFilter,
...recordGroupFilter,
},
orderBy,
};
}; };
export const useLoadRecordIndexTable = (objectNameSingular: string) => { export const useLoadRecordIndexTable = (objectNameSingular: string) => {

View File

@@ -1,18 +1,22 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { isNonEmptyString, isNull } from '@sniptt/guards'; import { isNonEmptyString, isNull } from '@sniptt/guards';
import { hasRecordGroupDefinitionsComponentSelector } from '@/object-record/record-group/states/hasRecordGroupDefinitionsComponentSelector';
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance'; import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
import { RecordTableContextProvider } from '@/object-record/record-table/components/RecordTableContextProvider'; import { RecordTableContextProvider } from '@/object-record/record-table/components/RecordTableContextProvider';
import { RecordTableStickyEffect } from '@/object-record/record-table/components/RecordTableStickyEffect';
import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId'; import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId';
import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState'; import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { RecordTableBody } from '@/object-record/record-table/record-table-body/components/RecordTableBody';
import { RecordTableBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableBodyEffect';
import { RecordTableBodyUnselectEffect } from '@/object-record/record-table/record-table-body/components/RecordTableBodyUnselectEffect'; import { RecordTableBodyUnselectEffect } from '@/object-record/record-table/record-table-body/components/RecordTableBodyUnselectEffect';
import { RecordTableNoRecordGroupBody } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBody';
import { RecordTableNoRecordGroupBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect';
import { RecordTableRecordGroupBodyEffects } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupBodyEffects';
import { RecordTableRecordGroupsBody } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupsBody';
import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader'; import { RecordTableHeader } from '@/object-record/record-table/record-table-header/components/RecordTableHeader';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState'; import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { recordTablePendingRecordIdComponentState } from '@/object-record/record-table/states/recordTablePendingRecordIdComponentState'; import { recordTablePendingRecordIdComponentState } from '@/object-record/record-table/states/recordTablePendingRecordIdComponentState';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@@ -40,17 +44,17 @@ export const RecordTable = ({
}: RecordTableProps) => { }: RecordTableProps) => {
const tableBodyRef = useRef<HTMLTableElement>(null); const tableBodyRef = useRef<HTMLTableElement>(null);
const { toggleClickOutsideListener } = useClickOutsideListener(
RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID,
);
const isRecordTableInitialLoading = useRecoilComponentValueV2( const isRecordTableInitialLoading = useRecoilComponentValueV2(
isRecordTableInitialLoadingComponentState, isRecordTableInitialLoadingComponentState,
recordTableId, recordTableId,
); );
const { toggleClickOutsideListener } = useClickOutsideListener(
RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID,
);
const tableRowIds = useRecoilComponentValueV2( const tableRowIds = useRecoilComponentValueV2(
tableRowIdsComponentState, tableAllRowIdsComponentState,
recordTableId, recordTableId,
); );
@@ -59,15 +63,20 @@ export const RecordTable = ({
recordTableId, recordTableId,
); );
const { resetTableRowSelection, setRowSelected } = useRecordTable({ const hasRecordGroups = useRecoilComponentValueV2(
hasRecordGroupDefinitionsComponentSelector,
recordTableId, recordTableId,
}); );
const recordTableIsEmpty = const recordTableIsEmpty =
!isRecordTableInitialLoading && !isRecordTableInitialLoading &&
tableRowIds.length === 0 && tableRowIds.length === 0 &&
isNull(pendingRecordId); isNull(pendingRecordId);
const { resetTableRowSelection, setRowSelected } = useRecordTable({
recordTableId,
});
if (!isNonEmptyString(objectNameSingular)) { if (!isNonEmptyString(objectNameSingular)) {
return <></>; return <></>;
} }
@@ -82,7 +91,11 @@ export const RecordTable = ({
recordTableId={recordTableId} recordTableId={recordTableId}
viewBarId={viewBarId} viewBarId={viewBarId}
> >
<RecordTableBodyEffect /> {!hasRecordGroups ? (
<RecordTableNoRecordGroupBodyEffect />
) : (
<RecordTableRecordGroupBodyEffects />
)}
<RecordTableBodyUnselectEffect <RecordTableBodyUnselectEffect
tableBodyRef={tableBodyRef} tableBodyRef={tableBodyRef}
recordTableId={recordTableId} recordTableId={recordTableId}
@@ -92,10 +105,15 @@ export const RecordTable = ({
) : ( ) : (
<> <>
<StyledTable className="entity-table-cell" ref={tableBodyRef}> <StyledTable className="entity-table-cell" ref={tableBodyRef}>
<RecordTableHeader <RecordTableHeader objectNameSingular={objectNameSingular} />
objectMetadataNameSingular={objectNameSingular} {!hasRecordGroups ? (
<RecordTableNoRecordGroupBody />
) : (
<RecordTableRecordGroupsBody
objectNameSingular={objectNameSingular}
/> />
<RecordTableBody /> )}
<RecordTableStickyEffect />
</StyledTable> </StyledTable>
<DragSelect <DragSelect
dragSelectable={tableBodyRef} dragSelectable={tableBodyRef}

View File

@@ -1,14 +1,14 @@
import { RecordTableBodyFetchMoreLoader } from '@/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader'; import { RecordTableBodyFetchMoreLoader } from '@/object-record/record-table/record-table-body/components/RecordTableBodyFetchMoreLoader';
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow'; import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
export const RecordTableRows = () => { export const RecordTableNoRecordGroupRows = () => {
const tableRowIds = useRecoilComponentValueV2(tableRowIdsComponentState); const rowIds = useRecoilComponentValueV2(tableAllRowIdsComponentState);
return ( return (
<> <>
{tableRowIds.map((recordId, rowIndex) => { {rowIds.map((recordId, rowIndex) => {
return ( return (
<RecordTableRow <RecordTableRow
key={recordId} key={recordId}

View File

@@ -0,0 +1,26 @@
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
import { RecordTableRow } from '@/object-record/record-table/record-table-row/components/RecordTableRow';
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { tableRowIdsByGroupComponentFamilyState } from '@/object-record/record-table/states/tableRowIdsByGroupComponentFamilyState';
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
export const RecordTableRecordGroupRows = () => {
const recordGroupId = useCurrentRecordGroupId();
const allRowIds = useRecoilComponentValueV2(tableAllRowIdsComponentState);
const recordGroupRowIds = useRecoilComponentFamilyValueV2(
tableRowIdsByGroupComponentFamilyState,
recordGroupId,
);
return recordGroupRowIds.map((recordId) => {
// Find the index of the recordId in allRowIds
const rowIndex = allRowIds.indexOf(recordId);
return (
<RecordTableRow key={recordId} recordId={recordId} rowIndex={rowIndex} />
);
});
};

View File

@@ -0,0 +1,49 @@
import { useEffect } from 'react';
import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
import { useScrollLeftValue } from '@/ui/utilities/scroll/hooks/useScrollLeftValue';
import { useScrollTopValue } from '@/ui/utilities/scroll/hooks/useScrollTopValue';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
export const RecordTableStickyEffect = () => {
const scrollTop = useScrollTopValue('recordTableWithWrappers');
useEffect(() => {
if (scrollTop > 0) {
document
.getElementById('record-table-header')
?.classList.add('header-sticky');
} else {
document
.getElementById('record-table-header')
?.classList.remove('header-sticky');
}
}, [scrollTop]);
const scrollLeft = useScrollLeftValue('recordTableWithWrappers');
const setIsRecordTableScrolledLeft = useSetRecoilComponentStateV2(
isRecordTableScrolledLeftComponentState,
);
useEffect(() => {
setIsRecordTableScrolledLeft(scrollLeft === 0);
if (scrollLeft > 0) {
document
.getElementById('record-table-body')
?.classList.add('first-columns-sticky');
document
.getElementById('record-table-header')
?.classList.add('first-columns-sticky');
} else {
document
.getElementById('record-table-body')
?.classList.remove('first-columns-sticky');
document
.getElementById('record-table-header')
?.classList.remove('first-columns-sticky');
}
}, [scrollLeft, setIsRecordTableScrolledLeft]);
return <></>;
};

View File

@@ -0,0 +1,43 @@
import { isNull } from '@sniptt/guards';
import { RecordTableEmptyState } from '@/object-record/record-table/empty-state/components/RecordTableEmptyState';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { recordTablePendingRecordIdComponentState } from '@/object-record/record-table/states/recordTablePendingRecordIdComponentState';
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
type RecordTableEmptyHandlerProps = {
recordTableId: string;
children: React.ReactNode;
};
export const RecordTableEmptyHandler = ({
recordTableId,
children,
}: RecordTableEmptyHandlerProps) => {
const isRecordTableInitialLoading = useRecoilComponentValueV2(
isRecordTableInitialLoadingComponentState,
recordTableId,
);
const tableRowIds = useRecoilComponentValueV2(
tableAllRowIdsComponentState,
recordTableId,
);
const pendingRecordId = useRecoilComponentValueV2(
recordTablePendingRecordIdComponentState,
recordTableId,
);
const recordTableIsEmpty =
!isRecordTableInitialLoading &&
tableRowIds.length === 0 &&
isNull(pendingRecordId);
if (recordTableIsEmpty) {
return <RecordTableEmptyState />;
}
return children;
};

View File

@@ -5,7 +5,7 @@ import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionM
import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState'; import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState';
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState'; import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
@@ -18,8 +18,8 @@ export const useResetTableRowSelection = (recordTableId?: string) => {
recordTableId, recordTableId,
); );
const tableRowIdsState = useRecoilComponentCallbackStateV2( const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
tableRowIdsComponentState, tableAllRowIdsComponentState,
recordTableIdFromContext, recordTableIdFromContext,
); );
@@ -41,9 +41,9 @@ export const useResetTableRowSelection = (recordTableId?: string) => {
); );
return useRecoilCallback( return useRecoilCallback(
({ snapshot, set }) => ({ set, snapshot }) =>
() => { () => {
const tableRowIds = getSnapshotValue(snapshot, tableRowIdsState); const tableRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
for (const rowId of tableRowIds) { for (const rowId of tableRowIds) {
set(isRowSelectedFamilyState(rowId), false); set(isRowSelectedFamilyState(rowId), false);
@@ -54,7 +54,7 @@ export const useResetTableRowSelection = (recordTableId?: string) => {
set(isActionMenuDropdownOpenState, false); set(isActionMenuDropdownOpenState, false);
}, },
[ [
tableRowIdsState, tableAllRowIdsState,
hasUserSelectedAllRowsState, hasUserSelectedAllRowsState,
isActionMenuDropdownOpenState, isActionMenuDropdownOpenState,
isRowSelectedFamilyState, isRowSelectedFamilyState,

View File

@@ -2,7 +2,7 @@ import { useRecoilCallback } from 'recoil';
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { allRowsSelectedStatusComponentSelector } from '@/object-record/record-table/states/selectors/allRowsSelectedStatusComponentSelector'; import { allRowsSelectedStatusComponentSelector } from '@/object-record/record-table/states/selectors/allRowsSelectedStatusComponentSelector';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
@@ -11,14 +11,14 @@ export const useSelectAllRows = (recordTableId?: string) => {
allRowsSelectedStatusComponentSelector, allRowsSelectedStatusComponentSelector,
recordTableId, recordTableId,
); );
const tableRowIdsState = useRecoilComponentCallbackStateV2(
tableRowIdsComponentState,
recordTableId,
);
const isRowSelectedFamilyState = useRecoilComponentCallbackStateV2( const isRowSelectedFamilyState = useRecoilComponentCallbackStateV2(
isRowSelectedComponentFamilyState, isRowSelectedComponentFamilyState,
recordTableId, recordTableId,
); );
const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
tableAllRowIdsComponentState,
recordTableId,
);
const selectAllRows = useRecoilCallback( const selectAllRows = useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>
@@ -28,7 +28,7 @@ export const useSelectAllRows = (recordTableId?: string) => {
allRowsSelectedStatusSelector, allRowsSelectedStatusSelector,
); );
const tableRowIds = getSnapshotValue(snapshot, tableRowIdsState); const tableRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
if ( if (
allRowsSelectedStatus === 'none' || allRowsSelectedStatus === 'none' ||
@@ -43,7 +43,11 @@ export const useSelectAllRows = (recordTableId?: string) => {
} }
} }
}, },
[allRowsSelectedStatusSelector, tableRowIdsState, isRowSelectedFamilyState], [
allRowsSelectedStatusSelector,
tableAllRowIdsState,
isRowSelectedFamilyState,
],
); );
return { return {

View File

@@ -1,14 +1,16 @@
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState'; import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState';
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { numberOfTableRowsComponentState } from '@/object-record/record-table/states/numberOfTableRowsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableRowIdsByGroupComponentFamilyState } from '@/object-record/record-table/states/tableRowIdsByGroupComponentFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { isDefined } from '~/utils/isDefined';
type useSetRecordTableDataProps = { type useSetRecordTableDataProps = {
recordTableId?: string; recordTableId?: string;
@@ -19,12 +21,12 @@ export const useSetRecordTableData = ({
recordTableId, recordTableId,
onEntityCountChange, onEntityCountChange,
}: useSetRecordTableDataProps) => { }: useSetRecordTableDataProps) => {
const tableRowIdsState = useRecoilComponentCallbackStateV2( const tableRowIdsByGroupFamilyState = useRecoilComponentCallbackStateV2(
tableRowIdsComponentState, tableRowIdsByGroupComponentFamilyState,
recordTableId, recordTableId,
); );
const numberOfTableRowsState = useRecoilComponentCallbackStateV2( const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
numberOfTableRowsComponentState, tableAllRowIdsComponentState,
recordTableId, recordTableId,
); );
const isRowSelectedFamilyState = useRecoilComponentCallbackStateV2( const isRowSelectedFamilyState = useRecoilComponentCallbackStateV2(
@@ -35,11 +37,23 @@ export const useSetRecordTableData = ({
hasUserSelectedAllRowsComponentState, hasUserSelectedAllRowsComponentState,
recordTableId, recordTableId,
); );
const recordGroupDefinitionsState = useRecoilComponentCallbackStateV2(
recordGroupDefinitionsComponentState,
recordTableId,
);
return useRecoilCallback( return useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>
<T extends ObjectRecord>(newRecords: T[], totalCount?: number) => { <T extends ObjectRecord>({
for (const record of newRecords) { records,
recordGroupId,
totalCount,
}: {
records: T[];
recordGroupId?: string;
totalCount?: number;
}) => {
for (const record of records) {
// TODO: refactor with scoped state later // TODO: refactor with scoped state later
const currentRecord = snapshot const currentRecord = snapshot
.getLoadable(recordStoreFamilyState(record.id)) .getLoadable(recordStoreFamilyState(record.id))
@@ -50,14 +64,24 @@ export const useSetRecordTableData = ({
} }
} }
const currentRowIds = getSnapshotValue(snapshot, tableRowIdsState); const currentRowIds = getSnapshotValue(
snapshot,
recordGroupId
? tableRowIdsByGroupFamilyState(recordGroupId)
: tableAllRowIdsState,
);
const hasUserSelectedAllRows = getSnapshotValue( const hasUserSelectedAllRows = getSnapshotValue(
snapshot, snapshot,
hasUserSelectedAllRowsState, hasUserSelectedAllRowsState,
); );
const recordIds = newRecords.map((record) => record.id); const recordGroupDefinitions = getSnapshotValue(
snapshot,
recordGroupDefinitionsState,
);
const recordIds = records.map((record) => record.id);
if (!isDeeplyEqual(currentRowIds, recordIds)) { if (!isDeeplyEqual(currentRowIds, recordIds)) {
if (hasUserSelectedAllRows) { if (hasUserSelectedAllRows) {
@@ -66,14 +90,36 @@ export const useSetRecordTableData = ({
} }
} }
set(tableRowIdsState, recordIds); if (isDefined(recordGroupId)) {
set(numberOfTableRowsState, totalCount ?? 0); // TODO: Hack to store all ids in the same order as the record group definitions
// Should be replaced by something more efficient
const allRowIds: string[] = [];
set(tableRowIdsByGroupFamilyState(recordGroupId), recordIds);
for (const recordGroupDefinition of recordGroupDefinitions) {
const tableRowIdsByGroup =
recordGroupDefinition.id !== recordGroupId
? getSnapshotValue(
snapshot,
tableRowIdsByGroupFamilyState(recordGroupDefinition.id),
)
: recordIds;
allRowIds.push(...tableRowIdsByGroup);
}
set(tableAllRowIdsState, allRowIds);
} else {
set(tableAllRowIdsState, recordIds);
}
onEntityCountChange(totalCount); onEntityCountChange(totalCount);
} }
}, },
[ [
numberOfTableRowsState, tableRowIdsByGroupFamilyState,
tableRowIdsState, tableAllRowIdsState,
recordGroupDefinitionsState,
onEntityCountChange, onEntityCountChange,
isRowSelectedFamilyState, isRowSelectedFamilyState,
hasUserSelectedAllRowsState, hasUserSelectedAllRowsState,

View File

@@ -3,9 +3,9 @@ import { useRecoilCallback } from 'recoil';
import { MoveFocusDirection } from '@/object-record/record-table/types/MoveFocusDirection'; import { MoveFocusDirection } from '@/object-record/record-table/types/MoveFocusDirection';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { numberOfTableRowsComponentState } from '@/object-record/record-table/states/numberOfTableRowsComponentState';
import { numberOfTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/numberOfTableColumnsComponentSelector'; import { numberOfTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/numberOfTableColumnsComponentSelector';
import { softFocusPositionComponentState } from '@/object-record/record-table/states/softFocusPositionComponentState'; import { softFocusPositionComponentState } from '@/object-record/record-table/states/softFocusPositionComponentState';
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useSetSoftFocusPosition } from './internal/useSetSoftFocusPosition'; import { useSetSoftFocusPosition } from './internal/useSetSoftFocusPosition';
@@ -17,6 +17,11 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
recordTableId, recordTableId,
); );
const tableAllRowIdsState = useRecoilComponentCallbackStateV2(
tableAllRowIdsComponentState,
recordTableId,
);
const moveUp = useRecoilCallback( const moveUp = useRecoilCallback(
({ snapshot }) => ({ snapshot }) =>
() => { () => {
@@ -25,50 +30,41 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
softFocusPositionState, softFocusPositionState,
); );
let newRowNumber = softFocusPosition.row - 1; let newRowIndex = softFocusPosition.row - 1;
if (newRowNumber < 0) { if (newRowIndex < 0) {
newRowNumber = 0; newRowIndex = 0;
} }
setSoftFocusPosition({ setSoftFocusPosition({
...softFocusPosition, ...softFocusPosition,
row: newRowNumber, row: newRowIndex,
}); });
}, },
[softFocusPositionState, setSoftFocusPosition], [softFocusPositionState, setSoftFocusPosition],
); );
const numberOfTableRowsState = useRecoilComponentCallbackStateV2(
numberOfTableRowsComponentState,
recordTableId,
);
const moveDown = useRecoilCallback( const moveDown = useRecoilCallback(
({ snapshot }) => ({ snapshot }) =>
() => { () => {
const allRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
const softFocusPosition = getSnapshotValue( const softFocusPosition = getSnapshotValue(
snapshot, snapshot,
softFocusPositionState, softFocusPositionState,
); );
const numberOfTableRows = getSnapshotValue( let newRowIndex = softFocusPosition.row + 1;
snapshot,
numberOfTableRowsState,
);
let newRowNumber = softFocusPosition.row + 1; if (newRowIndex >= allRowIds.length) {
newRowIndex = allRowIds.length - 1;
if (newRowNumber >= numberOfTableRows) {
newRowNumber = numberOfTableRows - 1;
} }
setSoftFocusPosition({ setSoftFocusPosition({
...softFocusPosition, ...softFocusPosition,
row: newRowNumber, row: newRowIndex,
}); });
}, },
[numberOfTableRowsState, setSoftFocusPosition, softFocusPositionState], [tableAllRowIdsState, setSoftFocusPosition, softFocusPositionState],
); );
const numberOfTableColumnsSelector = useRecoilComponentCallbackStateV2( const numberOfTableColumnsSelector = useRecoilComponentCallbackStateV2(
@@ -79,6 +75,7 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
const moveRight = useRecoilCallback( const moveRight = useRecoilCallback(
({ snapshot }) => ({ snapshot }) =>
() => { () => {
const allRowIds = getSnapshotValue(snapshot, tableAllRowIdsState);
const softFocusPosition = getSnapshotValue( const softFocusPosition = getSnapshotValue(
snapshot, snapshot,
softFocusPositionState, softFocusPositionState,
@@ -89,24 +86,18 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
numberOfTableColumnsSelector, numberOfTableColumnsSelector,
); );
const numberOfTableRows = getSnapshotValue( const currentColumnIndex = softFocusPosition.column;
snapshot, const currentRowIndex = softFocusPosition.row;
numberOfTableRowsState,
);
const currentColumnNumber = softFocusPosition.column;
const currentRowNumber = softFocusPosition.row;
const isLastRowAndLastColumn = const isLastRowAndLastColumn =
currentColumnNumber === numberOfTableColumns - 1 && currentColumnIndex === numberOfTableColumns - 1 &&
currentRowNumber === numberOfTableRows - 1; currentRowIndex === allRowIds.length - 1;
const isLastColumnButNotLastRow = const isLastColumnButNotLastRow =
currentColumnNumber === numberOfTableColumns - 1 && currentColumnIndex === numberOfTableColumns - 1 &&
currentRowNumber !== numberOfTableRows - 1; currentRowIndex !== allRowIds.length - 1;
const isNotLastColumn = const isNotLastColumn = currentColumnIndex !== numberOfTableColumns - 1;
currentColumnNumber !== numberOfTableColumns - 1;
if (isLastRowAndLastColumn) { if (isLastRowAndLastColumn) {
return; return;
@@ -114,20 +105,20 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
if (isNotLastColumn) { if (isNotLastColumn) {
setSoftFocusPosition({ setSoftFocusPosition({
row: currentRowNumber, row: currentRowIndex,
column: currentColumnNumber + 1, column: currentColumnIndex + 1,
}); });
} else if (isLastColumnButNotLastRow) { } else if (isLastColumnButNotLastRow) {
setSoftFocusPosition({ setSoftFocusPosition({
row: currentRowNumber + 1, row: currentRowIndex + 1,
column: 0, column: 0,
}); });
} }
}, },
[ [
tableAllRowIdsState,
softFocusPositionState, softFocusPositionState,
numberOfTableColumnsSelector, numberOfTableColumnsSelector,
numberOfTableRowsState,
setSoftFocusPosition, setSoftFocusPosition,
], ],
); );
@@ -145,16 +136,16 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
numberOfTableColumnsSelector, numberOfTableColumnsSelector,
); );
const currentColumnNumber = softFocusPosition.column; const currentColumnIndex = softFocusPosition.column;
const currentRowNumber = softFocusPosition.row; const currentRowIndex = softFocusPosition.row;
const isFirstRowAndFirstColumn = const isFirstRowAndFirstColumn =
currentColumnNumber === 0 && currentRowNumber === 0; currentColumnIndex === 0 && currentRowIndex === 0;
const isFirstColumnButNotFirstRow = const isFirstColumnButNotFirstRow =
currentColumnNumber === 0 && currentRowNumber > 0; currentColumnIndex === 0 && currentRowIndex > 0;
const isNotFirstColumn = currentColumnNumber > 0; const isNotFirstColumn = currentColumnIndex > 0;
if (isFirstRowAndFirstColumn) { if (isFirstRowAndFirstColumn) {
return; return;
@@ -162,12 +153,12 @@ export const useRecordTableMoveFocus = (recordTableId?: string) => {
if (isNotFirstColumn) { if (isNotFirstColumn) {
setSoftFocusPosition({ setSoftFocusPosition({
row: currentRowNumber, row: currentRowIndex,
column: currentColumnNumber - 1, column: currentColumnIndex - 1,
}); });
} else if (isFirstColumnButNotFirstRow) { } else if (isFirstColumnButNotFirstRow) {
setSoftFocusPosition({ setSoftFocusPosition({
row: currentRowNumber - 1, row: currentRowIndex - 1,
column: numberOfTableColumns - 1, column: numberOfTableColumns - 1,
}); });
} }

View File

@@ -6,7 +6,7 @@ import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
import { useComputeNewRowPosition } from '@/object-record/record-table/hooks/useComputeNewRowPosition'; import { useComputeNewRowPosition } from '@/object-record/record-table/hooks/useComputeNewRowPosition';
import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState'; import { isRemoveSortingModalOpenState } from '@/object-record/record-table/states/isRemoveSortingModalOpenState';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
@@ -22,7 +22,9 @@ export const RecordTableBodyDragDropContext = ({
objectNameSingular, objectNameSingular,
}); });
const tableRowIds = useRecoilComponentValueV2(tableRowIdsComponentState); const tableAllRowIds = useRecoilComponentValueV2(
tableAllRowIdsComponentState,
);
const { currentViewWithCombinedFiltersAndSorts } = const { currentViewWithCombinedFiltersAndSorts } =
useGetCurrentView(recordTableId); useGetCurrentView(recordTableId);
@@ -41,7 +43,7 @@ export const RecordTableBodyDragDropContext = ({
return; return;
} }
const computeResult = computeNewRowPosition(result, tableRowIds); const computeResult = computeNewRowPosition(result, tableAllRowIds);
if (!isDefined(computeResult)) { if (!isDefined(computeResult)) {
return; return;

View File

@@ -1,20 +1,22 @@
import { RecordTableRows } from '@/object-record/record-table/components/RecordTableRows'; import { RecordTableNoRecordGroupRows } from '@/object-record/record-table/components/RecordTableNoRecordGroupRows';
import { RecordTableBodyDragDropContext } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDragDropContext'; import { RecordTableBodyDragDropContext } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDragDropContext';
import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable'; import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading'; import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
import { RecordTablePendingRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRow'; import { RecordTablePendingRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRow';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState'; import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
export const RecordTableBody = () => { export const RecordTableNoRecordGroupBody = () => {
const tableRowIds = useRecoilComponentValueV2(tableRowIdsComponentState); const tableAllRowIds = useRecoilComponentValueV2(
tableAllRowIdsComponentState,
);
const isRecordTableInitialLoading = useRecoilComponentValueV2( const isRecordTableInitialLoading = useRecoilComponentValueV2(
isRecordTableInitialLoadingComponentState, isRecordTableInitialLoadingComponentState,
); );
if (isRecordTableInitialLoading && tableRowIds.length === 0) { if (isRecordTableInitialLoading && tableAllRowIds.length === 0) {
return <RecordTableBodyLoading />; return <RecordTableBodyLoading />;
} }
@@ -22,7 +24,7 @@ export const RecordTableBody = () => {
<RecordTableBodyDragDropContext> <RecordTableBodyDragDropContext>
<RecordTableBodyDroppable> <RecordTableBodyDroppable>
<RecordTablePendingRow /> <RecordTablePendingRow />
<RecordTableRows /> <RecordTableNoRecordGroupRows />
</RecordTableBodyDroppable> </RecordTableBodyDroppable>
</RecordTableBodyDragDropContext> </RecordTableBodyDragDropContext>
); );

View File

@@ -7,20 +7,17 @@ import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useL
import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight'; import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight';
import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2'; import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2';
import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState';
import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState'; import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState';
import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState'; import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState';
import { useScrollLeftValue } from '@/ui/utilities/scroll/hooks/useScrollLeftValue';
import { useScrollTopValue } from '@/ui/utilities/scroll/hooks/useScrollTopValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { isNonEmptyString } from '@sniptt/guards'; import { isNonEmptyString } from '@sniptt/guards';
import { useScrollToPosition } from '~/hooks/useScrollToPosition'; import { useScrollToPosition } from '~/hooks/useScrollToPosition';
export const RecordTableBodyEffect = () => { export const RecordTableNoRecordGroupBodyEffect = () => {
const { objectNameSingular } = useContext(RecordTableContext); const { objectNameSingular } = useContext(RecordTableContext);
const [hasInitializedScroll, setHasInitiazedScroll] = useState(false); const [hasInitializedScroll, setHasInitializedScroll] = useState(false);
const { const {
fetchMoreRecords, fetchMoreRecords,
@@ -40,51 +37,11 @@ export const RecordTableBodyEffect = () => {
tableLastRowVisibleComponentState, tableLastRowVisibleComponentState,
); );
const scrollTop = useScrollTopValue('recordTableWithWrappers');
const setHasRecordTableFetchedAllRecordsComponents = const setHasRecordTableFetchedAllRecordsComponents =
useSetRecoilComponentStateV2( useSetRecoilComponentStateV2(
hasRecordTableFetchedAllRecordsComponentStateV2, hasRecordTableFetchedAllRecordsComponentStateV2,
); );
// TODO: move this outside because it might cause way too many re-renders for other hooks
useEffect(() => {
if (scrollTop > 0) {
document
.getElementById('record-table-header')
?.classList.add('header-sticky');
} else {
document
.getElementById('record-table-header')
?.classList.remove('header-sticky');
}
}, [scrollTop]);
const scrollLeft = useScrollLeftValue('recordTableWithWrappers');
const setIsRecordTableScrolledLeft = useSetRecoilComponentStateV2(
isRecordTableScrolledLeftComponentState,
);
useEffect(() => {
setIsRecordTableScrolledLeft(scrollLeft === 0);
if (scrollLeft > 0) {
document
.getElementById('record-table-body')
?.classList.add('first-columns-sticky');
document
.getElementById('record-table-header')
?.classList.add('first-columns-sticky');
} else {
document
.getElementById('record-table-body')
?.classList.remove('first-columns-sticky');
document
.getElementById('record-table-header')
?.classList.remove('first-columns-sticky');
}
}, [scrollLeft, setIsRecordTableScrolledLeft]);
const [lastShowPageRecordId, setLastShowPageRecordId] = useRecoilState( const [lastShowPageRecordId, setLastShowPageRecordId] = useRecoilState(
lastShowPageRecordIdState, lastShowPageRecordIdState,
); );
@@ -106,7 +63,7 @@ export const RecordTableBodyEffect = () => {
scrollToPosition(positionInPx); scrollToPosition(positionInPx);
setHasInitiazedScroll(true); setHasInitializedScroll(true);
} }
} }
}, [ }, [
@@ -120,7 +77,10 @@ export const RecordTableBodyEffect = () => {
useEffect(() => { useEffect(() => {
if (!loading) { if (!loading) {
setRecordTableData(records, totalCount); setRecordTableData({
records,
totalCount,
});
} }
}, [records, totalCount, setRecordTableData, loading]); }, [records, totalCount, setRecordTableData, loading]);

View File

@@ -0,0 +1,79 @@
import { useContext, useEffect, useState } from 'react';
import { useRecoilState } from 'recoil';
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
import { useCurrentRecordGroupId } from '@/object-record/record-group/hooks/useCurrentRecordGroupId';
import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight';
import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext';
import { hasRecordTableFetchedAllRecordsComponentStateV2 } from '@/object-record/record-table/states/hasRecordTableFetchedAllRecordsComponentStateV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { isNonEmptyString } from '@sniptt/guards';
import { useScrollToPosition } from '~/hooks/useScrollToPosition';
export const RecordTableRecordGroupBodyEffect = () => {
const { objectNameSingular } = useContext(RecordTableContext);
const recordGroupId = useCurrentRecordGroupId();
const [hasInitializedScroll, setHasInitializedScroll] = useState(false);
const { records, totalCount, setRecordTableData, loading, hasNextPage } =
useLoadRecordIndexTable(objectNameSingular);
const setHasRecordTableFetchedAllRecordsComponents =
useSetRecoilComponentStateV2(
hasRecordTableFetchedAllRecordsComponentStateV2,
);
const [lastShowPageRecordId, setLastShowPageRecordId] = useRecoilState(
lastShowPageRecordIdState,
);
const { scrollToPosition } = useScrollToPosition();
useEffect(() => {
if (isNonEmptyString(lastShowPageRecordId) && !hasInitializedScroll) {
const isRecordAlreadyFetched = records.some(
(record) => record.id === lastShowPageRecordId,
);
if (isRecordAlreadyFetched) {
const recordPosition = records.findIndex(
(record) => record.id === lastShowPageRecordId,
);
const positionInPx = recordPosition * ROW_HEIGHT;
scrollToPosition(positionInPx);
setHasInitializedScroll(true);
}
}
}, [
loading,
lastShowPageRecordId,
records,
scrollToPosition,
hasInitializedScroll,
setLastShowPageRecordId,
]);
useEffect(() => {
if (!loading) {
setRecordTableData({
records,
recordGroupId,
totalCount,
});
}
}, [records, totalCount, setRecordTableData, loading, recordGroupId]);
useEffect(() => {
const allRecordsHaveBeenFetched = !hasNextPage;
setHasRecordTableFetchedAllRecordsComponents(allRecordsHaveBeenFetched);
}, [hasNextPage, setHasRecordTableFetchedAllRecordsComponents]);
return <></>;
};

View File

@@ -0,0 +1,18 @@
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
import { recordGroupDefinitionsComponentState } from '@/object-record/record-group/states/recordGroupDefinitionsComponentState';
import { RecordTableRecordGroupBodyEffect } from '@/object-record/record-table/record-table-body/components/RecordTableRecordGroupBodyEffect';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
export const RecordTableRecordGroupBodyEffects = () => {
const recordGroupDefinitions = useRecoilComponentValueV2(
recordGroupDefinitionsComponentState,
);
return recordGroupDefinitions.map((recordGroupDefinition) => (
<RecordGroupContext.Provider
value={{ recordGroupId: recordGroupDefinition.id }}
>
<RecordTableRecordGroupBodyEffect />
</RecordGroupContext.Provider>
));
};

View File

@@ -0,0 +1,47 @@
import { useRecordGroups } from '@/object-record/record-group/hooks/useRecordGroups';
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
import { RecordTableRecordGroupRows } from '@/object-record/record-table/components/RecordTableRecordGroupRows';
import { RecordTableBodyDragDropContext } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDragDropContext';
import { RecordTableBodyDroppable } from '@/object-record/record-table/record-table-body/components/RecordTableBodyDroppable';
import { RecordTableBodyLoading } from '@/object-record/record-table/record-table-body/components/RecordTableBodyLoading';
import { RecordTablePendingRow } from '@/object-record/record-table/record-table-row/components/RecordTablePendingRow';
import { isRecordTableInitialLoadingComponentState } from '@/object-record/record-table/states/isRecordTableInitialLoadingComponentState';
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
type RecordTableRecordGroupsBodyProps = {
objectNameSingular: string;
};
export const RecordTableRecordGroupsBody = ({
objectNameSingular,
}: RecordTableRecordGroupsBodyProps) => {
const tableAllRowIds = useRecoilComponentValueV2(
tableAllRowIdsComponentState,
);
const isRecordTableInitialLoading = useRecoilComponentValueV2(
isRecordTableInitialLoadingComponentState,
);
const { visibleRecordGroups } = useRecordGroups({ objectNameSingular });
if (isRecordTableInitialLoading && tableAllRowIds.length === 0) {
return <RecordTableBodyLoading />;
}
return (
<RecordTableBodyDragDropContext>
<RecordTableBodyDroppable>
<RecordTablePendingRow />
{visibleRecordGroups.map((recordGroupDefinition) => (
<RecordGroupContext.Provider
value={{ recordGroupId: recordGroupDefinition.id }}
>
<RecordTableRecordGroupRows />
</RecordGroupContext.Provider>
))}
</RecordTableBodyDroppable>
</RecordTableBodyDragDropContext>
);
};

View File

@@ -78,9 +78,9 @@ const StyledTableHead = styled.thead`
`; `;
export const RecordTableHeader = ({ export const RecordTableHeader = ({
objectMetadataNameSingular, objectNameSingular,
}: { }: {
objectMetadataNameSingular: string; objectNameSingular: string;
}) => { }) => {
const visibleTableColumns = useRecoilComponentValueV2( const visibleTableColumns = useRecoilComponentValueV2(
visibleTableColumnsComponentSelector, visibleTableColumnsComponentSelector,
@@ -95,7 +95,7 @@ export const RecordTableHeader = ({
<RecordTableHeaderCell <RecordTableHeaderCell
key={column.fieldMetadataId} key={column.fieldMetadataId}
column={column} column={column}
objectMetadataNameSingular={objectMetadataNameSingular} objectNameSingular={objectNameSingular}
/> />
))} ))}
<RecordTableHeaderLastColumn /> <RecordTableHeaderLastColumn />

View File

@@ -95,13 +95,13 @@ const StyledHeaderIcon = styled.div`
export const RecordTableHeaderCell = ({ export const RecordTableHeaderCell = ({
column, column,
objectMetadataNameSingular, objectNameSingular,
}: { }: {
column: ColumnDefinition<FieldMetadata>; column: ColumnDefinition<FieldMetadata>;
objectMetadataNameSingular: string; objectNameSingular: string;
}) => { }) => {
const { objectMetadataItem } = useObjectMetadataItem({ const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular: objectMetadataNameSingular, objectNameSingular,
}); });
const resizeFieldOffsetState = useRecoilComponentCallbackStateV2( const resizeFieldOffsetState = useRecoilComponentCallbackStateV2(

View File

@@ -1,7 +1,7 @@
import { selectedRowIdsComponentSelector } from '@/object-record/record-table/states/selectors/selectedRowIdsComponentSelector'; import { selectedRowIdsComponentSelector } from '@/object-record/record-table/states/selectors/selectedRowIdsComponentSelector';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2'; import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
import { AllRowsSelectedStatus } from '../../types/AllRowSelectedStatus'; import { AllRowsSelectedStatus } from '../../types/AllRowSelectedStatus';
@@ -13,11 +13,15 @@ export const allRowsSelectedStatusComponentSelector =
({ instanceId }) => ({ instanceId }) =>
({ get }) => { ({ get }) => {
const tableRowIds = get( const tableRowIds = get(
tableRowIdsComponentState.atomFamily({ instanceId }), tableAllRowIdsComponentState.atomFamily({
instanceId,
}),
); );
const selectedRowIds = get( const selectedRowIds = get(
selectedRowIdsComponentSelector.selectorFamily({ instanceId }), selectedRowIdsComponentSelector.selectorFamily({
instanceId,
}),
); );
const numberOfSelectedRows = selectedRowIds.length; const numberOfSelectedRows = selectedRowIds.length;

View File

@@ -1,6 +1,6 @@
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2'; import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
export const selectedRowIdsComponentSelector = createComponentSelectorV2< export const selectedRowIdsComponentSelector = createComponentSelectorV2<
@@ -11,7 +11,11 @@ export const selectedRowIdsComponentSelector = createComponentSelectorV2<
get: get:
({ instanceId }) => ({ instanceId }) =>
({ get }) => { ({ get }) => {
const rowIds = get(tableRowIdsComponentState.atomFamily({ instanceId })); const rowIds = get(
tableAllRowIdsComponentState.atomFamily({
instanceId,
}),
);
return rowIds.filter( return rowIds.filter(
(rowId) => (rowId) =>

View File

@@ -1,6 +1,6 @@
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState'; import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { tableRowIdsComponentState } from '@/object-record/record-table/states/tableRowIdsComponentState'; import { tableAllRowIdsComponentState } from '@/object-record/record-table/states/tableAllRowIdsComponentState';
import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2'; import { createComponentSelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentSelectorV2';
export const unselectedRowIdsComponentSelector = createComponentSelectorV2< export const unselectedRowIdsComponentSelector = createComponentSelectorV2<
@@ -11,7 +11,11 @@ export const unselectedRowIdsComponentSelector = createComponentSelectorV2<
get: get:
({ instanceId }) => ({ instanceId }) =>
({ get }) => { ({ get }) => {
const rowIds = get(tableRowIdsComponentState.atomFamily({ instanceId })); const rowIds = get(
tableAllRowIdsComponentState.atomFamily({
instanceId,
}),
);
return rowIds.filter( return rowIds.filter(
(rowId) => (rowId) =>

View File

@@ -1,8 +1,8 @@
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext'; import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const tableRowIdsComponentState = createComponentStateV2<string[]>({ export const tableAllRowIdsComponentState = createComponentStateV2<string[]>({
key: 'tableRowIdsComponentState', key: 'tableAllRowIdsComponentState',
defaultValue: [], defaultValue: [],
componentInstanceContext: RecordTableComponentInstanceContext, componentInstanceContext: RecordTableComponentInstanceContext,
}); });

View File

@@ -0,0 +1,11 @@
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const tableRecordGroupIdsComponentState = createComponentStateV2<
RecordGroupDefinition['id'][]
>({
key: 'tableRecordGroupIdsComponentState',
defaultValue: [],
componentInstanceContext: RecordTableComponentInstanceContext,
});

View File

@@ -0,0 +1,10 @@
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
export const tableRowIdsByGroupComponentFamilyState =
createComponentFamilyStateV2<string[], RecordGroupDefinition['id']>({
key: 'tableRowIdsByGroupComponentFamilyState',
defaultValue: [],
componentInstanceContext: RecordTableComponentInstanceContext,
});

View File

@@ -1,3 +1,5 @@
/* eslint-disable no-redeclare */
/* eslint-disable prefer-arrow/prefer-arrow-functions */
import { selectorFamily, SerializableParam } from 'recoil'; import { selectorFamily, SerializableParam } from 'recoil';
import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2'; import { ComponentFamilyReadOnlySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyReadOnlySelectorV2';
@@ -9,7 +11,26 @@ import { SelectorGetter } from '@/ui/utilities/state/types/SelectorGetter';
import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter'; import { SelectorSetter } from '@/ui/utilities/state/types/SelectorSetter';
import { isDefined } from 'twenty-ui'; import { isDefined } from 'twenty-ui';
export const createComponentFamilySelectorV2 = < export function createComponentFamilySelectorV2<
ValueType,
FamilyKey extends SerializableParam,
>(options: {
key: string;
get: SelectorGetter<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>;
componentInstanceContext: ComponentInstanceStateContext<any> | null;
}): ComponentFamilySelectorV2<ValueType, FamilyKey>;
export function createComponentFamilySelectorV2<
ValueType,
FamilyKey extends SerializableParam,
>(options: {
key: string;
get: SelectorGetter<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>;
set: SelectorSetter<ValueType, ComponentFamilyStateKeyV2<FamilyKey>>;
componentInstanceContext: ComponentInstanceStateContext<any> | null;
}): ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>;
export function createComponentFamilySelectorV2<
ValueType, ValueType,
FamilyKey extends SerializableParam, FamilyKey extends SerializableParam,
>({ >({
@@ -24,7 +45,7 @@ export const createComponentFamilySelectorV2 = <
componentInstanceContext: ComponentInstanceStateContext<any> | null; componentInstanceContext: ComponentInstanceStateContext<any> | null;
}): }):
| ComponentFamilySelectorV2<ValueType, FamilyKey> | ComponentFamilySelectorV2<ValueType, FamilyKey>
| ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey> => { | ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey> {
if (isDefined(componentInstanceContext)) { if (isDefined(componentInstanceContext)) {
globalComponentInstanceContextMap.set(key, componentInstanceContext); globalComponentInstanceContextMap.set(key, componentInstanceContext);
} }
@@ -55,4 +76,4 @@ export const createComponentFamilySelectorV2 = <
}), }),
} satisfies ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>; } satisfies ComponentFamilyReadOnlySelectorV2<ValueType, FamilyKey>;
} }
}; }

View File

@@ -6,11 +6,18 @@ import { AtomEffect, atomFamily, SerializableParam } from 'recoil';
import { isDefined } from 'twenty-ui'; import { isDefined } from 'twenty-ui';
type CreateComponentFamilyStateArgs<ValueType> = { type CreateComponentFamilyStateArgs<
ValueType,
FamilyKey extends SerializableParam,
> = {
key: string; key: string;
defaultValue: ValueType; defaultValue: ValueType;
componentInstanceContext: ComponentInstanceStateContext<any> | null; componentInstanceContext: ComponentInstanceStateContext<any> | null;
effects?: AtomEffect<ValueType>[]; effects?:
| AtomEffect<ValueType>[]
| ((
param: ComponentFamilyStateKeyV2<FamilyKey>,
) => ReadonlyArray<AtomEffect<ValueType>>);
}; };
export const createComponentFamilyStateV2 = < export const createComponentFamilyStateV2 = <
@@ -21,10 +28,10 @@ export const createComponentFamilyStateV2 = <
effects, effects,
defaultValue, defaultValue,
componentInstanceContext, componentInstanceContext,
}: CreateComponentFamilyStateArgs<ValueType>): ComponentFamilyStateV2< }: CreateComponentFamilyStateArgs<
ValueType, ValueType,
FamilyKey FamilyKey
> => { >): ComponentFamilyStateV2<ValueType, FamilyKey> => {
if (isDefined(componentInstanceContext)) { if (isDefined(componentInstanceContext)) {
globalComponentInstanceContextMap.set(key, componentInstanceContext); globalComponentInstanceContextMap.set(key, componentInstanceContext);
} }