From 1fc9961bf487df716fbf4147241d080bc684a026 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:06:10 +0100 Subject: [PATCH 01/38] Allow DataGrid height to be styled, fix HUD position in full-page elements --- .../PageEditor/RenderPanel/NodeHud.tsx | 27 ++++++++-- packages/toolpad-components/src/DataGrid.tsx | 51 +++++++++---------- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx index 5470b87082a..e8563370aa2 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx @@ -12,13 +12,18 @@ import { RECTANGLE_EDGE_LEFT, RECTANGLE_EDGE_RIGHT, } from '../../../../utils/geometry'; +import { usePageEditorState } from '../PageEditorProvider'; const HINT_POSITION_TOP = 'top'; const HINT_POSITION_BOTTOM = 'bottom'; +const HINT_POSITION_BOTTOM_INNER = 'bottomInner'; const HUD_HEIGHT = 30; // px -type HintPosition = typeof HINT_POSITION_TOP | typeof HINT_POSITION_BOTTOM; +type HintPosition = + | typeof HINT_POSITION_TOP + | typeof HINT_POSITION_BOTTOM + | typeof HINT_POSITION_BOTTOM_INNER; function stopPropagationHandler(event: React.SyntheticEvent) { event.stopPropagation(); @@ -84,7 +89,11 @@ const SelectionHintWrapper = styled('div', { zIndex: 1000, ...(hintPosition === HINT_POSITION_TOP ? { top: 0, transform: 'translate(0, -100%)' } - : { bottom: 0, transform: 'translate(0, 100%)' }), + : { + bottom: 0, + transform: + hintPosition === HINT_POSITION_BOTTOM_INNER ? 'translate(0, 0)' : 'translate(0, 100%)', + }), }, })); @@ -177,7 +186,19 @@ export default function NodeHud({ isHoverable = true, isHovered = false, }: NodeHudProps) { - const hintPosition = rect.y > HUD_HEIGHT ? HINT_POSITION_TOP : HINT_POSITION_BOTTOM; + const { nodeId: pageNodeId, viewState } = usePageEditorState(); + + const { nodes: nodesInfo } = viewState; + + const pageNodeRect = nodesInfo[pageNodeId]?.rect; + + let hintPosition: HintPosition = HINT_POSITION_BOTTOM; + if (rect.y > HUD_HEIGHT) { + hintPosition = HINT_POSITION_TOP; + } + if (pageNodeRect && rect.y + rect.height + HUD_HEIGHT >= pageNodeRect.height) { + hintPosition = HINT_POSITION_BOTTOM_INNER; + } const interactiveNodeClipPath = React.useMemo( () => diff --git a/packages/toolpad-components/src/DataGrid.tsx b/packages/toolpad-components/src/DataGrid.tsx index c571a05e5e4..821895116f6 100644 --- a/packages/toolpad-components/src/DataGrid.tsx +++ b/packages/toolpad-components/src/DataGrid.tsx @@ -36,6 +36,7 @@ import { Typography, Tooltip, Popover, + Container, } from '@mui/material'; import { getObjectKey } from '@mui/toolpad-utils/objectKey'; import { errorFrom } from '@mui/toolpad-utils/errors'; @@ -366,6 +367,7 @@ const DataGridComponent = React.forwardRef(function DataGridComponent( selection, onSelectionChange, hideToolbar, + sx, ...props }: ToolpadDataGridProps, ref: React.ForwardedRef, @@ -487,37 +489,34 @@ const DataGridComponent = React.forwardRef(function DataGridComponent( return ( -
- -
- -
-
+ /> +
); }); From 87cbb61585e510d2837fc581e9d7c733a3af1bfb Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:26:47 +0100 Subject: [PATCH 02/38] Only use bottom inner hint position if defaulting to bottom position --- .../src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx index e8563370aa2..361e607d2d6 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx @@ -195,8 +195,7 @@ export default function NodeHud({ let hintPosition: HintPosition = HINT_POSITION_BOTTOM; if (rect.y > HUD_HEIGHT) { hintPosition = HINT_POSITION_TOP; - } - if (pageNodeRect && rect.y + rect.height + HUD_HEIGHT >= pageNodeRect.height) { + } else if (pageNodeRect && rect.y + rect.height + HUD_HEIGHT >= pageNodeRect.height) { hintPosition = HINT_POSITION_BOTTOM_INNER; } From e04aff286ed90e078804a331934920b0ce7f66df Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 4 Sep 2023 22:35:35 +0100 Subject: [PATCH 03/38] Update NodeHud.tsx --- .../src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx index 361e607d2d6..f625bc05082 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx @@ -195,7 +195,7 @@ export default function NodeHud({ let hintPosition: HintPosition = HINT_POSITION_BOTTOM; if (rect.y > HUD_HEIGHT) { hintPosition = HINT_POSITION_TOP; - } else if (pageNodeRect && rect.y + rect.height + HUD_HEIGHT >= pageNodeRect.height) { + } else if (pageNodeRect && rect.y + rect.height + HUD_HEIGHT > pageNodeRect.height) { hintPosition = HINT_POSITION_BOTTOM_INNER; } From 95d16f60564dfbdd70c6e097949abded3c60b5d3 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 11 Oct 2023 21:52:19 +0100 Subject: [PATCH 04/38] Fix creating new page with blur and default name + scroll only below explorer headers --- .../src/components/EditableTreeItem.tsx | 13 +++------- .../src/toolpad/AppEditor/ExplorerHeader.tsx | 3 --- .../toolpad/AppEditor/PagesExplorer/index.tsx | 26 +++++++------------ 3 files changed, 13 insertions(+), 29 deletions(-) diff --git a/packages/toolpad-app/src/components/EditableTreeItem.tsx b/packages/toolpad-app/src/components/EditableTreeItem.tsx index 27e833ee4de..58b98f5fe1c 100644 --- a/packages/toolpad-app/src/components/EditableTreeItem.tsx +++ b/packages/toolpad-app/src/components/EditableTreeItem.tsx @@ -98,16 +98,9 @@ export default function EditableTreeItem({ event.target.select(); }, []); - const handleBlur = React.useCallback( - (event: React.FocusEvent) => { - if (!suggestedNewItemName || (event && event.target.value !== suggestedNewItemName)) { - handleConfirm(); - } else { - handleCancel(); - } - }, - [handleCancel, handleConfirm, suggestedNewItemName], - ); + const handleBlur = React.useCallback(() => { + handleConfirm(); + }, [handleConfirm]); const handleKeyDown = React.useCallback( (event: React.KeyboardEvent) => { diff --git a/packages/toolpad-app/src/toolpad/AppEditor/ExplorerHeader.tsx b/packages/toolpad-app/src/toolpad/AppEditor/ExplorerHeader.tsx index bb6d799a769..abe8e93c786 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/ExplorerHeader.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/ExplorerHeader.tsx @@ -10,9 +10,6 @@ interface ExplorerHeaderProps { const ExplorerHeaderContainer = styled(Stack)(({ theme }) => ({ backgroundColor: theme.palette.background.paper, - position: 'sticky', - top: 0, - left: 0, width: '100%', zIndex: 1, height: 36, diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PagesExplorer/index.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PagesExplorer/index.tsx index 0587f541ea4..461d4949ddd 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PagesExplorer/index.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PagesExplorer/index.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { styled, Box, IconButton } from '@mui/material'; +import { styled, Box, IconButton, Stack } from '@mui/material'; import { TreeView, treeItemClasses } from '@mui/x-tree-view'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; @@ -19,8 +19,8 @@ import EditableTreeItem, { EditableTreeItemProps } from '../../../components/Edi import { scrollIntoViewIfNeeded } from '../../../utils/dom'; import ExplorerHeader from '../ExplorerHeader'; -const PagesExplorerRoot = styled('div')({ - overflow: 'auto', +const PagesExplorerRoot = styled(Stack)({ + height: '100%', width: '100%', }); @@ -327,14 +327,12 @@ export default function PagesExplorer({ className }: PagesExplorerProps) { ); return ( - + + } defaultExpandIcon={} sx={{ + overflow: 'auto', scrollbarGutter: 'stable', }} > - {isCreateNewPageOpen ? ( Date: Thu, 12 Oct 2023 23:30:56 +0100 Subject: [PATCH 05/38] Fix resizing inside columns --- .../AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 4d2f1e9f83d..02d0a1f5eed 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1413,6 +1413,9 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isVerticallyResizable = isSelected && Boolean(nodeInfo?.componentConfig?.resizableHeightProp); + const isResizingVertically = + draggedEdge === RECTANGLE_EDGE_TOP || draggedEdge === RECTANGLE_EDGE_BOTTOM; + const isResizing = Boolean(draggedEdge); const isResizingNode = isResizing && node.id === draggedNodeId; @@ -1440,7 +1443,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { onEdgeDragStart={ isHorizontallyResizable || isVerticallyResizable ? handleEdgeDragStart( - parent && isPageColumnChild && !isVerticallyResizable ? parent : node, + parent && isPageColumnChild && !isResizingVertically ? parent : node, ) : undefined } From 97ec4286171dc97be2d32de1502463eee0cdb6e4 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:49:11 +0100 Subject: [PATCH 06/38] Fix resizing, add Spacer component (WIP) --- .../toolpad/reference/components/index.md | 1 + .../src/runtime/toolpadComponents/index.tsx | 4 +++ .../ComponentCatalog/ComponentCatalogItem.tsx | 2 ++ .../PageEditor/RenderPanel/RenderOverlay.tsx | 12 +++++++- packages/toolpad-app/src/toolpad/Toolpad.tsx | 3 +- packages/toolpad-components/src/Spacer.tsx | 29 +++++++++++++++++++ packages/toolpad-components/src/index.tsx | 2 ++ 7 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 packages/toolpad-components/src/Spacer.tsx diff --git a/docs/data/toolpad/reference/components/index.md b/docs/data/toolpad/reference/components/index.md index 43b864aea74..2ab059b41c2 100644 --- a/docs/data/toolpad/reference/components/index.md +++ b/docs/data/toolpad/reference/components/index.md @@ -20,6 +20,7 @@ - [PageRow](/toolpad/reference/components/page-row/) - [Paper](/toolpad/reference/components/paper/) - [Select](/toolpad/reference/components/select/) +- [Spacer](/toolpad/reference/components/spacer/) - [Stack](/toolpad/reference/components/stack/) - [Tabs](/toolpad/reference/components/tabs/) - [Text](/toolpad/reference/components/text/) diff --git a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx index 2adad9375bb..4782b315461 100644 --- a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx +++ b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx @@ -88,6 +88,10 @@ export const INTERNAL_COMPONENTS = new Map([ ['Metric', { displayName: 'Metric', builtIn: 'Metric', synonyms: ['value', 'number', 'output'] }], ['Checkbox', { displayName: 'Checkbox', builtIn: 'Checkbox', synonyms: ['switch'] }], [FORM_COMPONENT_ID, { displayName: 'Form', builtIn: 'Form', synonyms: [] }], + [ + 'Spacer', + { displayName: 'Spacer', builtIn: 'Spacer', synonyms: ['margin', 'blank', 'empty', 'void'] }, + ], ]); function createCodeComponent(domNode: appDom.CodeComponentNode): ToolpadComponentDefinition { diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx index c4fe5b8f14d..6b860192c87 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx @@ -33,6 +33,7 @@ import TagIcon from '@mui/icons-material/Tag'; import PasswordIcon from '@mui/icons-material/Password'; import LinkIcon from '@mui/icons-material/Link'; import TextFormatIcon from '@mui/icons-material/TextFormat'; +import SpaceBarIcon from '@mui/icons-material/SpaceBar'; const iconMap = new Map>([ ['Password', PasswordIcon], @@ -68,6 +69,7 @@ const iconMap = new Map>([ ['PageRow', TableRowsIcon], ['PageColumn', ViewColumnIcon], ['Metric', TagIcon], + ['Spacer', SpaceBarIcon], ]); type ComponentItemKind = 'future' | 'builtIn' | 'create' | 'custom'; diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 0370f0f5e15..cb2f9f55e24 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1368,6 +1368,17 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { [api, domApi, draggedEdge, draggedNode, nodesInfo], ); + // @TODO: Keep trying + // React.useEffect(() => { + // if (draggedEdge) { + // document.getElementById('yamaha').addEventListener('mouseup', handleEdgeDragEnd, true); + + // return () => { + // document.getElementById('yamaha').removeEventListener('mouseup', handleEdgeDragEnd, true); + // }; + // } + // }, [draggedEdge, handleEdgeDragEnd]); + return ( {/* Container that allows children to size to it with height: 100% */} - + {/* @TODO: pls delet sir pls */} + }> diff --git a/packages/toolpad-components/src/Spacer.tsx b/packages/toolpad-components/src/Spacer.tsx new file mode 100644 index 00000000000..bf53c7a6d74 --- /dev/null +++ b/packages/toolpad-components/src/Spacer.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { Box, BoxProps } from '@mui/material'; +import createBuiltin from './createBuiltin'; +import { SX_PROP_HELPER_TEXT } from './constants'; + +interface SpacerProps extends BoxProps { + height: number; +} + +function Spacer(props: SpacerProps) { + return ; +} + +export default createBuiltin(Spacer, { + helperText: 'Space component.\nIt allows for creating space between elements.', + resizableHeightProp: 'height', + argTypes: { + height: { + helperText: 'The height of the spacer.', + type: 'number', + default: 160, + minimum: 20, + }, + sx: { + helperText: SX_PROP_HELPER_TEXT, + type: 'object', + }, + }, +}); diff --git a/packages/toolpad-components/src/index.tsx b/packages/toolpad-components/src/index.tsx index d0f112ad58c..0ed2e3c78b1 100644 --- a/packages/toolpad-components/src/index.tsx +++ b/packages/toolpad-components/src/index.tsx @@ -36,6 +36,8 @@ export { default as Checkbox } from './Checkbox'; export { default as Form } from './Form'; +export { default as Spacer } from './Spacer'; + export { default as Metric } from './Metric'; export type { ColorScale, ColorScaleStop } from './Metric'; From 20a57647479dc3f9b19e1a5aa7585d230f3966c0 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 20 Oct 2023 19:13:50 +0100 Subject: [PATCH 07/38] Vertical resizing with spacer (ongoing) --- packages/toolpad-app/src/appDom/index.ts | 16 ++ packages/toolpad-app/src/canvas/index.tsx | 9 + .../src/runtime/toolpadComponents/index.tsx | 1 + packages/toolpad-app/src/server/localMode.ts | 13 +- .../PageEditor/RenderPanel/NodeHud.tsx | 10 + .../PageEditor/RenderPanel/RenderOverlay.tsx | 213 +++++++++++++----- .../src/toolpad/AppEditor/pageLayout.ts | 4 + packages/toolpad-app/src/toolpad/Toolpad.tsx | 3 +- packages/toolpad-components/src/DataGrid.tsx | 9 +- packages/toolpad-components/src/Spacer.tsx | 2 +- packages/toolpad-core/src/types.ts | 2 +- 11 files changed, 206 insertions(+), 76 deletions(-) diff --git a/packages/toolpad-app/src/appDom/index.ts b/packages/toolpad-app/src/appDom/index.ts index 9abb99128eb..8a8e22d0627 100644 --- a/packages/toolpad-app/src/appDom/index.ts +++ b/packages/toolpad-app/src/appDom/index.ts @@ -816,6 +816,22 @@ export function moveNode( return setNodeParent(dom, node, parent.id, parentProp, parentIndex); } +export function spreadNode(dom: AppDom, node: Child) { + const parent = getParent(dom, node); + const parentProp = node.parentProp; + + let draft = dom; + if (parent && parentProp && isElement(node)) { + for (const child of getDescendants(draft, node)) { + const parentIndex = getNewParentIndexBeforeNode(draft, node, parentProp); + draft = setNodeParent(draft, child, parent.id, parentProp, parentIndex); + } + draft = removeNode(draft, node.id); + } + + return draft; +} + export function nodeExists(dom: AppDom, nodeId: NodeId): boolean { return !!getMaybeNode(dom, nodeId); } diff --git a/packages/toolpad-app/src/canvas/index.tsx b/packages/toolpad-app/src/canvas/index.tsx index 7763af531f3..013503c2c5f 100644 --- a/packages/toolpad-app/src/canvas/index.tsx +++ b/packages/toolpad-app/src/canvas/index.tsx @@ -81,6 +81,15 @@ export default function AppCanvas({ } }); + const handleWindowResize = React.useCallback(() => { + handleScreenUpdate(); + }, []); + + React.useEffect(() => { + window.addEventListener('resize', handleWindowResize, false); + return () => window.removeEventListener('resize', handleWindowResize, false); + }, [handleWindowResize]); + React.useEffect(() => { if (!bridge) { return; diff --git a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx index 372d532188b..e9eb4a9c11f 100644 --- a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx +++ b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx @@ -18,6 +18,7 @@ export type InstantiatedComponents = Record optimizePageElement(child, true)); + } + const isLayoutElement = (possibleLayoutElement: ElementType): boolean => possibleLayoutElement.component === PAGE_ROW_COMPONENT_ID || possibleLayoutElement.component === PAGE_COLUMN_COMPONENT_ID; @@ -753,7 +760,7 @@ function optimizePageElement(element: ElementType): ElementType { return { ...element, - children: element.children && element.children.map(optimizePageElement), + children: element.children && element.children.flatMap((child) => optimizePageElement(child)), }; } @@ -762,7 +769,7 @@ function optimizePage(page: Page): Page { ...page, spec: { ...page.spec, - content: page.spec.content?.map(optimizePageElement), + content: page.spec.content?.flatMap((element) => optimizePageElement(element, true)), }, }; } diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx index f625bc05082..005fd9ec63d 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx @@ -11,6 +11,7 @@ import { RECTANGLE_EDGE_BOTTOM, RECTANGLE_EDGE_LEFT, RECTANGLE_EDGE_RIGHT, + RECTANGLE_EDGE_TOP, } from '../../../../utils/geometry'; import { usePageEditorState } from '../PageEditorProvider'; @@ -136,6 +137,15 @@ const DraggableEdge = styled('div', { width: '100%', }; } + if (edge === RECTANGLE_EDGE_TOP) { + dynamicStyles = { + cursor: 'ns-resize', + top: -10, + height: 22, + left: 0, + width: '100%', + }; + } return { ...dynamicStyles, diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index cb2f9f55e24..fb6f9879b2c 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { NodeId } from '@mui/toolpad-core'; +import { NodeId, NumberValueType } from '@mui/toolpad-core'; import { styled } from '@mui/material'; import clsx from 'clsx'; import invariant from 'invariant'; @@ -23,6 +23,7 @@ import { PAGE_COLUMN_COMPONENT_ID, isFormComponent, FORM_COMPONENT_ID, + SPACER_COMPONENT_ID, } from '../../../../runtime/toolpadComponents'; import { getRectanglePointActiveEdge, @@ -52,8 +53,6 @@ import { const VERTICAL_RESIZE_SNAP_UNITS = 2; // px -const MIN_RESIZABLE_ELEMENT_HEIGHT = 100; // px - const overlayClasses = { hud: 'Toolpad_Hud', nodeHud: 'Toolpad_NodeHud', @@ -306,7 +305,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isFirstChild = parent && appDom.isElement(parent) && nodeParentProp - ? appDom.getNodeFirstChild(dom, parent, node.parentProp)?.id === node.id + ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id : false; const isLastChild = parent && appDom.isElement(parent) && nodeParentProp @@ -332,11 +331,18 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { (event: React.MouseEvent) => { event.stopPropagation(); - api.edgeDragStart({ nodeId: node.id, edge }); + const parent = appDom.getParent(dom, node); - selectNode(node.id); + const isPageColumnChild = parent ? appDom.isElement(parent) && isPageColumn(parent) : false; + const isResizingVertically = edge === RECTANGLE_EDGE_TOP || edge === RECTANGLE_EDGE_BOTTOM; + + const nodeToResize = parent && isPageColumnChild && !isResizingVertically ? parent : node; + + api.edgeDragStart({ nodeId: nodeToResize.id, edge }); + + selectNode(nodeToResize.id); }, - [api, selectNode], + [api, dom, selectNode], ); const handleKeyDown = React.useCallback( @@ -1183,6 +1189,10 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const cursorPos = bridge?.canvasCommands.getViewCoordinates(event.clientX, event.clientY); + const previousSibling = appDom.getSiblingBeforeNode(dom, draggedNode, 'children'); + const previousSiblingInfo = previousSibling && nodesInfo[previousSibling.id]; + const previousSiblingRect = previousSiblingInfo?.rect; + if (draggedNodeRect && parentRect && resizePreviewElement && cursorPos) { if (draggedEdge === RECTANGLE_EDGE_LEFT || draggedEdge === RECTANGLE_EDGE_RIGHT) { let snappedToGridCursorRelativePosX = cursorPos.x - draggedNodeRect.x; @@ -1200,10 +1210,6 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { } } - const previousSibling = appDom.getSiblingBeforeNode(dom, draggedNode, 'children'); - const previousSiblingInfo = previousSibling && nodesInfo[previousSibling.id]; - const previousSiblingRect = previousSiblingInfo?.rect; - if ( draggedEdge === RECTANGLE_EDGE_LEFT && cursorPos.x > @@ -1238,9 +1244,28 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { } } + const defaultMinimumResizableHeight = 100; + + const resizableHeightProp = draggedNodeInfo?.componentConfig?.resizableHeightProp; + const minimumVerticalResizeHeight = resizableHeightProp + ? (draggedNodeInfo.componentConfig?.argTypes![resizableHeightProp] as NumberValueType) + .minimum ?? 100 + : null; + + const previousSiblingResizableHeightProp = + previousSiblingInfo?.componentConfig?.resizableHeightProp; + const previousSiblingMinimumVerticalResizeHeight = previousSiblingResizableHeightProp + ? ( + previousSiblingInfo.componentConfig?.argTypes![ + previousSiblingResizableHeightProp + ] as NumberValueType + ).minimum ?? defaultMinimumResizableHeight + : previousSiblingRect?.height ?? null; + if ( draggedEdge === RECTANGLE_EDGE_BOTTOM && - cursorPos.y > draggedNodeRect.y + MIN_RESIZABLE_ELEMENT_HEIGHT + minimumVerticalResizeHeight && + cursorPos.y > draggedNodeRect.y + minimumVerticalResizeHeight ) { const snappedToGridCursorRelativePosY = Math.ceil((cursorPos.y - draggedNodeRect.y) / VERTICAL_RESIZE_SNAP_UNITS) * @@ -1251,6 +1276,29 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { resizePreviewElement.style.transformOrigin = '50% 0'; resizePreviewElement.style.transform = `scaleY(${updatedTransformScale})`; } + + if ( + draggedEdge === RECTANGLE_EDGE_TOP && + minimumVerticalResizeHeight && + cursorPos.y < draggedNodeRect.y + draggedNodeRect.height - minimumVerticalResizeHeight && + (!previousSiblingRect || + !previousSiblingMinimumVerticalResizeHeight || + cursorPos.y > + draggedNodeRect.y - + previousSiblingRect.height + + previousSiblingMinimumVerticalResizeHeight) + ) { + const snappedToGridCursorRelativePosY = + Math.ceil( + (draggedNodeRect.y + draggedNodeRect.height - cursorPos.y) / + VERTICAL_RESIZE_SNAP_UNITS, + ) * VERTICAL_RESIZE_SNAP_UNITS; + + const updatedTransformScale = snappedToGridCursorRelativePosY / draggedNodeRect.height; + + resizePreviewElement.style.transformOrigin = '50% 100%'; + resizePreviewElement.style.transform = `scaleY(${updatedTransformScale})`; + } } }, [bridge, dom, draggedEdge, draggedNode, nodesInfo], @@ -1272,41 +1320,43 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { if (draggedNodeRect && resizePreviewRect) { domApi.update((draft) => { - if (draggedEdge === RECTANGLE_EDGE_LEFT || draggedEdge === RECTANGLE_EDGE_RIGHT) { - if (draggedEdge === RECTANGLE_EDGE_LEFT) { - const previousSibling = appDom.getSiblingBeforeNode(draft, draggedNode, 'children'); + const parent = appDom.getParent(draft, draggedNode); - if (previousSibling) { - const previousSiblingInfo = nodesInfo[previousSibling.id]; - const previousSiblingRect = previousSiblingInfo?.rect; + let previousSibling = appDom.getSiblingBeforeNode(draft, draggedNode, 'children'); - if (previousSiblingRect) { - const totalResizedColumnsSize = - (draggedNode.layout?.columnSize || 1) + - (previousSibling.layout?.columnSize || 1); - const totalResizedColumnsWidth = - draggedNodeRect.width + previousSiblingRect.width; + let previousSiblingInfo = null; + let previousSiblingRect = null; + if (previousSibling) { + previousSiblingInfo = nodesInfo[previousSibling.id]; + previousSiblingRect = previousSiblingInfo?.rect; + } - const updatedDraggedNodeColumnSize = - (resizePreviewRect.width / totalResizedColumnsWidth) * totalResizedColumnsSize; - const updatedPreviousSiblingColumnSize = - totalResizedColumnsSize - updatedDraggedNodeColumnSize; + if (draggedEdge === RECTANGLE_EDGE_LEFT || draggedEdge === RECTANGLE_EDGE_RIGHT) { + if (draggedEdge === RECTANGLE_EDGE_LEFT) { + if (previousSibling && previousSiblingRect) { + const totalResizedColumnsSize = + (draggedNode.layout?.columnSize || 1) + (previousSibling.layout?.columnSize || 1); + const totalResizedColumnsWidth = draggedNodeRect.width + previousSiblingRect.width; - draft = appDom.setNodeNamespacedProp( - draft, - draggedNode, - 'layout', - 'columnSize', - updatedDraggedNodeColumnSize, - ); - draft = appDom.setNodeNamespacedProp( - draft, - previousSibling, - 'layout', - 'columnSize', - updatedPreviousSiblingColumnSize, - ); - } + const updatedDraggedNodeColumnSize = + (resizePreviewRect.width / totalResizedColumnsWidth) * totalResizedColumnsSize; + const updatedPreviousSiblingColumnSize = + totalResizedColumnsSize - updatedDraggedNodeColumnSize; + + draft = appDom.setNodeNamespacedProp( + draft, + draggedNode, + 'layout', + 'columnSize', + updatedDraggedNodeColumnSize, + ); + draft = appDom.setNodeNamespacedProp( + draft, + previousSibling, + 'layout', + 'columnSize', + updatedPreviousSiblingColumnSize, + ); } } if (draggedEdge === RECTANGLE_EDGE_RIGHT) { @@ -1345,7 +1395,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { } } - if (draggedEdge === RECTANGLE_EDGE_BOTTOM) { + if (draggedEdge === RECTANGLE_EDGE_BOTTOM || draggedEdge === RECTANGLE_EDGE_TOP) { const resizableHeightProp = draggedNodeInfo?.componentConfig?.resizableHeightProp; if (resizableHeightProp) { @@ -1356,6 +1406,47 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { resizableHeightProp, resizePreviewRect.height, ); + + if (draggedEdge === RECTANGLE_EDGE_TOP) { + let previousSiblingResizableHeightProp = + previousSiblingInfo?.componentConfig?.resizableHeightProp; + + const draggedNodeParentProp = draggedNode.parentProp; + + const hasNewSpacer = + !previousSiblingResizableHeightProp && parent && draggedNodeParentProp; + + if (hasNewSpacer) { + const spacer = appDom.createElement(draft, SPACER_COMPONENT_ID); + + draft = appDom.addNode( + draft, + spacer, + parent, + draggedNodeParentProp, + appDom.getNewParentIndexBeforeNode(draft, draggedNode, draggedNodeParentProp), + ); + + previousSibling = spacer; + previousSiblingInfo = nodesInfo[previousSibling.id]; + previousSiblingRect = previousSiblingInfo?.rect; + previousSiblingResizableHeightProp = + previousSiblingInfo?.componentConfig?.resizableHeightProp; + } + + if (previousSibling && previousSiblingRect && previousSiblingResizableHeightProp) { + draft = appDom.setNodeNamespacedProp( + draft, + previousSibling, + 'props', + previousSiblingResizableHeightProp, + hasNewSpacer + ? draggedNodeRect.height - resizePreviewRect.height + : previousSiblingRect.height + + (draggedNodeRect.height - resizePreviewRect.height), + ); + } + } } } @@ -1368,17 +1459,6 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { [api, domApi, draggedEdge, draggedNode, nodesInfo], ); - // @TODO: Keep trying - // React.useEffect(() => { - // if (draggedEdge) { - // document.getElementById('yamaha').addEventListener('mouseup', handleEdgeDragEnd, true); - - // return () => { - // document.getElementById('yamaha').removeEventListener('mouseup', handleEdgeDragEnd, true); - // }; - // } - // }, [draggedEdge, handleEdgeDragEnd]); - return ( {/* Container that allows children to size to it with height: 100% */} - {/* @TODO: pls delet sir pls */} - + }> diff --git a/packages/toolpad-components/src/DataGrid.tsx b/packages/toolpad-components/src/DataGrid.tsx index 829d47877bd..8dd954e3649 100644 --- a/packages/toolpad-components/src/DataGrid.tsx +++ b/packages/toolpad-components/src/DataGrid.tsx @@ -43,7 +43,6 @@ import { Typography, Tooltip, Popover, - Container, } from '@mui/material'; import { getObjectKey } from '@mui/toolpad-utils/objectKey'; import { errorFrom } from '@mui/toolpad-utils/errors'; @@ -727,11 +726,7 @@ const DataGridComponent = React.forwardRef(function DataGridComponent( return ( - + - + ); }); diff --git a/packages/toolpad-components/src/Spacer.tsx b/packages/toolpad-components/src/Spacer.tsx index bf53c7a6d74..466022ca233 100644 --- a/packages/toolpad-components/src/Spacer.tsx +++ b/packages/toolpad-components/src/Spacer.tsx @@ -19,7 +19,7 @@ export default createBuiltin(Spacer, { helperText: 'The height of the spacer.', type: 'number', default: 160, - minimum: 20, + minimum: 4, }, sx: { helperText: SX_PROP_HELPER_TEXT, diff --git a/packages/toolpad-core/src/types.ts b/packages/toolpad-core/src/types.ts index b739b329f72..ca50b41990c 100644 --- a/packages/toolpad-core/src/types.ts +++ b/packages/toolpad-core/src/types.ts @@ -397,7 +397,7 @@ export type RuntimeEvent = { [K in keyof RuntimeEvents]: { type: K } & RuntimeEvents[K]; }[keyof RuntimeEvents]; -export interface ComponentConfig

{ +export interface ComponentConfig

> { /** * A short explanatory text that'll be shown in the editor UI when this component is referenced. * May contain Markdown. From 62e3ce1bc998d4cfc56bbe0c187e13112b521b61 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 20 Oct 2023 19:22:44 +0100 Subject: [PATCH 08/38] Fix duplication in page root --- packages/toolpad-app/src/appDom/index.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/toolpad-app/src/appDom/index.ts b/packages/toolpad-app/src/appDom/index.ts index 8a8e22d0627..dc6e8aba76b 100644 --- a/packages/toolpad-app/src/appDom/index.ts +++ b/packages/toolpad-app/src/appDom/index.ts @@ -1051,8 +1051,18 @@ export function duplicateNode( throw new Error(`Node "${node.id}" can't be duplicated, it must have a parent`); } - const fragment = cloneFragment(dom, node.id); - return addFragment(dom, fragment, parent.id, parentProp); + if (isElement(node)) { + const fragment = cloneFragment(dom, node.id); + return addFragment( + dom, + fragment, + parent.id, + parentProp, + getNewParentIndexAfterNode(dom, node, parentProp), + ); + } + + return dom; } const RENDERTREE_NODES = ['app', 'page', 'element', 'query', 'mutation', 'theme'] as const; From fbfca0bc632b7c42f8d30be16e6b9992733f0b63 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 1 Nov 2023 17:42:38 +0000 Subject: [PATCH 09/38] Fix more bugs, new layout height system --- packages/toolpad-app/src/appDom/index.ts | 4 +- .../toolpad-app/src/runtime/ToolpadApp.tsx | 3 +- packages/toolpad-app/src/server/localMode.ts | 1 + packages/toolpad-app/src/server/schema.ts | 1 + .../AppEditor/PageEditor/ComponentEditor.tsx | 7 +- .../PageEditor/RenderPanel/RenderOverlay.tsx | 114 +++++------------- .../src/toolpad/AppEditor/pageLayout.ts | 1 - packages/toolpad-components/src/Chart.tsx | 18 +-- packages/toolpad-components/src/DataGrid.tsx | 16 +-- .../toolpad-components/src/PageColumn.tsx | 2 +- packages/toolpad-components/src/Spacer.tsx | 19 +-- packages/toolpad-core/src/types.ts | 9 +- 12 files changed, 55 insertions(+), 140 deletions(-) diff --git a/packages/toolpad-app/src/appDom/index.ts b/packages/toolpad-app/src/appDom/index.ts index dc6e8aba76b..e13ce97e65f 100644 --- a/packages/toolpad-app/src/appDom/index.ts +++ b/packages/toolpad-app/src/appDom/index.ts @@ -102,6 +102,7 @@ export interface ElementNode

extends AppDomNodeBase { readonly horizontalAlign?: BoxProps['justifyContent']; readonly verticalAlign?: BoxProps['alignItems']; readonly columnSize?: number; + readonly height?: number; }; } @@ -823,8 +824,7 @@ export function spreadNode(dom: AppDom, node: Child) { let draft = dom; if (parent && parentProp && isElement(node)) { for (const child of getDescendants(draft, node)) { - const parentIndex = getNewParentIndexBeforeNode(draft, node, parentProp); - draft = setNodeParent(draft, child, parent.id, parentProp, parentIndex); + draft = setNodeParent(draft, child, parent.id, parentProp); } draft = removeNode(draft, node.id); } diff --git a/packages/toolpad-app/src/runtime/ToolpadApp.tsx b/packages/toolpad-app/src/runtime/ToolpadApp.tsx index 48d23191999..506f616779a 100644 --- a/packages/toolpad-app/src/runtime/ToolpadApp.tsx +++ b/packages/toolpad-app/src/runtime/ToolpadApp.tsx @@ -433,10 +433,8 @@ function getQueryConfigBindings({ enabled, refetchInterval }: appDom.QueryNode[' } function isBindableProp(componentConfig: ComponentConfig, propName: string) { - const isResizableHeightProp = propName === componentConfig.resizableHeightProp; const argType = componentConfig.argTypes?.[propName]; return ( - !isResizableHeightProp && argType?.control?.bindable !== false && argType?.type !== 'template' && argType?.type !== 'event' @@ -1172,6 +1170,7 @@ function RenderedNodeContent({ node, childNodeGroups, Component }: RenderedNodeC display: 'flex', alignItems: boundLayoutProps.verticalAlign, justifyContent: boundLayoutProps.horizontalAlign, + height: node.layout?.height ?? componentConfig.defaultLayoutHeight, }} > diff --git a/packages/toolpad-app/src/server/localMode.ts b/packages/toolpad-app/src/server/localMode.ts index dde329f8b58..029ee34d0c1 100644 --- a/packages/toolpad-app/src/server/localMode.ts +++ b/packages/toolpad-app/src/server/localMode.ts @@ -541,6 +541,7 @@ function expandFromDom( name: node.name, layout: undefinedWhenEmpty({ columnSize: node.layout?.columnSize, + height: node.layout?.height, horizontalAlign: stringOnly(node.layout?.horizontalAlign), verticalAlign: stringOnly(node.layout?.verticalAlign), }), diff --git a/packages/toolpad-app/src/server/schema.ts b/packages/toolpad-app/src/server/schema.ts index 2e8c52c885a..0b7a33579cf 100644 --- a/packages/toolpad-app/src/server/schema.ts +++ b/packages/toolpad-app/src/server/schema.ts @@ -215,6 +215,7 @@ const baseElementSchema = z.object({ .number() .optional() .describe('The width this element takes up, expressed in terms of columns on the page.'), + height: z.number().optional().describe('The height this element takes up, in pixels.'), }) .optional() .describe('Layout properties for this element.'), diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx index 3ae8b92c02d..40e5701c58d 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentEditor.tsx @@ -45,7 +45,6 @@ function shouldRenderControl

( propTypeDef: ArgTypeDefinition

, propName: keyof P, props: P, - componentConfig: ComponentConfig

, ) { if (propTypeDef.type === 'element' || propTypeDef.type === 'template') { return ( @@ -63,10 +62,6 @@ function shouldRenderControl

( return propTypeDef.visible(props); } - if (componentConfig.resizableHeightProp && propName === componentConfig.resizableHeightProp) { - return false; - } - return true; } @@ -144,7 +139,7 @@ function ComponentPropsEditor

({ {category}: {argTypeEntries.map(([propName, propTypeDef]) => - propTypeDef && shouldRenderControl(propTypeDef, propName, props, componentConfig) ? ( + propTypeDef && shouldRenderControl(propTypeDef, propName, props) ? (

draggedNodeRect.y + minimumVerticalResizeHeight ) { const snappedToGridCursorRelativePosY = @@ -1279,10 +1268,8 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { if ( draggedEdge === RECTANGLE_EDGE_TOP && - minimumVerticalResizeHeight && cursorPos.y < draggedNodeRect.y + draggedNodeRect.height - minimumVerticalResizeHeight && (!previousSiblingRect || - !previousSiblingMinimumVerticalResizeHeight || cursorPos.y > draggedNodeRect.y - previousSiblingRect.height + @@ -1320,9 +1307,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { if (draggedNodeRect && resizePreviewRect) { domApi.update((draft) => { - const parent = appDom.getParent(draft, draggedNode); - - let previousSibling = appDom.getSiblingBeforeNode(draft, draggedNode, 'children'); + const previousSibling = appDom.getSiblingBeforeNode(draft, draggedNode, 'children'); let previousSiblingInfo = null; let previousSiblingRect = null; @@ -1396,57 +1381,22 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { } if (draggedEdge === RECTANGLE_EDGE_BOTTOM || draggedEdge === RECTANGLE_EDGE_TOP) { - const resizableHeightProp = draggedNodeInfo?.componentConfig?.resizableHeightProp; + draft = appDom.setNodeNamespacedProp( + draft, + draggedNode, + 'layout', + 'height', + resizePreviewRect.height, + ); - if (resizableHeightProp) { + if (draggedEdge === RECTANGLE_EDGE_TOP && previousSibling && previousSiblingRect) { draft = appDom.setNodeNamespacedProp( draft, - draggedNode, - 'props', - resizableHeightProp, - resizePreviewRect.height, + previousSibling, + 'layout', + 'height', + previousSiblingRect.height + (draggedNodeRect.height - resizePreviewRect.height), ); - - if (draggedEdge === RECTANGLE_EDGE_TOP) { - let previousSiblingResizableHeightProp = - previousSiblingInfo?.componentConfig?.resizableHeightProp; - - const draggedNodeParentProp = draggedNode.parentProp; - - const hasNewSpacer = - !previousSiblingResizableHeightProp && parent && draggedNodeParentProp; - - if (hasNewSpacer) { - const spacer = appDom.createElement(draft, SPACER_COMPONENT_ID); - - draft = appDom.addNode( - draft, - spacer, - parent, - draggedNodeParentProp, - appDom.getNewParentIndexBeforeNode(draft, draggedNode, draggedNodeParentProp), - ); - - previousSibling = spacer; - previousSiblingInfo = nodesInfo[previousSibling.id]; - previousSiblingRect = previousSiblingInfo?.rect; - previousSiblingResizableHeightProp = - previousSiblingInfo?.componentConfig?.resizableHeightProp; - } - - if (previousSibling && previousSiblingRect && previousSiblingResizableHeightProp) { - draft = appDom.setNodeNamespacedProp( - draft, - previousSibling, - 'props', - previousSiblingResizableHeightProp, - hasNewSpacer - ? draggedNodeRect.height - resizePreviewRect.height - : previousSiblingRect.height + - (draggedNodeRect.height - resizePreviewRect.height), - ); - } - } } } @@ -1507,9 +1457,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isSelected = selectedNode && !newNode ? selectedNode.id === node.id : false; const isHovered = hoveredNodeId === node.id; - const isHorizontallyResizable = isSelected && (isPageRowChild || isPageColumnChild); - const isVerticallyResizable = - isSelected && Boolean(nodeInfo?.componentConfig?.resizableHeightProp); + const isHorizontallyResizable = isPageRowChild || isPageColumnChild; const isResizing = Boolean(draggedEdge); const isResizingNode = isResizing && node.id === draggedNodeId; @@ -1532,21 +1480,13 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { onNodeDragStart={handleNodeDragStart(node as appDom.ElementNode)} onDuplicate={handleNodeDuplicate(node as appDom.ElementNode)} draggableEdges={[ - ...getNodeDraggableHorizontalEdges(parent && isPageColumnChild ? parent : node), - ...(isVerticallyResizable - ? [ - RECTANGLE_EDGE_BOTTOM as RectangleEdge, - ...(isPageColumnChild && !isFirstChild - ? [RECTANGLE_EDGE_TOP as RectangleEdge] - : []), - ] + ...(isHorizontallyResizable + ? getNodeDraggableHorizontalEdges(parent && isPageColumnChild ? parent : node) : []), + RECTANGLE_EDGE_BOTTOM as RectangleEdge, + ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), ]} - onEdgeDragStart={ - isHorizontallyResizable || isVerticallyResizable - ? handleEdgeDragStart(node) - : undefined - } + onEdgeDragStart={isSelected ? handleEdgeDragStart(node) : undefined} onDelete={handleNodeDelete(node.id)} isResizing={isResizingNode} resizePreviewElementRef={resizePreviewElementRef} diff --git a/packages/toolpad-app/src/toolpad/AppEditor/pageLayout.ts b/packages/toolpad-app/src/toolpad/AppEditor/pageLayout.ts index c48a27faeb2..5fc3e68c6dc 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/pageLayout.ts +++ b/packages/toolpad-app/src/toolpad/AppEditor/pageLayout.ts @@ -57,7 +57,6 @@ export function deleteOrphanedLayoutNodes( if ( lastContainerChild.parentProp && parentParent.parentIndex && - moveTargetNodeId !== parentParent.id && moveTargetNodeId !== lastContainerChild.id ) { if ( diff --git a/packages/toolpad-components/src/Chart.tsx b/packages/toolpad-components/src/Chart.tsx index 309545e7490..5bf435687c0 100644 --- a/packages/toolpad-components/src/Chart.tsx +++ b/packages/toolpad-components/src/Chart.tsx @@ -41,10 +41,9 @@ interface ChartProps extends BoxProps { data?: ChartData; loading?: boolean; error?: Error | string; - height?: number; } -function Chart({ data = [], loading, error, height, sx }: ChartProps) { +function Chart({ data = [], loading, error, sx }: ChartProps) { const xValues = React.useMemo( () => data @@ -94,8 +93,8 @@ function Chart({ data = [], loading, error, height, sx }: ChartProps) { const isDataVisible = !loading && !displayError; return ( - - + + {isDataVisible ? ( @@ -193,7 +192,7 @@ function Chart({ data = [], loading, error, height, sx }: ChartProps) { sx={{ position: 'absolute', inset: '0 0 0 0' }} variant="rectangular" width="100%" - height={height} + height="100%" /> ) : null} @@ -205,7 +204,8 @@ export default createBuiltin(Chart, { loadingProp: 'loading', loadingPropSource: ['data'], errorProp: 'error', - resizableHeightProp: 'height', + defaultLayoutHeight: 360, + minimumLayoutHeight: 100, argTypes: { data: { helperText: 'The data to be displayed.', @@ -241,12 +241,6 @@ export default createBuiltin(Chart, { }, control: { type: 'ChartData', bindable: false }, }, - height: { - helperText: 'The height of the chart.', - type: 'number', - default: 300, - minimum: 100, - }, sx: { helperText: SX_PROP_HELPER_TEXT, type: 'object', diff --git a/packages/toolpad-components/src/DataGrid.tsx b/packages/toolpad-components/src/DataGrid.tsx index 8dd954e3649..91a3c5db17c 100644 --- a/packages/toolpad-components/src/DataGrid.tsx +++ b/packages/toolpad-components/src/DataGrid.tsx @@ -464,7 +464,6 @@ interface ToolpadDataGridProps extends Omit - + @@ -762,7 +759,8 @@ export default createBuiltin(DataGridComponent, { errorProp: 'error', loadingPropSource: ['rows', 'columns'], loadingProp: 'loading', - resizableHeightProp: 'height', + defaultLayoutHeight: 360, + minimumLayoutHeight: 100, argTypes: { rowsSource: { helperText: 'Defines how rows are provided to the grid.', @@ -843,12 +841,6 @@ export default createBuiltin(DataGridComponent, { enum: ['compact', 'standard', 'comfortable'], default: 'compact', }, - height: { - helperText: 'The height of the data grid.', - type: 'number', - default: 350, - minimum: 100, - }, loading: { helperText: "Displays a loading animation indicating the data grid isn't ready to present data yet.", diff --git a/packages/toolpad-components/src/PageColumn.tsx b/packages/toolpad-components/src/PageColumn.tsx index 30b7dc1f357..03447a6f6c0 100644 --- a/packages/toolpad-components/src/PageColumn.tsx +++ b/packages/toolpad-components/src/PageColumn.tsx @@ -14,7 +14,7 @@ function PageColumn({ gap, children }: PageColumnProps) { gap, display: 'grid', gridAutoFlow: 'row', - gridAutoRows: 'fit-content', + gridAutoRows: 'min-content', gridAutoColumns: '100%', }} > diff --git a/packages/toolpad-components/src/Spacer.tsx b/packages/toolpad-components/src/Spacer.tsx index 466022ca233..cb541529eed 100644 --- a/packages/toolpad-components/src/Spacer.tsx +++ b/packages/toolpad-components/src/Spacer.tsx @@ -3,24 +3,15 @@ import { Box, BoxProps } from '@mui/material'; import createBuiltin from './createBuiltin'; import { SX_PROP_HELPER_TEXT } from './constants'; -interface SpacerProps extends BoxProps { - height: number; -} - -function Spacer(props: SpacerProps) { - return ; +function Spacer(props: BoxProps) { + return ; } export default createBuiltin(Spacer, { - helperText: 'Space component.\nIt allows for creating space between elements.', - resizableHeightProp: 'height', + helperText: 'Spacer component.\nIt allows for creating space between elements.', + defaultLayoutHeight: 40, + minimumLayoutHeight: 4, argTypes: { - height: { - helperText: 'The height of the spacer.', - type: 'number', - default: 160, - minimum: 4, - }, sx: { helperText: SX_PROP_HELPER_TEXT, type: 'object', diff --git a/packages/toolpad-core/src/types.ts b/packages/toolpad-core/src/types.ts index ca50b41990c..f18a7f85079 100644 --- a/packages/toolpad-core/src/types.ts +++ b/packages/toolpad-core/src/types.ts @@ -426,10 +426,13 @@ export interface ComponentConfig

> { */ layoutDirection?: 'vertical' | 'horizontal' | 'both'; /** - * Designates a property as "the resizable height property". If Toolpad detects any - * vertical resizing of the component it will forward it to this property. + * Initial height of the component container box. */ - resizableHeightProp?: keyof P & string; + defaultLayoutHeight?: number; + /** + * Minimum height that the component container box can be resized to. + */ + minimumLayoutHeight?: number; /** * Describes the individual properties for this component. */ From 6f0aaecd1a60e37a12064ce3ca390588f66d029e Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:55:56 +0000 Subject: [PATCH 10/38] Add snapshot tests for vertical resizing of elements --- test/models/ToolpadEditor.ts | 7 +- test/utils/clickCenter.ts | 11 +--- test/utils/waitForBoundingBox.ts | 15 +++++ .../fixture/toolpad/pages/grids/page.yml | 43 ++++++++++++ .../fixture/toolpad/pages/rows/page.yml | 12 +--- test/visual/components/index.spec.ts | 65 +++++++++++++++++++ 6 files changed, 130 insertions(+), 23 deletions(-) create mode 100644 test/utils/waitForBoundingBox.ts create mode 100644 test/visual/components/fixture/toolpad/pages/grids/page.yml diff --git a/test/models/ToolpadEditor.ts b/test/models/ToolpadEditor.ts index ca583607107..456e28bb71f 100644 --- a/test/models/ToolpadEditor.ts +++ b/test/models/ToolpadEditor.ts @@ -1,6 +1,7 @@ import { setTimeout } from 'timers/promises'; import { expect, FrameLocator, Locator, Page } from '@playwright/test'; import { gotoIfNotCurrent } from './shared'; +import waitForBoundingBox from '../utils/waitForBoundingBox'; class CreateComponentDialog { readonly page: Page; @@ -137,11 +138,7 @@ export class ToolpadEditor { await this.componentCatalog.hover(); - let pageRootBoundingBox; - await expect(async () => { - pageRootBoundingBox = await this.pageRoot.boundingBox(); - expect(pageRootBoundingBox).toBeTruthy(); - }).toPass(); + const pageRootBoundingBox = await waitForBoundingBox(this.pageRoot); if (!moveTargetX) { moveTargetX = pageRootBoundingBox!.x + pageRootBoundingBox!.width / 2; diff --git a/test/utils/clickCenter.ts b/test/utils/clickCenter.ts index 5716bb9415f..af3c7c1c981 100644 --- a/test/utils/clickCenter.ts +++ b/test/utils/clickCenter.ts @@ -1,13 +1,8 @@ -import { Page, Locator, expect } from '@playwright/test'; +import { Page, Locator } from '@playwright/test'; +import waitForBoundingBox from './waitForBoundingBox'; export default async function clickCenter(page: Page, targetLocator: Locator) { - let targetBoundingBox; - await expect(async () => { - targetBoundingBox = await targetLocator.boundingBox(); - expect(targetBoundingBox).toBeTruthy(); - expect(targetBoundingBox!.width).toBeGreaterThan(0); - expect(targetBoundingBox!.height).toBeGreaterThan(0); - }).toPass(); + const targetBoundingBox = await waitForBoundingBox(targetLocator); await page.mouse.click( targetBoundingBox!.x + targetBoundingBox!.width / 2, diff --git a/test/utils/waitForBoundingBox.ts b/test/utils/waitForBoundingBox.ts new file mode 100644 index 00000000000..26fc6bb6ce5 --- /dev/null +++ b/test/utils/waitForBoundingBox.ts @@ -0,0 +1,15 @@ +import { Locator, expect } from '@playwright/test'; + +export default async function waitForBoundingBox( + locator: Locator, +): Promise> { + let boundingBox; + await expect(async () => { + boundingBox = await locator.boundingBox(); + expect(boundingBox).toBeTruthy(); + expect(boundingBox!.width).toBeGreaterThan(0); + expect(boundingBox!.height).toBeGreaterThan(0); + }).toPass(); + + return boundingBox!; +} diff --git a/test/visual/components/fixture/toolpad/pages/grids/page.yml b/test/visual/components/fixture/toolpad/pages/grids/page.yml new file mode 100644 index 00000000000..4f0ab597f47 --- /dev/null +++ b/test/visual/components/fixture/toolpad/pages/grids/page.yml @@ -0,0 +1,43 @@ +apiVersion: v1 +kind: page +spec: + id: Dh9u36B + title: grids + display: shell + content: + - component: PageRow + name: pageRow + props: + justifyContent: start + children: + - component: PageColumn + name: pageColumn + layout: + columnSize: 1 + children: + - component: DataGrid + name: dataGrid + layout: + columnSize: 1 + props: + rows: + - id: one + columns: + - field: id + type: string + - component: DataGrid + name: dataGrid2 + props: + rows: + - id: two + columns: + - field: id + type: string + - component: DataGrid + name: dataGrid1 + props: + rows: + - id: three + columns: + - field: id + type: string diff --git a/test/visual/components/fixture/toolpad/pages/rows/page.yml b/test/visual/components/fixture/toolpad/pages/rows/page.yml index afe70d59f26..fa6cb1e2196 100644 --- a/test/visual/components/fixture/toolpad/pages/rows/page.yml +++ b/test/visual/components/fixture/toolpad/pages/rows/page.yml @@ -9,16 +9,8 @@ spec: name: pageRow1 children: [ - { - component: TextField, - name: textField, - props: { fullWidth: true } - }, - { - component: TextField, - name: textField1, - props: { fullWidth: true } - } + { component: TextField, name: textField, props: { fullWidth: true } }, + { component: TextField, name: textField1, props: { fullWidth: true } }, ] props: justifyContent: start diff --git a/test/visual/components/index.spec.ts b/test/visual/components/index.spec.ts index dcbc3648b27..6f1adb670c6 100644 --- a/test/visual/components/index.spec.ts +++ b/test/visual/components/index.spec.ts @@ -4,6 +4,7 @@ import { ToolpadEditor } from '../../models/ToolpadEditor'; import { ToolpadRuntime } from '../../models/ToolpadRuntime'; import { test } from '../../playwright/localTest'; import clickCenter from '../../utils/clickCenter'; +import waitForBoundingBox from '../../utils/waitForBoundingBox'; const currentDirectory = url.fileURLToPath(new URL('.', import.meta.url)); @@ -71,6 +72,70 @@ test('showing grid while resizing elements', async ({ page, argosScreenshot }) = await argosScreenshot('resize-grid'); }); +test('resizing element heights', async ({ page, argosScreenshot }) => { + const editorModel = new ToolpadEditor(page); + await editorModel.goToPageById('Dh9u36B'); + + await editorModel.waitForOverlay(); + + const appCanvasBoundingBox = await editorModel.appCanvas.locator('body').boundingBox(); + + const screenshotConfig = { + clip: appCanvasBoundingBox || undefined, + }; + + const firstGrid = editorModel.appCanvas.getByRole('grid').nth(0); + + await clickCenter(page, firstGrid); + await argosScreenshot('vertical-resize-before', screenshotConfig); + + const firstGridBoundingBox = await waitForBoundingBox(firstGrid); + + await page.mouse.move( + firstGridBoundingBox!.x + firstGridBoundingBox!.width / 2, + firstGridBoundingBox!.y + firstGridBoundingBox!.height - 4, + { steps: 10 }, + ); + + await page.mouse.down(); + + await page.mouse.move( + firstGridBoundingBox!.x + firstGridBoundingBox!.width / 2, + firstGridBoundingBox!.y + firstGridBoundingBox!.height + 100, + { steps: 10 }, + ); + + await page.mouse.up(); + + const thirdGrid = editorModel.appCanvas.getByRole('grid').nth(2); + + await clickCenter(page, thirdGrid); + + const thirdGridBoundingBox = await waitForBoundingBox(thirdGrid); + + await page.mouse.move( + thirdGridBoundingBox!.x + thirdGridBoundingBox!.width / 2, + thirdGridBoundingBox!.y + thirdGridBoundingBox!.height - 4, + { steps: 10 }, + ); + + await page.mouse.down(); + + await page.mouse.move( + thirdGridBoundingBox!.x + thirdGridBoundingBox!.width / 2, + thirdGridBoundingBox!.y + thirdGridBoundingBox!.height + 100, + { steps: 10 }, + ); + + await page.mouse.up(); + + // Wait for resizing to happen + await waitForBoundingBox(thirdGrid); + + await clickCenter(page, firstGrid); + await argosScreenshot('vertical-resize-after', screenshotConfig); +}); + test('showing drag-and-drop previews', async ({ page, argosScreenshot }) => { const editorModel = new ToolpadEditor(page); await editorModel.goToPageById('8ixPqyI'); From 007c3117d2af4cf95d97c1436df81e1c84143618 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 2 Nov 2023 15:26:57 +0000 Subject: [PATCH 11/38] Improve Spacer component height --- packages/toolpad-components/src/Spacer.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/toolpad-components/src/Spacer.tsx b/packages/toolpad-components/src/Spacer.tsx index cb541529eed..05970165736 100644 --- a/packages/toolpad-components/src/Spacer.tsx +++ b/packages/toolpad-components/src/Spacer.tsx @@ -3,14 +3,15 @@ import { Box, BoxProps } from '@mui/material'; import createBuiltin from './createBuiltin'; import { SX_PROP_HELPER_TEXT } from './constants'; +const SPACER_MINIMUM_HEIGHT = 20; // pixels + function Spacer(props: BoxProps) { - return ; + return ; } export default createBuiltin(Spacer, { helperText: 'Spacer component.\nIt allows for creating space between elements.', - defaultLayoutHeight: 40, - minimumLayoutHeight: 4, + minimumLayoutHeight: SPACER_MINIMUM_HEIGHT, argTypes: { sx: { helperText: SX_PROP_HELPER_TEXT, From 5e25447a4036c24f1e4e161404b2b85bc83e1ed7 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 2 Nov 2023 16:24:34 +0000 Subject: [PATCH 12/38] Fix highlight in slots --- .../PageEditor/RenderPanel/NodeDropArea.tsx | 21 ++++++++++--------- .../PageEditor/RenderPanel/RenderOverlay.tsx | 10 +++++++-- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeDropArea.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeDropArea.tsx index 1d710582b17..c4def79390d 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeDropArea.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeDropArea.tsx @@ -177,6 +177,8 @@ export default function NodeDropArea({ const isPageNode = appDom.isPage(node); const isPageChild = dropAreaNodeParent ? appDom.isPage(dropAreaNodeParent) : false; + const isPageRowNode = appDom.isElement(node) && isPageRow(node); + const isPageChildElement = isPageChild && appDom.isElement(node) && !isPageRow(node); const isPageRowChild = dropAreaNodeParent ? appDom.isElement(dropAreaNodeParent) && isPageRow(dropAreaNodeParent) @@ -242,7 +244,7 @@ export default function NodeDropArea({ } // Is dragging over left, is page row and child of the page - if (dropAreaNodeParent && appDom.isElement(node) && isPageRow(node) && isPageChild) { + if (dropAreaNodeParent && isPageRowNode && isPageChild) { return null; } } @@ -252,13 +254,11 @@ export default function NodeDropArea({ if ( dropAreaNodeParent && dropAreaNodeParent.id === dragOverNodeId && - pageAwareParentProp === dragOverSlotParentProp && - !parentProp + (pageAwareParentProp === dragOverSlotParentProp || !parentProp) ) { const parentLastChild = - pageAwareParentProp && - (appDom.isPage(dropAreaNodeParent) || appDom.isElement(dropAreaNodeParent)) - ? appDom.getNodeLastChild(dom, dropAreaNodeParent, pageAwareParentProp) + appDom.isPage(dropAreaNodeParent) || appDom.isElement(dropAreaNodeParent) + ? appDom.getNodeLastChild(dom, dropAreaNodeParent, pageAwareParentProp || 'children') : null; const isParentLastChild = parentLastChild ? node.id === parentLastChild.id : false; @@ -266,7 +266,7 @@ export default function NodeDropArea({ const parentSlots = dropAreaNodeParentInfo?.slots || null; const parentFlowDirection = - parentSlots && pageAwareParentProp && parentSlots[pageAwareParentProp]?.flowDirection; + parentSlots && parentSlots[pageAwareParentProp || 'children']?.flowDirection; return parentFlowDirection && isParentLastChild ? getChildNodeHighlightedZone(parentFlowDirection) @@ -298,18 +298,19 @@ export default function NodeDropArea({ ? dragOverZone : null; }, [ - dropAreaNodeParent, - dom, dragOverZone, availableDropZones, isPageNode, parentProp, isEmptySlot, + dropAreaNodeParent, + dom, + isPageChild, node, dragOverNodeId, dragOverSlotParentProp, isPageRowChild, - isPageChild, + isPageRowNode, dropAreaNodeParentInfo?.slots, dropAreaNodeChildNodes, ]); diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 5022cd01b94..7287b26da40 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1458,6 +1458,8 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isHovered = hoveredNodeId === node.id; const isHorizontallyResizable = isPageRowChild || isPageColumnChild; + const isVerticallyResizable = + appDom.isElement(node) && !isPageRow(node) && !isPageColumn(node); const isResizing = Boolean(draggedEdge); const isResizingNode = isResizing && node.id === draggedNodeId; @@ -1483,8 +1485,12 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { ...(isHorizontallyResizable ? getNodeDraggableHorizontalEdges(parent && isPageColumnChild ? parent : node) : []), - RECTANGLE_EDGE_BOTTOM as RectangleEdge, - ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), + ...(isVerticallyResizable + ? [ + RECTANGLE_EDGE_BOTTOM as RectangleEdge, + ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), + ] + : []), ]} onEdgeDragStart={isSelected ? handleEdgeDragStart(node) : undefined} onDelete={handleNodeDelete(node.id)} From fa07e97d0b3226d83fee4526571ae985f57bb668 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 2 Nov 2023 16:39:22 +0000 Subject: [PATCH 13/38] Update schemas --- docs/schemas/v1/definitions.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/schemas/v1/definitions.json b/docs/schemas/v1/definitions.json index ccc9b284380..dea0462f5ad 100644 --- a/docs/schemas/v1/definitions.json +++ b/docs/schemas/v1/definitions.json @@ -570,6 +570,10 @@ "columnSize": { "type": "number", "description": "The width this element takes up, expressed in terms of columns on the page." + }, + "height": { + "type": "number", + "description": "The height this element takes up, in pixels." } }, "additionalProperties": false, From 0471351df51de3d8898dbe98b4b3d54a0c5fbc7b Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 2 Nov 2023 16:44:17 +0000 Subject: [PATCH 14/38] Fix Chart component height --- packages/toolpad-components/src/Chart.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/toolpad-components/src/Chart.tsx b/packages/toolpad-components/src/Chart.tsx index 4aad3e3632f..e4cbb6022c7 100644 --- a/packages/toolpad-components/src/Chart.tsx +++ b/packages/toolpad-components/src/Chart.tsx @@ -184,7 +184,6 @@ function Chart({ data = [], loading, error, sx }: ChartProps) { {isDataVisible ? ( Date: Thu, 2 Nov 2023 16:49:55 +0000 Subject: [PATCH 15/38] Update docs --- docs/data/toolpad/reference/components/chart.md | 9 ++++----- .../data/toolpad/reference/components/data-grid.md | 1 - .../toolpad/reference/components/manifest.json | 4 ++++ docs/data/toolpad/reference/components/spacer.md | 14 ++++++++++++++ docs/pages/toolpad/reference/components/spacer.js | 9 +++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 docs/data/toolpad/reference/components/spacer.md create mode 100644 docs/pages/toolpad/reference/components/spacer.js diff --git a/docs/data/toolpad/reference/components/chart.md b/docs/data/toolpad/reference/components/chart.md index 65e269ebf69..b4e9465312b 100644 --- a/docs/data/toolpad/reference/components/chart.md +++ b/docs/data/toolpad/reference/components/chart.md @@ -8,8 +8,7 @@ A chart component. ## Properties -| Name | Type | Default | Description | -| :------------------------------------ | :------------------------------------ | :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| data | array | | The data to be displayed. | -| height | number | 300 | The height of the chart. | -| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | +| Name | Type | Default | Description | +| :---------------------------------- | :------------------------------------ | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| data | array | | The data to be displayed. | +| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | diff --git a/docs/data/toolpad/reference/components/data-grid.md b/docs/data/toolpad/reference/components/data-grid.md index 7affa9a7032..8dc132419d6 100644 --- a/docs/data/toolpad/reference/components/data-grid.md +++ b/docs/data/toolpad/reference/components/data-grid.md @@ -19,7 +19,6 @@ The datagrid lets users display tabular data in a flexible grid. | rowIdField | string | | Defines which column contains the [id](https://mui.com/x/react-data-grid/row-definition/#row-identifier) that uniquely identifies each row. | | selection | object | null | The currently selected row. Or `null` in case no row has been selected. | | density | string | "compact" | The [density](https://mui.com/x/react-data-grid/accessibility/#density-prop) of the rows. Possible values are `compact`, `standard`, or `comfortable`. | -| height | number | 350 | The height of the data grid. | | loading | boolean | | Displays a loading animation indicating the data grid isn't ready to present data yet. | | hideToolbar | boolean | | Hide the toolbar area that contains the data grid user controls. | | sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | diff --git a/docs/data/toolpad/reference/components/manifest.json b/docs/data/toolpad/reference/components/manifest.json index 6a48d487c20..0f6cd8f4343 100644 --- a/docs/data/toolpad/reference/components/manifest.json +++ b/docs/data/toolpad/reference/components/manifest.json @@ -73,6 +73,10 @@ "title": "Select", "pathname": "/toolpad/reference/components/select" }, + { + "title": "Spacer", + "pathname": "/toolpad/reference/components/spacer" + }, { "title": "Stack", "pathname": "/toolpad/reference/components/stack" diff --git a/docs/data/toolpad/reference/components/spacer.md b/docs/data/toolpad/reference/components/spacer.md new file mode 100644 index 00000000000..1dffb2cab4c --- /dev/null +++ b/docs/data/toolpad/reference/components/spacer.md @@ -0,0 +1,14 @@ + + +# Spacer + +

API docs for the Toolpad Spacer component.

+ +Spacer component. +It allows for creating space between elements. + +## Properties + +| Name | Type | Default | Description | +| :-------------------------------- | :------------------------------------ | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | diff --git a/docs/pages/toolpad/reference/components/spacer.js b/docs/pages/toolpad/reference/components/spacer.js new file mode 100644 index 00000000000..665ecc093b0 --- /dev/null +++ b/docs/pages/toolpad/reference/components/spacer.js @@ -0,0 +1,9 @@ +/* This file has been auto-generated using `yarn docs:build:api`. */ + +import * as React from 'react'; +import MarkdownDocs from '@mui/monorepo/docs/src/modules/components/MarkdownDocs'; +import * as pageProps from '../../../../data/toolpad/reference/components/spacer.md?@mui/markdown'; + +export default function Page() { + return ; +} From 9cbe2989d8da696e7337d1ec994d8f8a1a89fd22 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:32:25 +0000 Subject: [PATCH 16/38] Continue merge, seeing if I can still turn this PR into something useful --- packages/toolpad-components/src/DataGrid.tsx | 2 +- test/visual/components/index.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/toolpad-components/src/DataGrid.tsx b/packages/toolpad-components/src/DataGrid.tsx index cae61dd3812..ea87f55ed33 100644 --- a/packages/toolpad-components/src/DataGrid.tsx +++ b/packages/toolpad-components/src/DataGrid.tsx @@ -1273,7 +1273,7 @@ const DataGridComponent = React.forwardRef(function DataGridComponent( {...dataProviderProps} sx={{ height: '100%', - visibility: error ? 'hidden' : 'visible', + visibility: errorProp ? 'hidden' : 'visible', }} /> diff --git a/test/visual/components/index.spec.ts b/test/visual/components/index.spec.ts index f63b99aba36..a246943669b 100644 --- a/test/visual/components/index.spec.ts +++ b/test/visual/components/index.spec.ts @@ -114,7 +114,7 @@ test('showing grid while resizing elements', async ({ page, argosScreenshot }) = test('resizing element heights', async ({ page, argosScreenshot }) => { const editorModel = new ToolpadEditor(page); - await editorModel.goToPageById('Dh9u36B'); + await editorModel.goToPage('grids'); await editorModel.waitForOverlay(); From 189a104b5cc40370fd67a72394a1a93d5bd38a87 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:24:35 +0000 Subject: [PATCH 17/38] More merge fixes --- test/models/ToolpadEditor.ts | 2 +- test/utils/clickCenter.ts | 11 ----------- test/visual/components/index.spec.ts | 6 +----- 3 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 test/utils/clickCenter.ts diff --git a/test/models/ToolpadEditor.ts b/test/models/ToolpadEditor.ts index a312b4411b1..abadb6ce08b 100644 --- a/test/models/ToolpadEditor.ts +++ b/test/models/ToolpadEditor.ts @@ -1,7 +1,7 @@ import { setTimeout } from 'timers/promises'; import { expect, FrameLocator, Locator, Page } from '@playwright/test'; import { gotoIfNotCurrent } from './shared'; -import waitForBoundingBox from '../utils/waitForBoundingBox'; +import { waitForBoundingBox } from '../utils/locators'; class CreateComponentDialog { readonly page: Page; diff --git a/test/utils/clickCenter.ts b/test/utils/clickCenter.ts deleted file mode 100644 index af3c7c1c981..00000000000 --- a/test/utils/clickCenter.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Page, Locator } from '@playwright/test'; -import waitForBoundingBox from './waitForBoundingBox'; - -export default async function clickCenter(page: Page, targetLocator: Locator) { - const targetBoundingBox = await waitForBoundingBox(targetLocator); - - await page.mouse.click( - targetBoundingBox!.x + targetBoundingBox!.width / 2, - targetBoundingBox!.y + targetBoundingBox!.height / 2, - ); -} diff --git a/test/visual/components/index.spec.ts b/test/visual/components/index.spec.ts index a246943669b..1074d81e463 100644 --- a/test/visual/components/index.spec.ts +++ b/test/visual/components/index.spec.ts @@ -3,8 +3,7 @@ import * as url from 'url'; import { ToolpadEditor } from '../../models/ToolpadEditor'; import { ToolpadRuntime } from '../../models/ToolpadRuntime'; import { test } from '../../playwright/localTest'; -import { clickCenter } from '../../utils/locators'; -import waitForBoundingBox from '../../utils/waitForBoundingBox'; +import { clickCenter, waitForBoundingBox } from '../../utils/locators'; const currentDirectory = url.fileURLToPath(new URL('.', import.meta.url)); @@ -169,9 +168,6 @@ test('resizing element heights', async ({ page, argosScreenshot }) => { await page.mouse.up(); - // Wait for resizing to happen - await waitForBoundingBox(thirdGrid); - await clickCenter(page, firstGrid); await argosScreenshot('vertical-resize-after', screenshotConfig); }); From 0e06cc09e42533b8bbd35ab10a740de7f9283089 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:32:45 +0000 Subject: [PATCH 18/38] Make elements always fill column space --- packages/toolpad-app/src/runtime/ToolpadApp.tsx | 2 +- packages/toolpad-components/src/PageColumn.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/toolpad-app/src/runtime/ToolpadApp.tsx b/packages/toolpad-app/src/runtime/ToolpadApp.tsx index a1d7b78bf1e..16b6b2a1b8b 100644 --- a/packages/toolpad-app/src/runtime/ToolpadApp.tsx +++ b/packages/toolpad-app/src/runtime/ToolpadApp.tsx @@ -1193,7 +1193,7 @@ function RenderedNodeContent({ node, childNodeGroups, Component }: RenderedNodeC display: 'flex', alignItems: boundLayoutProps.verticalAlign, justifyContent: boundLayoutProps.horizontalAlign, - height: node.layout?.height ?? componentConfig.defaultLayoutHeight, + minHeight: node.layout?.height ?? componentConfig.defaultLayoutHeight, }} ref={nodeRef} data-toolpad-node-id={nodeId} diff --git a/packages/toolpad-components/src/PageColumn.tsx b/packages/toolpad-components/src/PageColumn.tsx index 42ae8fe53c9..db214598292 100644 --- a/packages/toolpad-components/src/PageColumn.tsx +++ b/packages/toolpad-components/src/PageColumn.tsx @@ -18,7 +18,7 @@ const PageColumn = React.forwardRef(function PageColumn( gap, display: 'grid', gridAutoFlow: 'row', - gridAutoRows: 'min-content', + gridAutoRows: 'fit-content', gridAutoColumns: '100%', }} {...props} From afb84ae1bbc7f8bf1c00357d0c537bb1947549a8 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:12:45 +0000 Subject: [PATCH 19/38] More adjustments --- packages/toolpad-app/src/runtime/ToolpadApp.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/toolpad-app/src/runtime/ToolpadApp.tsx b/packages/toolpad-app/src/runtime/ToolpadApp.tsx index 16b6b2a1b8b..0c172e21a38 100644 --- a/packages/toolpad-app/src/runtime/ToolpadApp.tsx +++ b/packages/toolpad-app/src/runtime/ToolpadApp.tsx @@ -1193,7 +1193,8 @@ function RenderedNodeContent({ node, childNodeGroups, Component }: RenderedNodeC display: 'flex', alignItems: boundLayoutProps.verticalAlign, justifyContent: boundLayoutProps.horizontalAlign, - minHeight: node.layout?.height ?? componentConfig.defaultLayoutHeight, + height: node.layout?.height ?? componentConfig.defaultLayoutHeight, + minHeight: '100%', }} ref={nodeRef} data-toolpad-node-id={nodeId} From 3980eae1d5b5c19301a921f48874dc8dfbe1c035 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:20:39 +0000 Subject: [PATCH 20/38] Regenerate docs --- docs/data/toolpad/reference/components/chart.md | 9 ++++----- docs/data/toolpad/reference/components/spacer.md | 4 ++-- docs/pages/toolpad/reference/components/spacer.js | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/data/toolpad/reference/components/chart.md b/docs/data/toolpad/reference/components/chart.md index 1b3f52b15e0..1a071050abd 100644 --- a/docs/data/toolpad/reference/components/chart.md +++ b/docs/data/toolpad/reference/components/chart.md @@ -8,8 +8,7 @@ A chart component. ## Properties -| Name | Type | Default | Description | -| :------------------------------------ | :------------------------------------ | :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| data | array | | The data to be displayed. | -| height | number | 300 | The height of the chart. | -| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | +| Name | Type | Default | Description | +| :---------------------------------- | :------------------------------------ | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| data | array | | The data to be displayed. | +| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | diff --git a/docs/data/toolpad/reference/components/spacer.md b/docs/data/toolpad/reference/components/spacer.md index 1dffb2cab4c..7e9572506ac 100644 --- a/docs/data/toolpad/reference/components/spacer.md +++ b/docs/data/toolpad/reference/components/spacer.md @@ -1,4 +1,4 @@ - + # Spacer @@ -11,4 +11,4 @@ It allows for creating space between elements. | Name | Type | Default | Description | | :-------------------------------- | :------------------------------------ | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | +| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | diff --git a/docs/pages/toolpad/reference/components/spacer.js b/docs/pages/toolpad/reference/components/spacer.js index 665ecc093b0..bfad331aa56 100644 --- a/docs/pages/toolpad/reference/components/spacer.js +++ b/docs/pages/toolpad/reference/components/spacer.js @@ -1,4 +1,4 @@ -/* This file has been auto-generated using `yarn docs:build:api`. */ +/* ATTENTION: DO NOT EDIT! This file has been auto-generated using `pnpm docs:build:api`. */ import * as React from 'react'; import MarkdownDocs from '@mui/monorepo/docs/src/modules/components/MarkdownDocs'; From af6a74f8686c2c57787ca87b73cfc95aceae87f2 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:55:38 +0000 Subject: [PATCH 21/38] Block invalid top resize --- .../PageEditor/RenderPanel/RenderOverlay.tsx | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 357ba62d058..84920bd2f26 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1378,15 +1378,23 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { } if (draggedEdge === RECTANGLE_EDGE_BOTTOM || draggedEdge === RECTANGLE_EDGE_TOP) { - draft = appDom.setNodeNamespacedProp( - draft, - draggedNode, - 'layout', - 'height', - resizePreviewRect.height, - ); + const isValidTopResize = + draggedEdge === RECTANGLE_EDGE_TOP && + previousSibling && + previousSiblingRect && + !isPageRow(previousSibling); + + if (draggedEdge === RECTANGLE_EDGE_BOTTOM || isValidTopResize) { + draft = appDom.setNodeNamespacedProp( + draft, + draggedNode, + 'layout', + 'height', + resizePreviewRect.height, + ); + } - if (draggedEdge === RECTANGLE_EDGE_TOP && previousSibling && previousSiblingRect) { + if (isValidTopResize && previousSiblingRect) { draft = appDom.setNodeNamespacedProp( draft, previousSibling, From 7523bb7a4bae2b8177fc1c1f4348286eaa0b08a3 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:02:26 +0000 Subject: [PATCH 22/38] Disable resizing from top for now, it's still not good enough --- .../PageEditor/RenderPanel/RenderOverlay.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 84920bd2f26..25c7de9465d 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1453,11 +1453,12 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isPageRowChild = parent ? appDom.isElement(parent) && isPageRow(parent) : false; const isPageColumnChild = parent ? appDom.isElement(parent) && isPageColumn(parent) : false; - const nodeParentProp = node.parentProp; - const isFirstChild = - parent && appDom.isElement(parent) && nodeParentProp - ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id - : false; + // @TODO: Improve solution for resizing from top, it's still not a great UX + // const nodeParentProp = node.parentProp; + // const isFirstChild = + // parent && appDom.isElement(parent) && nodeParentProp + // ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id + // : false; const isSelected = selectedNode && !newNode ? selectedNode.id === node.id : false; const isHovered = hoveredNodeId === node.id; @@ -1493,7 +1494,8 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { ...(isVerticallyResizable ? [ RECTANGLE_EDGE_BOTTOM as RectangleEdge, - ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), + // @TODO: Improve solution for resizing from top, it's still not a great UX + // ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), ] : []), ]} From 9e967deb2293b6353123391d5d3ec3d5d545994c Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Mon, 19 Feb 2024 19:09:39 +0000 Subject: [PATCH 23/38] Nevermind UX is bad anyway in some cases --- .../PageEditor/RenderPanel/RenderOverlay.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 25c7de9465d..84920bd2f26 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1453,12 +1453,11 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isPageRowChild = parent ? appDom.isElement(parent) && isPageRow(parent) : false; const isPageColumnChild = parent ? appDom.isElement(parent) && isPageColumn(parent) : false; - // @TODO: Improve solution for resizing from top, it's still not a great UX - // const nodeParentProp = node.parentProp; - // const isFirstChild = - // parent && appDom.isElement(parent) && nodeParentProp - // ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id - // : false; + const nodeParentProp = node.parentProp; + const isFirstChild = + parent && appDom.isElement(parent) && nodeParentProp + ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id + : false; const isSelected = selectedNode && !newNode ? selectedNode.id === node.id : false; const isHovered = hoveredNodeId === node.id; @@ -1494,8 +1493,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { ...(isVerticallyResizable ? [ RECTANGLE_EDGE_BOTTOM as RectangleEdge, - // @TODO: Improve solution for resizing from top, it's still not a great UX - // ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), + ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), ] : []), ]} From 8608ab4829c6c44446a0e46d605c4b301bfb71e4 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:46:00 +0000 Subject: [PATCH 24/38] Revert "Nevermind UX is bad anyway in some cases" This reverts commit 9e967deb2293b6353123391d5d3ec3d5d545994c. --- .../PageEditor/RenderPanel/RenderOverlay.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 84920bd2f26..25c7de9465d 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1453,11 +1453,12 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isPageRowChild = parent ? appDom.isElement(parent) && isPageRow(parent) : false; const isPageColumnChild = parent ? appDom.isElement(parent) && isPageColumn(parent) : false; - const nodeParentProp = node.parentProp; - const isFirstChild = - parent && appDom.isElement(parent) && nodeParentProp - ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id - : false; + // @TODO: Improve solution for resizing from top, it's still not a great UX + // const nodeParentProp = node.parentProp; + // const isFirstChild = + // parent && appDom.isElement(parent) && nodeParentProp + // ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id + // : false; const isSelected = selectedNode && !newNode ? selectedNode.id === node.id : false; const isHovered = hoveredNodeId === node.id; @@ -1493,7 +1494,8 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { ...(isVerticallyResizable ? [ RECTANGLE_EDGE_BOTTOM as RectangleEdge, - ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), + // @TODO: Improve solution for resizing from top, it's still not a great UX + // ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), ] : []), ]} From 0efe12b5b4f60ee241dc61eabd947b8bca8d1cd6 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:27:31 +0000 Subject: [PATCH 25/38] Fix spread method --- .../PageEditor/RenderPanel/RenderOverlay.tsx | 25 ++++++++++++------- packages/toolpad-core/src/appDom.ts | 7 ++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 25c7de9465d..78796da8030 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -24,6 +24,7 @@ import { PAGE_COLUMN_COMPONENT_ID, isFormComponent, FORM_COMPONENT_ID, + getElementNodeComponentId, } from '../../../../runtime/toolpadComponents'; import { getRectanglePointActiveEdge, @@ -1449,23 +1450,30 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const parent = appDom.getParent(dom, node); const isPageNode = appDom.isPage(node); + const isElementNode = appDom.isElement(node); const isPageRowChild = parent ? appDom.isElement(parent) && isPageRow(parent) : false; const isPageColumnChild = parent ? appDom.isElement(parent) && isPageColumn(parent) : false; - // @TODO: Improve solution for resizing from top, it's still not a great UX - // const nodeParentProp = node.parentProp; - // const isFirstChild = - // parent && appDom.isElement(parent) && nodeParentProp - // ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id - // : false; + const nodeParentProp = node.parentProp; + const isFirstChild = + parent && appDom.isElement(parent) && nodeParentProp + ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id + : false; const isSelected = selectedNode && !newNode ? selectedNode.id === node.id : false; const isHovered = hoveredNodeId === node.id; const isHorizontallyResizable = isPageRowChild || isPageColumnChild; + + const nodeComponentId = isElementNode ? getElementNodeComponentId(node) : null; + + // @TODO: Enable vertical resizing for all component types when there is a better solution for adjusting size of other elements in same row const isVerticallyResizable = - appDom.isElement(node) && !isPageRow(node) && !isPageColumn(node); + isElementNode && + !isPageRow(node) && + !isPageColumn(node) && + (nodeComponentId === 'Chart' || nodeComponentId === 'DataGrid'); const isResizing = Boolean(draggedEdge); const isResizingNode = isResizing && node.id === draggedNodeId; @@ -1494,8 +1502,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { ...(isVerticallyResizable ? [ RECTANGLE_EDGE_BOTTOM as RectangleEdge, - // @TODO: Improve solution for resizing from top, it's still not a great UX - // ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), + ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), ] : []), ]} diff --git a/packages/toolpad-core/src/appDom.ts b/packages/toolpad-core/src/appDom.ts index 8de852e8f04..7164bac1a45 100644 --- a/packages/toolpad-core/src/appDom.ts +++ b/packages/toolpad-core/src/appDom.ts @@ -6,6 +6,7 @@ import { guessTitle, pascalCase, removeDiacritics, uncapitalize } from '@mui/too import { mapProperties, mapValues, hasOwnProperty } from '@mui/toolpad-utils/collections'; import { ExactEntriesOf, Maybe } from '@mui/toolpad-utils/types'; import { omit, update, updateOrCreate } from '@mui/toolpad-utils/immutability'; +import { get } from 'node:http'; import type { NodeId, NodeReference, @@ -829,8 +830,10 @@ export function spreadNode(dom: AppDom, node: Child) { let draft = dom; if (parent && parentProp && isElement(node)) { - for (const child of getDescendants(draft, node)) { - draft = setNodeParent(draft, child, parent.id, parentProp); + for (const child of getChildNodes(draft, node).children) { + const parentIndex = getNewParentIndexBeforeNode(draft, node, parentProp); + + draft = setNodeParent(draft, child, parent.id, parentProp, parentIndex); } draft = removeNode(draft, node.id); } From 64ce555abddd1b5bf845f2e3ae23d824ddda2a35 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:33:57 +0000 Subject: [PATCH 26/38] Re-add todos, this would take too much time --- .../PageEditor/RenderPanel/RenderOverlay.tsx | 16 +++++++++------- packages/toolpad-core/src/appDom.ts | 1 - 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 78796da8030..7390849b1ed 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1455,11 +1455,12 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const isPageRowChild = parent ? appDom.isElement(parent) && isPageRow(parent) : false; const isPageColumnChild = parent ? appDom.isElement(parent) && isPageColumn(parent) : false; - const nodeParentProp = node.parentProp; - const isFirstChild = - parent && appDom.isElement(parent) && nodeParentProp - ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id - : false; + // @TODO: Improve solution for resizing from top, it's still not a great UX + // const nodeParentProp = node.parentProp; + // const isFirstChild = + // parent && appDom.isElement(parent) && nodeParentProp + // ? appDom.getNodeFirstChild(dom, parent, nodeParentProp)?.id === node.id + // : false; const isSelected = selectedNode && !newNode ? selectedNode.id === node.id : false; const isHovered = hoveredNodeId === node.id; @@ -1468,7 +1469,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { const nodeComponentId = isElementNode ? getElementNodeComponentId(node) : null; - // @TODO: Enable vertical resizing for all component types when there is a better solution for adjusting size of other elements in same row + // @TODO: Enable vertical resizing for all component types when there is a better solution for adjusting size of other elements in same row after resizing const isVerticallyResizable = isElementNode && !isPageRow(node) && @@ -1502,7 +1503,8 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { ...(isVerticallyResizable ? [ RECTANGLE_EDGE_BOTTOM as RectangleEdge, - ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), + // @TODO: Improve solution for resizing from top, it's still not a great UX + // ...(!isFirstChild ? [RECTANGLE_EDGE_TOP as RectangleEdge] : []), ] : []), ]} diff --git a/packages/toolpad-core/src/appDom.ts b/packages/toolpad-core/src/appDom.ts index 7164bac1a45..58d34dbc247 100644 --- a/packages/toolpad-core/src/appDom.ts +++ b/packages/toolpad-core/src/appDom.ts @@ -6,7 +6,6 @@ import { guessTitle, pascalCase, removeDiacritics, uncapitalize } from '@mui/too import { mapProperties, mapValues, hasOwnProperty } from '@mui/toolpad-utils/collections'; import { ExactEntriesOf, Maybe } from '@mui/toolpad-utils/types'; import { omit, update, updateOrCreate } from '@mui/toolpad-utils/immutability'; -import { get } from 'node:http'; import type { NodeId, NodeReference, From f867615713f475d1cc16910041e14df0a10f3f2e Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:50:14 +0000 Subject: [PATCH 27/38] Line spacing --- packages/toolpad-core/src/appDom.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/toolpad-core/src/appDom.ts b/packages/toolpad-core/src/appDom.ts index 58d34dbc247..e14bef164b2 100644 --- a/packages/toolpad-core/src/appDom.ts +++ b/packages/toolpad-core/src/appDom.ts @@ -831,7 +831,6 @@ export function spreadNode(dom: AppDom, node: Child) { if (parent && parentProp && isElement(node)) { for (const child of getChildNodes(draft, node).children) { const parentIndex = getNewParentIndexBeforeNode(draft, node, parentProp); - draft = setNodeParent(draft, child, parent.id, parentProp, parentIndex); } draft = removeNode(draft, node.id); From 11caaa3cd615d97a2ed2486bf5bd1a693b50b722 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:11:51 +0000 Subject: [PATCH 28/38] More tests behaving differently for no reason --- test/utils/locators.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/utils/locators.ts b/test/utils/locators.ts index dc69e5fdb8c..a3dc2cf9fbe 100644 --- a/test/utils/locators.ts +++ b/test/utils/locators.ts @@ -1,9 +1,11 @@ import { Page, Locator, expect } from '../playwright/test'; +type BoundingBox = NonNullable>>; + export async function waitForBoundingBox( locator: Locator, ): Promise> { - let boundingBox; + let boundingBox: BoundingBox | null = null; await expect(async () => { boundingBox = await locator.boundingBox(); expect(boundingBox).toBeTruthy(); From 01f7c34eed7cd991711f96c9a479c66e63ff3a5d Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:36:53 +0000 Subject: [PATCH 29/38] Still don't know what's wrong --- test/models/ToolpadEditor.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/models/ToolpadEditor.ts b/test/models/ToolpadEditor.ts index abadb6ce08b..c49482658ab 100644 --- a/test/models/ToolpadEditor.ts +++ b/test/models/ToolpadEditor.ts @@ -120,7 +120,7 @@ export class ToolpadEditor { await this.page.mouse.move( sourceBoundingBox!.x + sourceBoundingBox!.width / 2, sourceBoundingBox!.y + sourceBoundingBox!.height / 2, - { steps: 10 }, + { steps }, ); await this.page.mouse.down(); @@ -153,7 +153,7 @@ export class ToolpadEditor { moveTargetX = pageRootBoundingBox!.x + pageRootBoundingBox!.width / 2; } if (!moveTargetY) { - moveTargetY = pageRootBoundingBox!.y + pageRootBoundingBox!.height / 2; + moveTargetY = pageRootBoundingBox!.y + pageRootBoundingBox!.height + 12; } const sourceLocator = this.getComponentCatalogItem(componentName); From 16db5e67fd14f62c9ca5062255f95e290496e5f1 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:22:16 +0000 Subject: [PATCH 30/38] Fix tests not passing if component catalog needs to scroll --- test/models/ToolpadEditor.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/models/ToolpadEditor.ts b/test/models/ToolpadEditor.ts index c49482658ab..bce9c05aad6 100644 --- a/test/models/ToolpadEditor.ts +++ b/test/models/ToolpadEditor.ts @@ -159,6 +159,8 @@ export class ToolpadEditor { const sourceLocator = this.getComponentCatalogItem(componentName); await expect(sourceLocator).toBeVisible(); + await sourceLocator.hover(); + await this.dragTo(sourceLocator, moveTargetX!, moveTargetY!, hasDrop, steps); await style.evaluate((elm) => elm.parentNode?.removeChild(elm)); From f05c44bce8f1409d2ac7985b4f4e42c04c21194f Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 22 Feb 2024 16:49:07 +0000 Subject: [PATCH 31/38] I don't think this condition is ever true --- .../PageEditor/RenderPanel/NodeHud.tsx | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx index 390143943b4..2f3c2727feb 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/NodeHud.tsx @@ -13,18 +13,13 @@ import { RECTANGLE_EDGE_RIGHT, RECTANGLE_EDGE_TOP, } from '../../../../utils/geometry'; -import { usePageEditorState } from '../PageEditorProvider'; const HINT_POSITION_TOP = 'top'; const HINT_POSITION_BOTTOM = 'bottom'; -const HINT_POSITION_BOTTOM_INNER = 'bottomInner'; const HUD_HEIGHT = 30; // px -type HintPosition = - | typeof HINT_POSITION_TOP - | typeof HINT_POSITION_BOTTOM - | typeof HINT_POSITION_BOTTOM_INNER; +type HintPosition = typeof HINT_POSITION_TOP | typeof HINT_POSITION_BOTTOM; function stopPropagationHandler(event: React.SyntheticEvent) { event.stopPropagation(); @@ -92,8 +87,7 @@ const SelectionHintWrapper = styled('div', { ? { top: 0, transform: 'translate(0, -100%)' } : { bottom: 0, - transform: - hintPosition === HINT_POSITION_BOTTOM_INNER ? 'translate(0, 0)' : 'translate(0, 100%)', + transform: 'translate(0, 100%)', }), }, })); @@ -196,17 +190,9 @@ export default function NodeHud({ isHoverable = true, isHovered = false, }: NodeHudProps) { - const { nodeId: pageNodeId, viewState } = usePageEditorState(); - - const { nodes: nodesInfo } = viewState; - - const pageNodeRect = nodesInfo[pageNodeId]?.rect; - let hintPosition: HintPosition = HINT_POSITION_BOTTOM; if (rect.y > HUD_HEIGHT) { hintPosition = HINT_POSITION_TOP; - } else if (pageNodeRect && rect.y + rect.height + HUD_HEIGHT > pageNodeRect.height) { - hintPosition = HINT_POSITION_BOTTOM_INNER; } const interactiveNodeClipPath = React.useMemo( From ffcf4286c503dfc39b9b6be5cbb1026579d8bd32 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 22 Feb 2024 18:09:24 +0000 Subject: [PATCH 32/38] Fix fixtures --- test/visual/components/fixture/toolpad/application.yml | 3 +++ .../components/fixture/toolpad/pages/blank/page.yml | 5 ++++- .../components/fixture/toolpad/pages/components/page.yml | 5 ++++- .../components/fixture/toolpad/pages/dragdrop/page.yml | 5 ++++- .../components/fixture/toolpad/pages/grids/page.yml | 8 +++++++- .../visual/components/fixture/toolpad/pages/rows/page.yml | 5 ++++- .../visual/components/fixture/toolpad/pages/text/page.yml | 5 ++++- test/visual/components/index.spec.ts | 2 +- 8 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 test/visual/components/fixture/toolpad/application.yml diff --git a/test/visual/components/fixture/toolpad/application.yml b/test/visual/components/fixture/toolpad/application.yml new file mode 100644 index 00000000000..6b008228134 --- /dev/null +++ b/test/visual/components/fixture/toolpad/application.yml @@ -0,0 +1,3 @@ +apiVersion: v1 +kind: application +spec: {} diff --git a/test/visual/components/fixture/toolpad/pages/blank/page.yml b/test/visual/components/fixture/toolpad/pages/blank/page.yml index dc75ccf1a19..a4a31d642ce 100644 --- a/test/visual/components/fixture/toolpad/pages/blank/page.yml +++ b/test/visual/components/fixture/toolpad/pages/blank/page.yml @@ -1,6 +1,9 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/mui/mui-toolpad/v0.1.50/docs/schemas/v1/definitions.json#properties/Page + apiVersion: v1 kind: page spec: - id: QYjq2fJ title: blank display: shell + alias: + - QYjq2fJ diff --git a/test/visual/components/fixture/toolpad/pages/components/page.yml b/test/visual/components/fixture/toolpad/pages/components/page.yml index a194a9adf87..c0d087af411 100644 --- a/test/visual/components/fixture/toolpad/pages/components/page.yml +++ b/test/visual/components/fixture/toolpad/pages/components/page.yml @@ -1,7 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/mui/mui-toolpad/v0.1.50/docs/schemas/v1/definitions.json#properties/Page + apiVersion: v1 kind: page spec: - id: f703ps3 title: components content: - component: Button @@ -116,3 +117,5 @@ spec: props: mode: switch label: Switch + alias: + - f703ps3 diff --git a/test/visual/components/fixture/toolpad/pages/dragdrop/page.yml b/test/visual/components/fixture/toolpad/pages/dragdrop/page.yml index f68ca1d9d0d..a1fc3c229f8 100644 --- a/test/visual/components/fixture/toolpad/pages/dragdrop/page.yml +++ b/test/visual/components/fixture/toolpad/pages/dragdrop/page.yml @@ -1,7 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/mui/mui-toolpad/v0.1.50/docs/schemas/v1/definitions.json#properties/Page + apiVersion: v1 kind: page spec: - id: 8ixPqyI title: dragdrop display: shell content: @@ -19,3 +20,5 @@ spec: content: contained - component: Paper name: paper1 + alias: + - 8ixPqyI diff --git a/test/visual/components/fixture/toolpad/pages/grids/page.yml b/test/visual/components/fixture/toolpad/pages/grids/page.yml index 4f0ab597f47..83b532d77bf 100644 --- a/test/visual/components/fixture/toolpad/pages/grids/page.yml +++ b/test/visual/components/fixture/toolpad/pages/grids/page.yml @@ -1,7 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/mui/mui-toolpad/v0.1.50/docs/schemas/v1/definitions.json#properties/Page + apiVersion: v1 kind: page spec: - id: Dh9u36B title: grids display: shell content: @@ -19,6 +20,7 @@ spec: name: dataGrid layout: columnSize: 1 + height: 120 props: rows: - id: one @@ -33,6 +35,8 @@ spec: columns: - field: id type: string + layout: + height: 120 - component: DataGrid name: dataGrid1 props: @@ -41,3 +45,5 @@ spec: columns: - field: id type: string + alias: + - Dh9u36B diff --git a/test/visual/components/fixture/toolpad/pages/rows/page.yml b/test/visual/components/fixture/toolpad/pages/rows/page.yml index fa6cb1e2196..6aaaf9868b6 100644 --- a/test/visual/components/fixture/toolpad/pages/rows/page.yml +++ b/test/visual/components/fixture/toolpad/pages/rows/page.yml @@ -1,7 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/mui/mui-toolpad/v0.1.50/docs/schemas/v1/definitions.json#properties/Page + apiVersion: v1 kind: page spec: - id: 5YDOftB title: rows display: shell content: @@ -14,3 +15,5 @@ spec: ] props: justifyContent: start + alias: + - 5YDOftB diff --git a/test/visual/components/fixture/toolpad/pages/text/page.yml b/test/visual/components/fixture/toolpad/pages/text/page.yml index 37e2ce79792..77701e105c8 100644 --- a/test/visual/components/fixture/toolpad/pages/text/page.yml +++ b/test/visual/components/fixture/toolpad/pages/text/page.yml @@ -1,7 +1,8 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/mui/mui-toolpad/v0.1.50/docs/schemas/v1/definitions.json#properties/Page + apiVersion: v1 kind: page spec: - id: QYjq2fJ title: text display: shell content: @@ -59,3 +60,5 @@ spec: props: mode: link value: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + alias: + - QYjq2fJ diff --git a/test/visual/components/index.spec.ts b/test/visual/components/index.spec.ts index 1074d81e463..566e3daca55 100644 --- a/test/visual/components/index.spec.ts +++ b/test/visual/components/index.spec.ts @@ -111,7 +111,7 @@ test('showing grid while resizing elements', async ({ page, argosScreenshot }) = await argosScreenshot('resize-grid'); }); -test('resizing element heights', async ({ page, argosScreenshot }) => { +test.only('resizing element heights', async ({ page, argosScreenshot }) => { const editorModel = new ToolpadEditor(page); await editorModel.goToPage('grids'); From 1ae8a850171acaf663727e5ba9e87feead1e3c42 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Thu, 22 Feb 2024 18:12:02 +0000 Subject: [PATCH 33/38] Remove test.only --- test/visual/components/index.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/visual/components/index.spec.ts b/test/visual/components/index.spec.ts index 566e3daca55..1074d81e463 100644 --- a/test/visual/components/index.spec.ts +++ b/test/visual/components/index.spec.ts @@ -111,7 +111,7 @@ test('showing grid while resizing elements', async ({ page, argosScreenshot }) = await argosScreenshot('resize-grid'); }); -test.only('resizing element heights', async ({ page, argosScreenshot }) => { +test('resizing element heights', async ({ page, argosScreenshot }) => { const editorModel = new ToolpadEditor(page); await editorModel.goToPage('grids'); From 1dba2a349856810f1cc206d80bd42b22ec33e89d Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 23 Feb 2024 16:52:03 +0000 Subject: [PATCH 34/38] Make Spacer height resizable --- .../AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx | 4 +++- packages/toolpad-components/src/Spacer.tsx | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 7390849b1ed..10afae7efd2 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1474,7 +1474,9 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { isElementNode && !isPageRow(node) && !isPageColumn(node) && - (nodeComponentId === 'Chart' || nodeComponentId === 'DataGrid'); + (nodeComponentId === 'Chart' || + nodeComponentId === 'DataGrid' || + nodeComponentId === 'Spacer'); const isResizing = Boolean(draggedEdge); const isResizingNode = isResizing && node.id === draggedNodeId; diff --git a/packages/toolpad-components/src/Spacer.tsx b/packages/toolpad-components/src/Spacer.tsx index 05970165736..92f48675f94 100644 --- a/packages/toolpad-components/src/Spacer.tsx +++ b/packages/toolpad-components/src/Spacer.tsx @@ -3,7 +3,7 @@ import { Box, BoxProps } from '@mui/material'; import createBuiltin from './createBuiltin'; import { SX_PROP_HELPER_TEXT } from './constants'; -const SPACER_MINIMUM_HEIGHT = 20; // pixels +const SPACER_MINIMUM_HEIGHT = 60; // pixels function Spacer(props: BoxProps) { return ; From 6e1e06c0b3a75537160f1d730ed65f381f42ea30 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 23 Feb 2024 17:43:11 +0000 Subject: [PATCH 35/38] Remove Spacer component --- .../toolpad/reference/components/index.md | 1 - .../reference/components/manifest.json | 4 ---- .../toolpad/reference/components/spacer.md | 14 ------------- .../toolpad/reference/components/spacer.js | 9 -------- .../src/runtime/toolpadComponents/index.tsx | 1 - .../ComponentCatalog/ComponentCatalogItem.tsx | 1 - .../PageEditor/RenderPanel/RenderOverlay.tsx | 3 +-- .../toolpad/AppEditor/toolpadComponents.tsx | 5 ----- packages/toolpad-components/src/Spacer.tsx | 21 ------------------- 9 files changed, 1 insertion(+), 58 deletions(-) delete mode 100644 docs/data/toolpad/reference/components/spacer.md delete mode 100644 docs/pages/toolpad/reference/components/spacer.js delete mode 100644 packages/toolpad-components/src/Spacer.tsx diff --git a/docs/data/toolpad/reference/components/index.md b/docs/data/toolpad/reference/components/index.md index 2ab059b41c2..43b864aea74 100644 --- a/docs/data/toolpad/reference/components/index.md +++ b/docs/data/toolpad/reference/components/index.md @@ -20,7 +20,6 @@ - [PageRow](/toolpad/reference/components/page-row/) - [Paper](/toolpad/reference/components/paper/) - [Select](/toolpad/reference/components/select/) -- [Spacer](/toolpad/reference/components/spacer/) - [Stack](/toolpad/reference/components/stack/) - [Tabs](/toolpad/reference/components/tabs/) - [Text](/toolpad/reference/components/text/) diff --git a/docs/data/toolpad/reference/components/manifest.json b/docs/data/toolpad/reference/components/manifest.json index 2ad5bb43e2a..4b9f04a1960 100644 --- a/docs/data/toolpad/reference/components/manifest.json +++ b/docs/data/toolpad/reference/components/manifest.json @@ -73,10 +73,6 @@ "title": "Select", "pathname": "/toolpad/reference/components/select" }, - { - "title": "Spacer", - "pathname": "/toolpad/reference/components/spacer" - }, { "title": "Stack", "pathname": "/toolpad/reference/components/stack" diff --git a/docs/data/toolpad/reference/components/spacer.md b/docs/data/toolpad/reference/components/spacer.md deleted file mode 100644 index 7e9572506ac..00000000000 --- a/docs/data/toolpad/reference/components/spacer.md +++ /dev/null @@ -1,14 +0,0 @@ - - -# Spacer - -

API docs for the Toolpad Spacer component.

- -Spacer component. -It allows for creating space between elements. - -## Properties - -| Name | Type | Default | Description | -| :-------------------------------- | :------------------------------------ | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | diff --git a/docs/pages/toolpad/reference/components/spacer.js b/docs/pages/toolpad/reference/components/spacer.js deleted file mode 100644 index bfad331aa56..00000000000 --- a/docs/pages/toolpad/reference/components/spacer.js +++ /dev/null @@ -1,9 +0,0 @@ -/* ATTENTION: DO NOT EDIT! This file has been auto-generated using `pnpm docs:build:api`. */ - -import * as React from 'react'; -import MarkdownDocs from '@mui/monorepo/docs/src/modules/components/MarkdownDocs'; -import * as pageProps from '../../../../data/toolpad/reference/components/spacer.md?@mui/markdown'; - -export default function Page() { - return ; -} diff --git a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx index 77bb5872a8b..35baa6a4bd6 100644 --- a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx +++ b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx @@ -2,7 +2,6 @@ import * as appDom from '@mui/toolpad-core/appDom'; export const PAGE_ROW_COMPONENT_ID = 'PageRow'; export const PAGE_COLUMN_COMPONENT_ID = 'PageColumn'; -export const SPACER_COMPONENT_ID = 'Spacer'; export const STACK_COMPONENT_ID = 'Stack'; export const FORM_COMPONENT_ID = 'Form'; diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx index f6e4e04ed6e..b2d6c5cb46f 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx @@ -71,7 +71,6 @@ const iconMap = new Map>([ ['PageRow', TableRowsIcon], ['PageColumn', ViewColumnIcon], ['Metric', TagIcon], - ['Spacer', SpaceBarIcon], ]); type ComponentItemKind = 'future' | 'builtIn' | 'create' | 'custom'; diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 10afae7efd2..41da4e94ec5 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1475,8 +1475,7 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { !isPageRow(node) && !isPageColumn(node) && (nodeComponentId === 'Chart' || - nodeComponentId === 'DataGrid' || - nodeComponentId === 'Spacer'); + nodeComponentId === 'DataGrid'); const isResizing = Boolean(draggedEdge); const isResizingNode = isResizing && node.id === draggedNodeId; diff --git a/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx b/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx index 1a8dca21e54..05e4743b616 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx @@ -5,7 +5,6 @@ import { FORM_COMPONENT_ID, PAGE_COLUMN_COMPONENT_ID, PAGE_ROW_COMPONENT_ID, - SPACER_COMPONENT_ID, STACK_COMPONENT_ID, } from '../../runtime/toolpadComponents'; import { useProject } from '../../project'; @@ -115,10 +114,6 @@ export const INTERNAL_COMPONENTS = new Map([ }, ], [FORM_COMPONENT_ID, { displayName: 'Form', builtIn: 'Form', synonyms: [] }], - [ - SPACER_COMPONENT_ID, - { displayName: 'Spacer', builtIn: 'Spacer', synonyms: ['margin', 'blank', 'empty', 'void'] }, - ], [ 'Password', { diff --git a/packages/toolpad-components/src/Spacer.tsx b/packages/toolpad-components/src/Spacer.tsx deleted file mode 100644 index 92f48675f94..00000000000 --- a/packages/toolpad-components/src/Spacer.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react'; -import { Box, BoxProps } from '@mui/material'; -import createBuiltin from './createBuiltin'; -import { SX_PROP_HELPER_TEXT } from './constants'; - -const SPACER_MINIMUM_HEIGHT = 60; // pixels - -function Spacer(props: BoxProps) { - return ; -} - -export default createBuiltin(Spacer, { - helperText: 'Spacer component.\nIt allows for creating space between elements.', - minimumLayoutHeight: SPACER_MINIMUM_HEIGHT, - argTypes: { - sx: { - helperText: SX_PROP_HELPER_TEXT, - type: 'object', - }, - }, -}); From 19f3ef59454b974dcbc2a6a3b2daa3966efa30f0 Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 23 Feb 2024 17:46:29 +0000 Subject: [PATCH 36/38] Unused imports --- .../PageEditor/ComponentCatalog/ComponentCatalogItem.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx index b2d6c5cb46f..5fe3f267f1d 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx @@ -33,7 +33,6 @@ import TagIcon from '@mui/icons-material/Tag'; import PasswordIcon from '@mui/icons-material/Password'; import LinkIcon from '@mui/icons-material/Link'; import TextFormatIcon from '@mui/icons-material/TextFormat'; -import SpaceBarIcon from '@mui/icons-material/SpaceBar'; import PieChartIcon from '@mui/icons-material/PieChart'; const iconMap = new Map>([ From 7b9c76303502129e03ef09f767cb4a40866f729e Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 23 Feb 2024 18:05:21 +0000 Subject: [PATCH 37/38] Revert "Remove Spacer component" This reverts commit 6e1e06c0b3a75537160f1d730ed65f381f42ea30. --- .../toolpad/reference/components/index.md | 1 + .../reference/components/manifest.json | 4 ++++ .../toolpad/reference/components/spacer.md | 14 +++++++++++++ .../toolpad/reference/components/spacer.js | 9 ++++++++ .../src/runtime/toolpadComponents/index.tsx | 1 + .../ComponentCatalog/ComponentCatalogItem.tsx | 1 + .../PageEditor/RenderPanel/RenderOverlay.tsx | 3 ++- .../toolpad/AppEditor/toolpadComponents.tsx | 5 +++++ packages/toolpad-components/src/Spacer.tsx | 21 +++++++++++++++++++ 9 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 docs/data/toolpad/reference/components/spacer.md create mode 100644 docs/pages/toolpad/reference/components/spacer.js create mode 100644 packages/toolpad-components/src/Spacer.tsx diff --git a/docs/data/toolpad/reference/components/index.md b/docs/data/toolpad/reference/components/index.md index 43b864aea74..2ab059b41c2 100644 --- a/docs/data/toolpad/reference/components/index.md +++ b/docs/data/toolpad/reference/components/index.md @@ -20,6 +20,7 @@ - [PageRow](/toolpad/reference/components/page-row/) - [Paper](/toolpad/reference/components/paper/) - [Select](/toolpad/reference/components/select/) +- [Spacer](/toolpad/reference/components/spacer/) - [Stack](/toolpad/reference/components/stack/) - [Tabs](/toolpad/reference/components/tabs/) - [Text](/toolpad/reference/components/text/) diff --git a/docs/data/toolpad/reference/components/manifest.json b/docs/data/toolpad/reference/components/manifest.json index 4b9f04a1960..2ad5bb43e2a 100644 --- a/docs/data/toolpad/reference/components/manifest.json +++ b/docs/data/toolpad/reference/components/manifest.json @@ -73,6 +73,10 @@ "title": "Select", "pathname": "/toolpad/reference/components/select" }, + { + "title": "Spacer", + "pathname": "/toolpad/reference/components/spacer" + }, { "title": "Stack", "pathname": "/toolpad/reference/components/stack" diff --git a/docs/data/toolpad/reference/components/spacer.md b/docs/data/toolpad/reference/components/spacer.md new file mode 100644 index 00000000000..7e9572506ac --- /dev/null +++ b/docs/data/toolpad/reference/components/spacer.md @@ -0,0 +1,14 @@ + + +# Spacer + +

API docs for the Toolpad Spacer component.

+ +Spacer component. +It allows for creating space between elements. + +## Properties + +| Name | Type | Default | Description | +| :-------------------------------- | :------------------------------------ | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| sx | object | | The [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/) is used for defining custom styles that have access to the theme. All MUI System properties are available via the `sx` prop. In addition, the `sx` prop allows you to specify any other CSS rules you may need. | diff --git a/docs/pages/toolpad/reference/components/spacer.js b/docs/pages/toolpad/reference/components/spacer.js new file mode 100644 index 00000000000..bfad331aa56 --- /dev/null +++ b/docs/pages/toolpad/reference/components/spacer.js @@ -0,0 +1,9 @@ +/* ATTENTION: DO NOT EDIT! This file has been auto-generated using `pnpm docs:build:api`. */ + +import * as React from 'react'; +import MarkdownDocs from '@mui/monorepo/docs/src/modules/components/MarkdownDocs'; +import * as pageProps from '../../../../data/toolpad/reference/components/spacer.md?@mui/markdown'; + +export default function Page() { + return ; +} diff --git a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx index 35baa6a4bd6..77bb5872a8b 100644 --- a/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx +++ b/packages/toolpad-app/src/runtime/toolpadComponents/index.tsx @@ -2,6 +2,7 @@ import * as appDom from '@mui/toolpad-core/appDom'; export const PAGE_ROW_COMPONENT_ID = 'PageRow'; export const PAGE_COLUMN_COMPONENT_ID = 'PageColumn'; +export const SPACER_COMPONENT_ID = 'Spacer'; export const STACK_COMPONENT_ID = 'Stack'; export const FORM_COMPONENT_ID = 'Form'; diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx index 5fe3f267f1d..6774e39d20b 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx @@ -70,6 +70,7 @@ const iconMap = new Map>([ ['PageRow', TableRowsIcon], ['PageColumn', ViewColumnIcon], ['Metric', TagIcon], + ['Spacer', SpaceBarIcon], ]); type ComponentItemKind = 'future' | 'builtIn' | 'create' | 'custom'; diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 41da4e94ec5..10afae7efd2 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -1475,7 +1475,8 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) { !isPageRow(node) && !isPageColumn(node) && (nodeComponentId === 'Chart' || - nodeComponentId === 'DataGrid'); + nodeComponentId === 'DataGrid' || + nodeComponentId === 'Spacer'); const isResizing = Boolean(draggedEdge); const isResizingNode = isResizing && node.id === draggedNodeId; diff --git a/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx b/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx index 05e4743b616..1a8dca21e54 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/toolpadComponents.tsx @@ -5,6 +5,7 @@ import { FORM_COMPONENT_ID, PAGE_COLUMN_COMPONENT_ID, PAGE_ROW_COMPONENT_ID, + SPACER_COMPONENT_ID, STACK_COMPONENT_ID, } from '../../runtime/toolpadComponents'; import { useProject } from '../../project'; @@ -114,6 +115,10 @@ export const INTERNAL_COMPONENTS = new Map([ }, ], [FORM_COMPONENT_ID, { displayName: 'Form', builtIn: 'Form', synonyms: [] }], + [ + SPACER_COMPONENT_ID, + { displayName: 'Spacer', builtIn: 'Spacer', synonyms: ['margin', 'blank', 'empty', 'void'] }, + ], [ 'Password', { diff --git a/packages/toolpad-components/src/Spacer.tsx b/packages/toolpad-components/src/Spacer.tsx new file mode 100644 index 00000000000..92f48675f94 --- /dev/null +++ b/packages/toolpad-components/src/Spacer.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import { Box, BoxProps } from '@mui/material'; +import createBuiltin from './createBuiltin'; +import { SX_PROP_HELPER_TEXT } from './constants'; + +const SPACER_MINIMUM_HEIGHT = 60; // pixels + +function Spacer(props: BoxProps) { + return ; +} + +export default createBuiltin(Spacer, { + helperText: 'Spacer component.\nIt allows for creating space between elements.', + minimumLayoutHeight: SPACER_MINIMUM_HEIGHT, + argTypes: { + sx: { + helperText: SX_PROP_HELPER_TEXT, + type: 'object', + }, + }, +}); From bc1488177b9a34e70c32d1421d9b6cca5805fd6f Mon Sep 17 00:00:00 2001 From: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com> Date: Fri, 23 Feb 2024 18:07:49 +0000 Subject: [PATCH 38/38] Readjust --- .../PageEditor/ComponentCatalog/ComponentCatalogItem.tsx | 1 + packages/toolpad-components/src/index.tsx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx index 6774e39d20b..f6e4e04ed6e 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/ComponentCatalog/ComponentCatalogItem.tsx @@ -33,6 +33,7 @@ import TagIcon from '@mui/icons-material/Tag'; import PasswordIcon from '@mui/icons-material/Password'; import LinkIcon from '@mui/icons-material/Link'; import TextFormatIcon from '@mui/icons-material/TextFormat'; +import SpaceBarIcon from '@mui/icons-material/SpaceBar'; import PieChartIcon from '@mui/icons-material/PieChart'; const iconMap = new Map>([ diff --git a/packages/toolpad-components/src/index.tsx b/packages/toolpad-components/src/index.tsx index d0f112ad58c..0ed2e3c78b1 100644 --- a/packages/toolpad-components/src/index.tsx +++ b/packages/toolpad-components/src/index.tsx @@ -36,6 +36,8 @@ export { default as Checkbox } from './Checkbox'; export { default as Form } from './Form'; +export { default as Spacer } from './Spacer'; + export { default as Metric } from './Metric'; export type { ColorScale, ColorScaleStop } from './Metric';