diff --git a/frontend/src/AppBuilder/AppCanvas/ConfigHandle/ConfigHandle.jsx b/frontend/src/AppBuilder/AppCanvas/ConfigHandle/ConfigHandle.jsx index aaedf9deb9..45835c39de 100644 --- a/frontend/src/AppBuilder/AppCanvas/ConfigHandle/ConfigHandle.jsx +++ b/frontend/src/AppBuilder/AppCanvas/ConfigHandle/ConfigHandle.jsx @@ -48,7 +48,6 @@ export const ConfigHandle = ({ }, shallow); let height = visibility === false ? 10 : widgetHeight; - return (
{ diff --git a/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx b/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx index 174c68b475..7043c78774 100644 --- a/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx +++ b/frontend/src/AppBuilder/AppCanvas/Grid/Grid.jsx @@ -23,8 +23,6 @@ import { handleDeactivateTargets, handleActivateNonDraggingComponents, } from './gridUtils'; -import { useAppVersionStore } from '@/_stores/appVersionStore'; -import { resolveWidgetFieldValue } from '@/_helpers/utils'; import { dragContextBuilder, getAdjustedDropPosition } from './helpers/dragEnd'; import useStore from '@/AppBuilder/_stores/store'; import './Grid.css'; @@ -67,6 +65,8 @@ export default function Grid({ gridWidth, currentLayout }) { const prevDragParentId = useRef(null); const newDragParentId = useRef(null); const [isGroupDragging, setIsGroupDragging] = useState(false); + const checkIfAnyWidgetVisibilityChanged = useStore((state) => state.checkIfAnyWidgetVisibilityChanged(), shallow); + const getExposedValueOfComponent = useStore((state) => state.getExposedValueOfComponent, shallow); const setReorderContainerChildren = useStore((state) => state.setReorderContainerChildren, shallow); useEffect(() => { @@ -319,7 +319,7 @@ export default function Grid({ gridWidth, currentLayout }) { useEffect(() => { reloadGrid(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedComponents, openModalWidgetId, boxList, currentLayout]); + }, [selectedComponents, openModalWidgetId, boxList, currentLayout, checkIfAnyWidgetVisibilityChanged]); const updateNewPosition = (events, parent = null) => { const posWithParent = { @@ -331,6 +331,8 @@ export default function Grid({ gridWidth, currentLayout }) { const isComponentVisible = (id) => { const component = getResolvedComponent(id); + const componentExposedVisibility = getExposedValueOfComponent(id)?.isVisible; + if (componentExposedVisibility === false) return false; let visibility; if (isArray(component)) { visibility = component?.[0]?.properties?.visibility ?? component?.[0]?.styles?.visibility ?? null; @@ -633,13 +635,13 @@ export default function Grid({ gridWidth, currentLayout }) { // When clicked on widget boundary/resizer, select the component setSelectedComponents([e.target.id]); } - showGridLines(); if (!isComponentVisible(e.target.id)) { return false; } handleActivateNonDraggingComponents(); useGridStore.getState().actions.setResizingComponentId(e.target.id); e.setMin([gridWidth, GRID_HEIGHT]); + showGridLines(); }} onResizeEnd={(e) => { try { @@ -648,10 +650,12 @@ export default function Grid({ gridWidth, currentLayout }) { return id === e.target.id; }); hideGridLines(); + if (!e.lastEvent) { + return; + } let _gridWidth = useGridStore.getState().subContainerWidths[currentWidget.component?.parent] || gridWidth; let width = Math.round(e?.lastEvent?.width / _gridWidth) * _gridWidth; const height = Math.round(e?.lastEvent?.height / GRID_HEIGHT) * GRID_HEIGHT; - const currentWidth = currentWidget.width * _gridWidth; const diffWidth = e.lastEvent?.width - currentWidth; const diffHeight = e.lastEvent?.height - currentWidget?.height; @@ -882,7 +886,6 @@ export default function Grid({ gridWidth, currentLayout }) { left = dragged.left * sourcegridWidth; top = dragged.top; - !isModalToCanvas ?? toast.error(`${dragged.widgetType} is not compatible as a child component of ${target.widgetType}`); } diff --git a/frontend/src/AppBuilder/AppCanvas/RenderWidget.jsx b/frontend/src/AppBuilder/AppCanvas/RenderWidget.jsx index 1116c3fb42..7862db5676 100644 --- a/frontend/src/AppBuilder/AppCanvas/RenderWidget.jsx +++ b/frontend/src/AppBuilder/AppCanvas/RenderWidget.jsx @@ -7,6 +7,7 @@ import { renderTooltip } from '@/_helpers/appUtils'; import { useTranslation } from 'react-i18next'; import ErrorBoundary from '@/_ui/ErrorBoundary'; import { BOX_PADDING } from './appCanvasConstants'; + const shouldAddBoxShadowAndVisibility = [ 'Table', 'TextInput', diff --git a/frontend/src/AppBuilder/AppCanvas/WidgetWrapper.jsx b/frontend/src/AppBuilder/AppCanvas/WidgetWrapper.jsx index 0384d4cc6e..df78a8afa4 100644 --- a/frontend/src/AppBuilder/AppCanvas/WidgetWrapper.jsx +++ b/frontend/src/AppBuilder/AppCanvas/WidgetWrapper.jsx @@ -37,6 +37,8 @@ const WidgetWrapper = memo( }); const visibility = useStore((state) => { const component = state.getResolvedComponent(id, subContainerIndex); + const componentExposedVisibility = state.getExposedValueOfComponent(id)?.isVisible; + if (componentExposedVisibility === false) return false; if (component?.properties?.visibility === false || component?.styles?.visibility === false) return false; return true; }); @@ -52,7 +54,7 @@ const WidgetWrapper = memo( height: visibility === false ? '10px' : `${height}px`, transform: `translate(${layoutData.left * gridWidth}px, ${layoutData.top}px)`, WebkitFontSmoothing: 'antialiased', - border: visibility === false ? `1px solid var(--border-default)` : 'none', + border: visibility === false && mode === 'edit' ? `1px solid var(--border-default)` : 'none', }; if (!componentType) return null; diff --git a/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js b/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js index 8d5f2dfe62..913d3a22df 100644 --- a/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js +++ b/frontend/src/AppBuilder/AppCanvas/appCanvasUtils.js @@ -49,8 +49,16 @@ export const addNewWidgetToTheEditor = (componentType, eventMonitorObject, curre left = Math.round(left / gridWidth); // Adjust widget width based on the dropping canvas width const mainCanvasWidth = useGridStore.getState().subContainerWidths['canvas']; - const width = Math.round((defaultWidth * mainCanvasWidth) / gridWidth); + let width = Math.round((defaultWidth * mainCanvasWidth) / gridWidth); + // Ensure minimum width + width = Math.max(width, 1); + + // Adjust position and width if exceeding grid bounds + if (width + left > NO_OF_GRIDS) { + left = Math.max(0, NO_OF_GRIDS - width); + width = Math.min(width, NO_OF_GRIDS); + } if (currentLayout === 'mobile') { componentData.definition.others.showOnDesktop.value = `{{false}}`; componentData.definition.others.showOnMobile.value = `{{true}}`; @@ -513,7 +521,7 @@ export function pasteComponents(targetParentId, copiedComponentObj) { targetParentId === key || (components?.[key]?.component.component === 'Tabs' && targetParentId?.split('-')?.slice(0, -1)?.join('-') === key) || - (['Container', 'Form', 'Modal'].includes(components?.[key]?.component.component) && + (['Container', 'Form', 'ModalV2'].includes(components?.[key]?.component.component) && ['header', 'footer'].some((section) => targetParentId.includes(section))) ) ) { @@ -525,6 +533,7 @@ export function pasteComponents(targetParentId, copiedComponentObj) { } pastedComponents.forEach((component) => { + component = deepClone(component); const newComponentId = isCut ? component.id : uuidv4(); const componentName = computeComponentName(component.component.component, { ...components, @@ -565,15 +574,28 @@ export function pasteComponents(targetParentId, copiedComponentObj) { componentData.definition.others.showOnMobile.value = currentLayout === 'mobile' ? `{{true}}` : `{{false}}`; // Adjust width if parent changed - let width = component.layouts.desktop.width; + let width = component.layouts[currentLayout].width; if (targetParentId !== component.component?.parent) { const containerWidth = useGridStore.getState().subContainerWidths[targetParentId || 'canvas']; const oldContainerWidth = useGridStore.getState().subContainerWidths[component?.component?.parent || 'canvas']; width = Math.round((width * oldContainerWidth) / containerWidth); + + // Ensure minimum width + width = Math.max(width, 1); + + // Adjust position and width if exceeding grid bounds + if (width + component.layouts[currentLayout].left > NO_OF_GRIDS) { + component.layouts[currentLayout].left = Math.max(0, NO_OF_GRIDS - width); + width = Math.min(width, NO_OF_GRIDS); + } } - component.layouts[currentLayout].width = width; + component.layouts[currentLayout] = { + ...component.layouts[currentLayout], + width, + }; + const newComponent = { component: { ...componentData, diff --git a/frontend/src/AppBuilder/AppCanvas/selecto.scss b/frontend/src/AppBuilder/AppCanvas/selecto.scss index 5602b35d5a..7366e2fd06 100644 --- a/frontend/src/AppBuilder/AppCanvas/selecto.scss +++ b/frontend/src/AppBuilder/AppCanvas/selecto.scss @@ -1,5 +1,5 @@ .active-target { - outline: 1px solid #4af; + outline: 1px solid #4af !important; } .main-editor-canvas .widget-target:not(:has(.widget-target:hover)):hover { diff --git a/frontend/src/AppBuilder/RightSideBar/ComponentsManagerTab/DragLayer.jsx b/frontend/src/AppBuilder/RightSideBar/ComponentsManagerTab/DragLayer.jsx index 77274cd658..9589ac145b 100644 --- a/frontend/src/AppBuilder/RightSideBar/ComponentsManagerTab/DragLayer.jsx +++ b/frontend/src/AppBuilder/RightSideBar/ComponentsManagerTab/DragLayer.jsx @@ -42,12 +42,18 @@ const CustomDragLayer = ({ size }) => { const canvasBounds = item?.canvasRef?.getBoundingClientRect(); const height = size.height; - const width = (canvasWidth * size.width) / NO_OF_GRIDS; + const mainCanvasWidth = document.getElementById('real-canvas')?.offsetWidth || 0; + let width = (mainCanvasWidth * size.width) / NO_OF_GRIDS; // Calculate position relative to the current canvas (parent or child) const left = currentOffset.x - (canvasBounds?.left || 0); const top = currentOffset.y - (canvasBounds?.top || 0); + // Adjust position and width if exceeding grid bounds + if (width >= canvasWidth) { + width = canvasWidth; + } + const [x, y] = snapToGrid(canvasWidth, left, top); return (
({ setLastCanvasClickPosition: (position) => { set({ lastCanvasClickPosition: position }); }, + checkIfAnyWidgetVisibilityChanged: () => { + // This is required to reload the grid if visibility is turned off using CSA + const { getExposedValueOfComponent, getCurrentPageComponents } = get(); + const currentPageComponents = getCurrentPageComponents(); + + const visibilityState = {}; + + Object.keys(currentPageComponents).forEach((componentId) => { + const componentExposedVisibility = getExposedValueOfComponent(componentId)?.isVisible; + + // Determine if component is visible + visibilityState[componentId] = !(componentExposedVisibility === false); + }); + + return visibilityState; + }, setReorderContainerChildren: (containerId) => { // Function to trigger reordering of specific container for tab navigation set((state) => ({