diff --git a/src/components/DashKit/__stories__/DashKitGroupsShowcase.tsx b/src/components/DashKit/__stories__/DashKitGroupsShowcase.tsx index ce1940a..d829dec 100644 --- a/src/components/DashKit/__stories__/DashKitGroupsShowcase.tsx +++ b/src/components/DashKit/__stories__/DashKitGroupsShowcase.tsx @@ -29,6 +29,7 @@ const GRID_COLUMNS = 36; export const DashKitGroupsShowcase: React.FC = () => { const [editMode, setEditMode] = React.useState(true); + const [headerInteractions, setHeaderInteractions] = React.useState(true); const onClick = () => { console.log('click'); @@ -112,21 +113,30 @@ export const DashKitGroupsShowcase: React.FC = () => { ); }, gridProperties: (props: ReactGridLayoutProps) => { - return { + const overrideProps: ReactGridLayoutProps = { ...props, compactType: 'horizontal-nowrap', maxRows: MAX_ROWS, + }; + + if (headerInteractions) { + return overrideProps; + } + + return { + ...overrideProps, noOverlay: true, + isResizable: false, + isDraggable: false, + resizeHandles: [], }; }, }, { id: DEFAULT_GROUP, gridProperties: (props: ReactGridLayoutProps) => { - const copy = {...props}; - return { - ...copy, + ...props, compactType: null, allowOverlap: true, resizeHandles: ['s', 'w', 'e', 'n', 'sw', 'nw', 'se', 'ne'], @@ -134,7 +144,7 @@ export const DashKitGroupsShowcase: React.FC = () => { }, }, ], - [], + [headerInteractions], ); const overlayMenuItems = React.useMemo(() => { @@ -280,12 +290,29 @@ export const DashKitGroupsShowcase: React.FC = () => { onDragEnd={() => { console.log('dragEnded'); }} + onDropDragOver={(item) => { + if (!headerInteractions && item.parent === fixedGroup) { + return false; + } + + return true; + }} > + { overlayMenuItems={overlayMenuItems} onDragStart={updateConfigOrder} onResizeStart={updateConfigOrder} + context={{editModeHeader: headerInteractions}} /> diff --git a/src/components/DashKit/__stories__/Demo.scss b/src/components/DashKit/__stories__/Demo.scss index 58cb1e4..8d17691 100644 --- a/src/components/DashKit/__stories__/Demo.scss +++ b/src/components/DashKit/__stories__/Demo.scss @@ -36,7 +36,7 @@ overflow: auto; top: 0; z-index: 3; - min-height: 44px; + min-height: 52px; display: flex; flex-direction: column; margin-bottom: 8px; diff --git a/src/components/DashKitDnDWrapper/DashKitDnDWrapper.tsx b/src/components/DashKitDnDWrapper/DashKitDnDWrapper.tsx index 01e91ce..9d9bb9e 100644 --- a/src/components/DashKitDnDWrapper/DashKitDnDWrapper.tsx +++ b/src/components/DashKitDnDWrapper/DashKitDnDWrapper.tsx @@ -1,10 +1,14 @@ import React from 'react'; import {DashKitDnDContext} from '../../context/DashKitContext'; -import type {ItemDragProps} from '../../shared'; +import type {ItemDragProps, ItemDropDragOver} from '../../shared'; type DashKitDnDWrapperProps = { dragImageSrc?: string; + onDropDragOver?: ( + draggedItem: ItemDropDragOver, + sharedItem: ItemDropDragOver | null, + ) => void | boolean; onDragStart?: (dragProps: ItemDragProps) => void; onDragEnd?: () => void; children: React.ReactElement; @@ -22,20 +26,22 @@ export const DashKitDnDWrapper: React.FC = (props) => { return img; }, [props.dragImageSrc]); + const onDragStartProp = props.onDragStart; const onDragStart = React.useCallback( (_: React.DragEvent, itemDragProps: ItemDragProps) => { setDragProps(itemDragProps); - props.onDragStart?.(itemDragProps); + onDragStartProp?.(itemDragProps); }, - [setDragProps, props.onDragStart], + [setDragProps, onDragStartProp], ); + const onDragEndProp = props.onDragEnd; const onDragEnd = React.useCallback( (_: React.DragEvent) => { setDragProps(null); - props.onDragEnd?.(); + onDragEndProp?.(); }, - [setDragProps, props.onDragEnd], + [setDragProps, onDragEndProp], ); const contextValue = React.useMemo(() => { @@ -44,8 +50,9 @@ export const DashKitDnDWrapper: React.FC = (props) => { dragImagePreview, onDragStart, onDragEnd, + onDropDragOver: props.onDropDragOver, }; - }, [dragProps, dragImagePreview, onDragStart, onDragEnd]); + }, [dragProps, dragImagePreview, onDragStart, onDragEnd, props.onDropDragOver]); return ( diff --git a/src/components/GridLayout/GridLayout.js b/src/components/GridLayout/GridLayout.js index 51e5085..660be2e 100644 --- a/src/components/GridLayout/GridLayout.js +++ b/src/components/GridLayout/GridLayout.js @@ -533,11 +533,17 @@ export default class GridLayout extends React.PureComponent { const {h, w, i} = currentDraggingElement.layoutItem; const {type} = currentDraggingElement.item; - return onDropDragOver(e, properties, layout, {h, w, i, type}); + return onDropDragOver(e, group, properties, layout, { + h, + w, + i, + type, + parent: currentDraggingElement.group, + }); } if (dragOverPlugin) { - return onDropDragOver(e, properties, layout); + return onDropDragOver(e, group, properties, layout); } return false; @@ -581,11 +587,9 @@ export default class GridLayout extends React.PureComponent { } = this.context; const {currentDraggingElement, draggedOverGroup} = this.state; - - const properties = groupGridProperties - ? groupGridProperties({ - ...registerManager.gridLayout, - }) + const hasOwnGroupProperties = typeof groupGridProperties === 'function'; + const properties = hasOwnGroupProperties + ? groupGridProperties({...registerManager.gridLayout}) : registerManager.gridLayout; let {compactType} = properties; @@ -637,7 +641,9 @@ export default class GridLayout extends React.PureComponent { const isDraggedOut = isCurrentItem && this.state.draggedOut; const isDragging = this.state.isDragging; const itemNoOverlay = - 'noOverlay' in properties ? properties.noOverlay : noOverlay; + hasOwnGroupProperties && 'noOverlay' in properties + ? properties.noOverlay + : noOverlay; return ( ref && ref.reload && ref.reload(data)); }, []); - const dragProps = dndContext?.dragProps; + const dragPropsContext = dndContext?.dragProps; + const onDropDragOverContext = dndContext?.onDropDragOver; const dragOverPlugin = React.useMemo(() => { - if (!dragProps) { + if (!dragPropsContext) { return null; } - const pluginType = dragProps.type; + const pluginType = dragPropsContext.type; if (props.registerManager.check(pluginType)) { return props.registerManager.getItem(pluginType); @@ -333,10 +334,10 @@ function useMemoStateContext(props) { console.error(`Uknown pluginType: ${pluginType}`); return null; } - }, [dragProps, props.registerManager]); + }, [dragPropsContext, props.registerManager]); const onDropDragOver = React.useCallback( - (_e, gridProps, groupLayout, sharedItem) => { + (_e, group, gridProps, groupLayout, sharedItem) => { if (temporaryLayout) { resetTemporaryLayout(); return false; @@ -372,26 +373,49 @@ function useMemoStateContext(props) { const { h = defaultLayout?.h || DEFAULT_WIDGET_HEIGHT, w = defaultLayout?.w || DEFAULT_WIDGET_WIDTH, - } = dragProps?.layout || {}; + } = dragPropsContext?.layout || {}; - return { + const resultLayout = { h: maxH ? Math.min(h, maxH) : h, w: maxW ? Math.min(w, maxW) : w, }; + + if ( + onDropDragOverContext && + onDropDragOverContext?.( + { + ...sharedItem, + ...resultLayout, + ...dragPropsContext, + parent: group, + }, + sharedItem ?? null, + ) === false + ) { + return false; + } + + return resultLayout; }, - [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps], + [ + resetTemporaryLayout, + temporaryLayout, + dragOverPlugin, + dragPropsContext, + onDropDragOverContext, + ], ); const onDropProp = props.onDrop; const onDrop = React.useCallback( (newLayout, item) => { - if (!dragProps) { + if (!dragPropsContext) { return; } setTemporaryLayout({ data: [...newLayout, item], - dragProps, + dragProps: dragPropsContext, }); onDropProp({ @@ -404,10 +428,10 @@ function useMemoStateContext(props) { }, []), itemLayout: pick(item, ITEM_PROPS), commit: resetTemporaryLayout, - dragProps, + dragProps: dragPropsContext, }); }, - [dragProps, onDropProp, setTemporaryLayout, resetTemporaryLayout], + [dragPropsContext, onDropProp, setTemporaryLayout, resetTemporaryLayout], ); const dashkitContextValue = React.useMemo( diff --git a/src/shared/types/common.ts b/src/shared/types/common.ts index 607ff2a..74b7ab0 100644 --- a/src/shared/types/common.ts +++ b/src/shared/types/common.ts @@ -16,6 +16,11 @@ export type ItemDragProps = { extra?: any; }; +export type ItemDropDragOver = Omit & { + type: string; + i?: ConfigLayout['i']; +}; + export type ItemDropProps = { commit: () => void; dragProps: ItemDragProps;