mirror of
https://github.com/ToolJet/ToolJet
synced 2026-05-24 01:18:23 +00:00
Merge pull request #12395 from ToolJet/feat/tab-navigation
Feat: Added support for tab navigation in Editor and Viewer
This commit is contained in:
commit
d0966c947c
4 changed files with 79 additions and 1 deletions
|
|
@ -20,6 +20,7 @@ import NoComponentCanvasContainer from './NoComponentCanvasContainer';
|
|||
import { RIGHT_SIDE_BAR_TAB } from '../RightSideBar/rightSidebarConstants';
|
||||
import { isPDFSupported } from '@/_helpers/appUtils';
|
||||
import toast from 'react-hot-toast';
|
||||
import useSortedComponents from '../_hooks/useSortedComponents';
|
||||
|
||||
//TODO: Revisit the logic of height (dropRef)
|
||||
|
||||
|
|
@ -146,6 +147,8 @@ export const Container = React.memo(
|
|||
[setLastCanvasClickPosition]
|
||||
);
|
||||
|
||||
const sortedComponents = useSortedComponents(components, currentLayout, id);
|
||||
|
||||
return (
|
||||
<div
|
||||
// {...(config.COMMENT_FEATURE_ENABLE && showComments && { onClick: handleAddThread })}
|
||||
|
|
@ -197,7 +200,7 @@ export const Container = React.memo(
|
|||
data-parent-type={id === 'canvas' ? 'canvas' : componentType}
|
||||
style={{ height: !showEmptyContainer ? '100%' : 'auto' }} //TODO: remove hardcoded height & canvas condition
|
||||
>
|
||||
{components.map((id) => (
|
||||
{sortedComponents.map((id) => (
|
||||
<WidgetWrapper
|
||||
id={id}
|
||||
key={id}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ export default function Grid({ gridWidth, currentLayout }) {
|
|||
const prevDragParentId = useRef(null);
|
||||
const newDragParentId = useRef(null);
|
||||
const [isGroupDragging, setIsGroupDragging] = useState(false);
|
||||
const setReorderContainerChildren = useStore((state) => state.setReorderContainerChildren, shallow);
|
||||
|
||||
useEffect(() => {
|
||||
const selectedSet = new Set(selectedComponents);
|
||||
|
|
@ -536,6 +537,7 @@ export default function Grid({ gridWidth, currentLayout }) {
|
|||
})
|
||||
);
|
||||
}
|
||||
setReorderContainerChildren(draggedOverElemId ?? 'canvas');
|
||||
} catch (error) {
|
||||
console.error('Error dragging group', error);
|
||||
}
|
||||
|
|
@ -696,6 +698,7 @@ export default function Grid({ gridWidth, currentLayout }) {
|
|||
resizeData.gw = _gridWidth;
|
||||
}
|
||||
handleResizeStop([resizeData]);
|
||||
setReorderContainerChildren(currentWidget?.parent ?? 'canvas');
|
||||
} catch (error) {
|
||||
console.error('ResizeEnd error ->', error);
|
||||
}
|
||||
|
|
@ -775,6 +778,11 @@ export default function Grid({ gridWidth, currentLayout }) {
|
|||
ev.target.style.transform = `translate(${posX}px, ${posY}px)`;
|
||||
});
|
||||
}
|
||||
|
||||
const groupParentId =
|
||||
boxList.find(({ id }) => id === groupResizeDataRef.current[0].target.id)?.parent ?? 'canvas';
|
||||
setReorderContainerChildren(groupParentId);
|
||||
|
||||
groupResizeDataRef.current = [];
|
||||
reloadGrid();
|
||||
} catch (error) {
|
||||
|
|
@ -841,6 +849,8 @@ export default function Grid({ gridWidth, currentLayout }) {
|
|||
useStore.getState().setDraggingComponentId(null);
|
||||
isDraggingRef.current = false;
|
||||
}
|
||||
|
||||
const oldParentId = boxList.find((b) => b.id === e.target.id)?.parent ?? 'canvas';
|
||||
prevDragParentId.current = null;
|
||||
newDragParentId.current = null;
|
||||
setDragParentId(null);
|
||||
|
|
@ -880,6 +890,12 @@ export default function Grid({ gridWidth, currentLayout }) {
|
|||
// Apply transform for smooth transition
|
||||
e.target.style.transform = `translate(${left}px, ${top}px)`;
|
||||
|
||||
// Force reordering of conatiner if the parent has not changed
|
||||
const newParentId = target.slotId === 'real-canvas' ? 'canvas' : target.slotId;
|
||||
if (oldParentId === newParentId) {
|
||||
setReorderContainerChildren(newParentId);
|
||||
}
|
||||
|
||||
// Select the dragged component after drop
|
||||
setTimeout(() => setSelectedComponents([dragged.id]));
|
||||
} catch (error) {
|
||||
|
|
|
|||
49
frontend/src/AppBuilder/_hooks/useSortedComponents.js
Normal file
49
frontend/src/AppBuilder/_hooks/useSortedComponents.js
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { useMemo, useRef } from 'react';
|
||||
import useStore from '@/AppBuilder/_stores/store';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
|
||||
const useSortedComponents = (components, currentLayout, id) => {
|
||||
const getCurrentPageComponents = useStore((state) => state.getCurrentPageComponents, shallow);
|
||||
const reorderContainerChildren = useStore((state) => state.reorderContainerChildren, shallow);
|
||||
const prevForceUpdateRef = useRef(0);
|
||||
const prevComponentsOrder = useRef(components);
|
||||
|
||||
// Function to sort the components based on position in container for tab navigation
|
||||
const sortedComponents = useMemo(() => {
|
||||
const { triggerUpdate, containerId } = reorderContainerChildren;
|
||||
|
||||
// If a forced update occurred for a different container, return the previous order
|
||||
const isForcedUpdate = prevForceUpdateRef.current !== triggerUpdate;
|
||||
if (isForcedUpdate) {
|
||||
prevForceUpdateRef.current = triggerUpdate;
|
||||
if (containerId !== id) {
|
||||
return prevComponentsOrder.current;
|
||||
}
|
||||
}
|
||||
|
||||
const currentPageComponents = getCurrentPageComponents();
|
||||
|
||||
const newComponentsOrder = [...components].sort((a, b) => {
|
||||
const aTop = currentPageComponents?.[a]?.layouts?.[currentLayout]?.top;
|
||||
const bTop = currentPageComponents?.[b]?.layouts?.[currentLayout]?.top;
|
||||
if (aTop !== bTop) {
|
||||
return aTop - bTop;
|
||||
} else {
|
||||
const aLeft = currentPageComponents?.[a]?.layouts?.[currentLayout]?.left;
|
||||
const bLeft = currentPageComponents?.[b]?.layouts?.[currentLayout]?.left;
|
||||
if (aLeft !== bLeft) {
|
||||
return aLeft - bLeft;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
prevComponentsOrder.current = newComponentsOrder;
|
||||
return newComponentsOrder;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [components, currentLayout, reorderContainerChildren.triggerUpdate, id]);
|
||||
|
||||
return sortedComponents;
|
||||
};
|
||||
|
||||
export default useSortedComponents;
|
||||
|
|
@ -8,6 +8,10 @@ const initialState = {
|
|||
lastCanvasIdClick: '',
|
||||
lastCanvasClickPosition: null,
|
||||
draggingComponentId: null,
|
||||
reorderContainerChildren: {
|
||||
containerId: null,
|
||||
triggerUpdate: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export const createGridSlice = (set, get) => ({
|
||||
|
|
@ -73,4 +77,10 @@ export const createGridSlice = (set, get) => ({
|
|||
setLastCanvasClickPosition: (position) => {
|
||||
set({ lastCanvasClickPosition: position });
|
||||
},
|
||||
setReorderContainerChildren: (containerId) => {
|
||||
// Function to trigger reordering of specific container for tab navigation
|
||||
set((state) => ({
|
||||
reorderContainerChildren: { containerId, triggerUpdate: state.reorderContainerChildren.triggerUpdate + 1 },
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue