Skip to content

Commit

Permalink
feat: add custom dimenstions values for dragProps
Browse files Browse the repository at this point in the history
  • Loading branch information
flops committed May 16, 2024
1 parent cb7a7f0 commit c66df04
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 43 deletions.
18 changes: 4 additions & 14 deletions src/components/ActionPanel/ActionPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,10 @@ import {CSSTransition} from 'react-transition-group';
import {DashKitDnDContext} from '../../context/DashKitContext';
import {cn} from '../../utils/cn';

import {ActionPanelProps} from './types';
import {ActionPanelItem, ActionPanelProps} from './types';

import './ActionPanel.scss';

export type ActionPanelItem = {
id: string;
icon: React.ReactNode;
title: string;
onClick?: () => void;
className?: string;
qa?: string;
pluginType?: string;
};

type DndProps =
| {}
| {
Expand All @@ -35,9 +25,9 @@ export const ActionPanelItemContainer = ({item}: {item: ActionPanelItem}) => {

const onDragStart = React.useCallback(
(e: React.DragEvent) => {
dragContext?.onDragStart(e, item.pluginType);
dragContext?.onDragStart(e, item.dragProps);
},
[dragContext?.onDragStart, item.pluginType],
[dragContext?.onDragStart, item.dragProps],

Check warning on line 30 in src/components/ActionPanel/ActionPanel.tsx

View workflow job for this annotation

GitHub Actions / Verify Files

React Hook React.useCallback has a missing dependency: 'dragContext'. Either include it or remove the dependency array

Check warning on line 30 in src/components/ActionPanel/ActionPanel.tsx

View workflow job for this annotation

GitHub Actions / build

React Hook React.useCallback has a missing dependency: 'dragContext'. Either include it or remove the dependency array
);

const onDragEnd = React.useCallback<React.DragEventHandler<HTMLDivElement>>(
Expand All @@ -49,7 +39,7 @@ export const ActionPanelItemContainer = ({item}: {item: ActionPanelItem}) => {

let dndProps: DndProps = {};

if (item.pluginType) {
if (item.dragProps) {
dndProps = {
draggable: true,
unselectable: 'on',
Expand Down
4 changes: 3 additions & 1 deletion src/components/ActionPanel/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React from 'react';

import type {DragProps} from '../../shared';

export type ActionPanelItem = {
id: string;
icon: React.ReactNode;
title: string;
onClick?: () => void;
className?: string;
qa?: string;
pluginType?: string;
dragProps?: DragProps;
};

export type ActionPanelProps = {
Expand Down
3 changes: 2 additions & 1 deletion src/components/DashKit/DashKit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
Config,
ConfigItem,
ConfigLayout,
DragProps,
GlobalParams,
ItemsStateAndParams,
} from '../../shared';
Expand Down Expand Up @@ -36,7 +37,7 @@ interface DashKitDefaultProps {
onChange: (data: {config: Config; itemsStateAndParams: ItemsStateAndParams}) => void;
onDrop: (dropProps: {
commit: () => void;
pluginType: string;
dragProps: DragProps;
itemLayout: ConfigLayout;
newLayout: ConfigLayout[];
}) => void;
Expand Down
36 changes: 28 additions & 8 deletions src/components/DashKit/__stories__/DashKitDnDShowcase.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {ChartColumn, Heading, Sliders, TextAlignLeft} from '@gravity-ui/icons';
import {ChartColumn, Copy, Heading, Sliders, TextAlignLeft} from '@gravity-ui/icons';
import {Icon} from '@gravity-ui/uikit';

import {ActionPanel, DashKit, DashKitDnDWrapper, DashKitProps} from '../../..';
Expand Down Expand Up @@ -49,29 +49,48 @@ export const DashKitDnDShowcase: React.FC = () => {
title: 'Chart',
className: 'test',
qa: 'chart',
pluginType: 'custom',
dragProps: {
type: 'custom',
},
onClick,
},
{
id: 'selector',
icon: <Icon data={Sliders} />,
title: 'Selector',
qa: 'selector',
pluginType: 'custom',
dragProps: {
type: 'custom',
},
onClick,
},
{
id: 'text',
icon: <Icon data={TextAlignLeft} />,
title: 'Text',
pluginType: 'text',
dragProps: {
type: 'text',
},
onClick,
},
{
id: 'header',
icon: <Icon data={Heading} />,
title: 'Header',
pluginType: 'title',
dragProps: {
type: 'title',
},
onClick,
},
{
id: 'custom',
icon: <Icon data={Copy} />,
title: 'Custom',
dragProps: {
type: 'title',
h: 10,
w: 36,
},
onClick,
},
],
Expand All @@ -86,13 +105,14 @@ export const DashKitDnDShowcase: React.FC = () => {
const onDrop = React.useCallback<Exclude<DashKitProps['onDrop'], undefined>>(
(dropProps) => {
let data = null;
if (dropProps.pluginType === 'custom') {
const type = dropProps.dragProps?.type;
if (type === 'custom') {
data = {};
} else {
const text = prompt('Enter text');
if (text) {
data =
dropProps.pluginType === 'title'
type === 'title'
? {
size: 'm',
text,
Expand All @@ -106,8 +126,8 @@ export const DashKitDnDShowcase: React.FC = () => {
const newConfig = DashKit.setItem({
item: {
data,
type,
namespace: 'default',
type: dropProps.pluginType,
layout: dropProps.itemLayout,
},
config,
Expand Down
17 changes: 9 additions & 8 deletions src/components/DashKitDnDWrapper/DashKitDnDWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
import React from 'react';

import {DashKitDnDContext} from '../../context/DashKitContext';
import type {DragProps} from '../../shared';

type DashKitDnDWrapperProps = {
children: React.ReactElement;
};

export const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps> = (props) => {
const [dragPluginType, setDragPluginType] = React.useState<string | null>(null);
const [dragProps, setDragProps] = React.useState<DragProps | null>(null);

const onDragStart = React.useCallback(
(_: React.DragEvent<Element>, type: string) => {
setDragPluginType(type);
(_: React.DragEvent<Element>, currentProps: DragProps) => {
setDragProps(currentProps);
},
[setDragPluginType],
[setDragProps],
);

const onDragEnd = React.useCallback(
(_: React.DragEvent<Element>) => {
setDragPluginType(null);
setDragProps(null);
},
[setDragPluginType],
[setDragProps],
);

const contextValue = React.useMemo(() => {
return {
dragPluginType,
dragProps,
onDragStart,
onDragEnd,
};
}, [dragPluginType, onDragStart, onDragEnd]);
}, [dragProps, onDragStart, onDragEnd]);

return (
<DashKitDnDContext.Provider value={contextValue}>
Expand Down
5 changes: 3 additions & 2 deletions src/components/GridLayout/GridLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ class DragOverLayout extends ReactGridLayout {
};

processGridItem(child, isDroppingItem) {
const gridItem = super.processGridItem(child, isDroppingItem);

if (isDroppingItem) {
// Drop item from outside gets 0,0 droppingPosition
// centering cursor on newly creted grid item
// And cause grid-layout using it's own GridItem to make it look
// like overlay adding className
const gridItem = super.processGridItem(child, isDroppingItem);
if (!gridItem) return null;

const {props} = gridItem;
Expand All @@ -49,7 +50,7 @@ class DragOverLayout extends ReactGridLayout {
});
}

return super.processGridItem(child, isDroppingItem);
return gridItem;
}
}

Expand Down
28 changes: 19 additions & 9 deletions src/hocs/withContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {DashKitContext, DashKitDnDContext} from '../context/DashKitContext';
import {getItemsParams, getItemsState} from '../shared';
import {UpdateManager} from '../utils';

const DEFAULT_HEIGHT = 3;
const DEFAULT_WIDTH = 3;

function useMemoStateContext(props) {
// так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
// (видимый юзером в конкретный момент времени) лэйаут (массив объектов с данными о ширине, высоте,
Expand Down Expand Up @@ -202,12 +205,12 @@ function useMemoStateContext(props) {
pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
}, []);

const dndPluginType = dndContext?.dragPluginType;
const dragProps = dndContext?.dragProps;

const dragOverPlugin = React.useMemo(() => {
const pluginType = dndPluginType;
if (!dragProps && temporaryLayout === null) return null;

if (pluginType === null && temporaryLayout === null) return null;
const pluginType = dragProps.type;

if (props.registerManager.check(pluginType)) {
return props.registerManager.getItem(pluginType);
Expand All @@ -216,25 +219,32 @@ function useMemoStateContext(props) {
console.error(`Uknown pluginType: ${pluginType}`);
return null;
}
}, [dndPluginType, props.registerManager, temporaryLayout]);
}, [dragProps, temporaryLayout, props.registerManager]);

const onDropDragOver = React.useCallback(() => {
if (temporaryLayout) {
resetTemporaryLayout();
return false;
}

if (dragOverPlugin?.defaultLayout) {
const {h = 3, w = 3} = dragOverPlugin.defaultLayout;
if (dragOverPlugin) {
const {defaultLayout} = dragOverPlugin;
const {h = defaultLayout?.h || DEFAULT_HEIGHT, w = defaultLayout?.w || DEFAULT_WIDTH} =
dragProps;

return {h, w};
}

return false;
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin]);
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);

const onDropProp = props.onDrop;
const onDrop = React.useCallback(
(newLayout, item) => {
if (!dragProps) {
return;
}

setTemporaryLayout(newLayout);
const {i, w, h, x, y} = item;

Expand All @@ -246,11 +256,11 @@ function useMemoStateContext(props) {
return memo;
}, []),
itemLayout: {w, h, x, y},
pluginType: dndPluginType,
commit: resetTemporaryLayout,
dragProps,
});
},
[dndPluginType, onDropProp, resetTemporaryLayout],
[dragProps, onDropProp, resetTemporaryLayout],
);

return React.useMemo(
Expand Down
6 changes: 6 additions & 0 deletions src/shared/types/config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import {StringParams} from './common';

export type DragProps = {
type: string;
w?: number;
h?: number;
};

export interface ConfigLayout {
i: string;
h: number;
Expand Down

0 comments on commit c66df04

Please sign in to comment.