react-align 1.1.6 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -34
- package/dist/GridArea.d.ts +18 -0
- package/dist/GridItem.d.ts +27 -0
- package/dist/{Grid/GridSection/index.d.ts → GridSection.d.ts} +4 -3
- package/dist/GridWrapper.d.ts +17 -0
- package/dist/Icon/index.d.ts +1 -1
- package/dist/context.d.ts +11 -4
- package/dist/index.d.ts +5 -5
- package/dist/react-align.cjs.development.js +225 -317
- package/dist/react-align.cjs.development.js.map +1 -1
- package/dist/react-align.cjs.production.min.js +1 -1
- package/dist/react-align.cjs.production.min.js.map +1 -1
- package/dist/react-align.esm.js +226 -318
- package/dist/react-align.esm.js.map +1 -1
- package/package.json +7 -12
- package/src/GridArea.tsx +152 -0
- package/src/GridItem.tsx +155 -0
- package/src/GridSection.tsx +53 -0
- package/src/GridWrapper.tsx +87 -0
- package/src/Icon/index.tsx +3 -3
- package/src/context.tsx +8 -4
- package/src/grid.css +80 -0
- package/src/index.tsx +5 -5
- package/dist/Grid/GridArea/index.d.ts +0 -18
- package/dist/Grid/GridItem/index.d.ts +0 -25
- package/dist/Grid/GridWrapper/index.d.ts +0 -12
- package/src/Grid/GridArea/index.tsx +0 -180
- package/src/Grid/GridItem/index.tsx +0 -266
- package/src/Grid/GridSection/index.tsx +0 -46
- package/src/Grid/GridWrapper/index.tsx +0 -39
- package/src/Grid/grid.css +0 -78
- package/src/Grid/interfaces.ts +0 -5
- package/src/stories/GridArea.stories.tsx +0 -28
package/src/Icon/index.tsx
CHANGED
|
@@ -9,8 +9,8 @@ export type IconProps = {
|
|
|
9
9
|
className?: string;
|
|
10
10
|
name: string | Icons;
|
|
11
11
|
size?: number;
|
|
12
|
+
style?: CSSProperties;
|
|
12
13
|
onClick?: () => void;
|
|
13
|
-
styles?: CSSProperties;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
const IconStyles = (size?: number) =>
|
|
@@ -28,15 +28,15 @@ const Icon: React.FC<IconProps> = ({
|
|
|
28
28
|
className,
|
|
29
29
|
name,
|
|
30
30
|
size,
|
|
31
|
+
style,
|
|
31
32
|
onClick,
|
|
32
|
-
styles,
|
|
33
33
|
}) => {
|
|
34
34
|
const LocalIconComponent = Icons[name as Icons];
|
|
35
35
|
return (
|
|
36
36
|
<LocalIconComponent
|
|
37
37
|
className={className}
|
|
38
38
|
{...IconStyles(size)}
|
|
39
|
-
style={
|
|
39
|
+
style={style}
|
|
40
40
|
onClick={onClick}
|
|
41
41
|
/>
|
|
42
42
|
);
|
package/src/context.tsx
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { createContext, useContext } from 'react';
|
|
2
|
+
import { Alignment } from '.';
|
|
2
3
|
|
|
3
|
-
export const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export const Context = createContext<{
|
|
5
|
+
editing: boolean;
|
|
6
|
+
isDragging: boolean;
|
|
7
|
+
onAlignChange?: (location: string, align: Alignment) => void;
|
|
8
|
+
onExtend?: (location: string, extended: boolean) => void;
|
|
9
|
+
}>({ editing: false, isDragging: false });
|
|
10
|
+
export const useAlignContext = () => useContext(Context);
|
package/src/grid.css
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Default component styles */
|
|
2
|
+
.wrapper {
|
|
3
|
+
height: 100%;
|
|
4
|
+
display: flex;
|
|
5
|
+
justify-content: space-between;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.section {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
justify-content: space-between;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.area {
|
|
15
|
+
display: flex;
|
|
16
|
+
border: 1px solid transparent;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
border-radius: 8px;
|
|
19
|
+
position: relative;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.area-transition-in {
|
|
23
|
+
transition: all 0.3s ease-in-out, min-height 0.5s ease-in-out 0.2s, min-width 0.5s ease-in-out 0.2s;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.area-transition-out {
|
|
27
|
+
transition: all 0.3s ease-in-out 0.4s, min-height 0.5s ease-in-out 0.2s, min-width 0.5s ease-in-out 0.2s;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.item {
|
|
31
|
+
position: relative;
|
|
32
|
+
border: 1px solid transparent;
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
margin: 6px;
|
|
35
|
+
border-radius: 6px;
|
|
36
|
+
min-width: 70px;
|
|
37
|
+
min-height: 40px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.stretch {
|
|
41
|
+
flex: auto;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.middle {
|
|
45
|
+
flex-grow: 0;
|
|
46
|
+
flex: auto;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.just-centered {
|
|
50
|
+
justify-content: center;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.just-end {
|
|
54
|
+
justify-content: flex-end;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.end {
|
|
58
|
+
align-items:flex-end;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.hide {
|
|
62
|
+
display: none;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.overlay {
|
|
66
|
+
position: absolute;
|
|
67
|
+
top: 0;
|
|
68
|
+
left: 0;
|
|
69
|
+
bottom: 0;
|
|
70
|
+
right: 0;
|
|
71
|
+
box-sizing: border-box;
|
|
72
|
+
background: rgba(0,0,0,0.6);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.overlay-buttons {
|
|
76
|
+
display: flex;
|
|
77
|
+
padding: 6px;
|
|
78
|
+
box-sizing: border-box;
|
|
79
|
+
justify-content: space-between;
|
|
80
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { default as GridWrapper } from "./
|
|
2
|
-
export { default as GridSection } from "./
|
|
3
|
-
export { default as GridArea } from "./
|
|
4
|
-
export { default as GridItem } from "./
|
|
1
|
+
export { default as GridWrapper } from "./GridWrapper";
|
|
2
|
+
export { default as GridSection } from "./GridSection";
|
|
3
|
+
export { default as GridArea } from "./GridArea";
|
|
4
|
+
export { default as GridItem } from "./GridItem";
|
|
5
5
|
export { default as Icon } from "./Icon";
|
|
6
6
|
|
|
7
7
|
// eslint-disable-next-line prettier/prettier
|
|
8
|
-
export type { Alignment } from "./
|
|
8
|
+
export type { Alignment } from "./GridArea";
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { CSSProperties, PropsWithChildren } from 'react';
|
|
2
|
-
import '../grid.css';
|
|
3
|
-
export declare type Alignment = 'start' | 'end' | 'centered';
|
|
4
|
-
export declare type AreaProps<T = unknown> = {
|
|
5
|
-
className?: string;
|
|
6
|
-
vertical?: boolean;
|
|
7
|
-
reverse?: boolean;
|
|
8
|
-
stretch?: boolean;
|
|
9
|
-
end?: boolean;
|
|
10
|
-
droppable?: boolean;
|
|
11
|
-
align?: Alignment;
|
|
12
|
-
location: T;
|
|
13
|
-
styles?: CSSProperties;
|
|
14
|
-
editorStyles?: CSSProperties;
|
|
15
|
-
iconColor?: string;
|
|
16
|
-
onAlignChange?: (a: Alignment) => void;
|
|
17
|
-
};
|
|
18
|
-
export default function GridArea<T = unknown>({ className, vertical, reverse, stretch, end, droppable, align, onAlignChange, location, children, styles, editorStyles, iconColor, }: PropsWithChildren<AreaProps<T>>): JSX.Element;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { CSSProperties, PropsWithChildren } from 'react';
|
|
2
|
-
import '../grid.css';
|
|
3
|
-
export declare type ItemProps<T = unknown> = {
|
|
4
|
-
className?: string;
|
|
5
|
-
id: string;
|
|
6
|
-
index: number;
|
|
7
|
-
extendable?: boolean;
|
|
8
|
-
extended?: boolean;
|
|
9
|
-
draggable?: boolean;
|
|
10
|
-
onReorder: (id: string, originalLocation: T, currentIndex: number, hoverIndex: number) => void;
|
|
11
|
-
onMoveArea: (currentItem: string, dropLocation: T, originalLocation: T) => void;
|
|
12
|
-
onExtend?: (id: string, extended: boolean) => void;
|
|
13
|
-
location: T;
|
|
14
|
-
end?: boolean;
|
|
15
|
-
vertical?: boolean;
|
|
16
|
-
styles?: CSSProperties;
|
|
17
|
-
editorStyles?: CSSProperties;
|
|
18
|
-
iconSize?: number;
|
|
19
|
-
iconColor?: string;
|
|
20
|
-
};
|
|
21
|
-
export declare const ItemType: {
|
|
22
|
-
ITEM: string;
|
|
23
|
-
GROUP: string;
|
|
24
|
-
};
|
|
25
|
-
export default function GridItem<T = unknown>({ className, children, id, index, extendable, extended, draggable, onReorder, onMoveArea, onExtend, location, end, vertical, styles, editorStyles, iconSize, iconColor, }: PropsWithChildren<ItemProps<T>>): JSX.Element;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React, { CSSProperties } from 'react';
|
|
2
|
-
import '../grid.css';
|
|
3
|
-
export declare type GridWrapperProps = {
|
|
4
|
-
className?: string;
|
|
5
|
-
enabled?: boolean;
|
|
6
|
-
vertical?: boolean;
|
|
7
|
-
stretch?: boolean;
|
|
8
|
-
styles?: CSSProperties;
|
|
9
|
-
editorStyles?: CSSProperties;
|
|
10
|
-
};
|
|
11
|
-
declare const GridWrapper: React.FC<GridWrapperProps>;
|
|
12
|
-
export default GridWrapper;
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
CSSProperties,
|
|
3
|
-
PropsWithChildren,
|
|
4
|
-
useCallback,
|
|
5
|
-
useMemo,
|
|
6
|
-
} from 'react';
|
|
7
|
-
import { useDrop, DropTargetMonitor } from 'react-dnd';
|
|
8
|
-
import { ItemProps } from '../GridItem';
|
|
9
|
-
import { useEditorMode } from '../../context';
|
|
10
|
-
import Icon from '../../Icon';
|
|
11
|
-
import '../grid.css';
|
|
12
|
-
|
|
13
|
-
import { ItemType } from '../GridItem';
|
|
14
|
-
|
|
15
|
-
export type Alignment = 'start' | 'end' | 'centered';
|
|
16
|
-
|
|
17
|
-
export type AreaProps<T = unknown> = {
|
|
18
|
-
className?: string;
|
|
19
|
-
vertical?: boolean;
|
|
20
|
-
reverse?: boolean;
|
|
21
|
-
stretch?: boolean;
|
|
22
|
-
end?: boolean;
|
|
23
|
-
droppable?: boolean; // optional to override editorMode context (enabled param passed to GridWrapper) **Needs to be accompanied with GridItems draggable prop**
|
|
24
|
-
align?: Alignment;
|
|
25
|
-
location: T;
|
|
26
|
-
// Extra customizable parts only for the really picky
|
|
27
|
-
styles?: CSSProperties;
|
|
28
|
-
editorStyles?: CSSProperties;
|
|
29
|
-
iconColor?: string;
|
|
30
|
-
onAlignChange?: (a: Alignment) => void;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export default function GridArea<T = unknown>({
|
|
34
|
-
className,
|
|
35
|
-
vertical,
|
|
36
|
-
reverse,
|
|
37
|
-
stretch,
|
|
38
|
-
end,
|
|
39
|
-
droppable,
|
|
40
|
-
align,
|
|
41
|
-
onAlignChange,
|
|
42
|
-
location,
|
|
43
|
-
children,
|
|
44
|
-
// Picky stuff
|
|
45
|
-
styles,
|
|
46
|
-
editorStyles,
|
|
47
|
-
iconColor = '#FFFFFF',
|
|
48
|
-
}: PropsWithChildren<AreaProps<T>>) {
|
|
49
|
-
const { enabled } = useEditorMode();
|
|
50
|
-
|
|
51
|
-
const handleAlignChange = useCallback(
|
|
52
|
-
(align: Alignment) => {
|
|
53
|
-
switch (align) {
|
|
54
|
-
case 'start':
|
|
55
|
-
onAlignChange?.('centered');
|
|
56
|
-
break;
|
|
57
|
-
case 'centered':
|
|
58
|
-
onAlignChange?.('end');
|
|
59
|
-
break;
|
|
60
|
-
default:
|
|
61
|
-
onAlignChange?.('start');
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
[onAlignChange]
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
// ***************************************
|
|
69
|
-
// Drop logic
|
|
70
|
-
const [{ isOver }, drop] = useDrop(() => ({
|
|
71
|
-
accept: [ItemType.ITEM, ItemType.GROUP],
|
|
72
|
-
drop: () => ({ location: location }),
|
|
73
|
-
collect: (monitor: DropTargetMonitor) => ({
|
|
74
|
-
isOver: monitor.isOver(),
|
|
75
|
-
}),
|
|
76
|
-
}));
|
|
77
|
-
// ***************************************
|
|
78
|
-
|
|
79
|
-
// ***************************************
|
|
80
|
-
// Internal styles used
|
|
81
|
-
const buttonStyle: CSSProperties = useMemo(
|
|
82
|
-
() => ({
|
|
83
|
-
position: 'absolute',
|
|
84
|
-
left: vertical ? (end ? 0 : undefined) : '50%',
|
|
85
|
-
right: vertical ? (!end ? 0 : undefined) : '50%',
|
|
86
|
-
bottom: !vertical && !end ? 0 : vertical ? '50%' : undefined,
|
|
87
|
-
top: vertical ? '50%' : end ? 0 : undefined,
|
|
88
|
-
opacity: (droppable ?? enabled) && align ? 1 : 0,
|
|
89
|
-
transition: 'all 0.5s ease-in-out',
|
|
90
|
-
}),
|
|
91
|
-
[vertical, end, droppable, enabled, align]
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
const mainStyles: CSSProperties = useMemo(
|
|
95
|
-
() => ({
|
|
96
|
-
opacity: isOver ? 0.8 : 1,
|
|
97
|
-
minHeight: !React.Children.count(children) && !enabled ? '0px' : '26px',
|
|
98
|
-
minWidth: !React.Children.count(children) && !enabled ? '0px' : '46px',
|
|
99
|
-
}),
|
|
100
|
-
[isOver, children, enabled]
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const stylesFromProps: CSSProperties | undefined = enabled
|
|
104
|
-
? editorStyles
|
|
105
|
-
: styles;
|
|
106
|
-
// ***************************************
|
|
107
|
-
|
|
108
|
-
// Rebuilds the GridItem children to receive their parent GridArea's 'end' and 'vertical' values.
|
|
109
|
-
// Used to know where to align the overlay buttons (end) and how to extend the GridItems (vertical).
|
|
110
|
-
const childrenWithParentProps = React.Children.map(children, child =>
|
|
111
|
-
React.cloneElement(child as React.ReactElement<ItemProps<T>>, {
|
|
112
|
-
end,
|
|
113
|
-
vertical,
|
|
114
|
-
location,
|
|
115
|
-
})
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
return (
|
|
119
|
-
<div
|
|
120
|
-
ref={drop}
|
|
121
|
-
className={`
|
|
122
|
-
${className}
|
|
123
|
-
area
|
|
124
|
-
${stretch && 'stretch'}
|
|
125
|
-
${end && 'end'}
|
|
126
|
-
${
|
|
127
|
-
align === 'centered'
|
|
128
|
-
? 'just-centered'
|
|
129
|
-
: align === 'end'
|
|
130
|
-
? 'just-end'
|
|
131
|
-
: 'start'
|
|
132
|
-
}
|
|
133
|
-
${
|
|
134
|
-
vertical
|
|
135
|
-
? reverse
|
|
136
|
-
? 'vertical-r'
|
|
137
|
-
: 'vertical'
|
|
138
|
-
: reverse
|
|
139
|
-
? 'horizontal-r'
|
|
140
|
-
: 'horizontal'
|
|
141
|
-
}
|
|
142
|
-
${enabled ? 'area-transition-in' : 'area-transition-out'}
|
|
143
|
-
`}
|
|
144
|
-
style={{ ...mainStyles, ...stylesFromProps }}
|
|
145
|
-
>
|
|
146
|
-
{childrenWithParentProps}
|
|
147
|
-
<div style={buttonStyle}>
|
|
148
|
-
<Icon
|
|
149
|
-
name={
|
|
150
|
-
align === 'centered'
|
|
151
|
-
? vertical
|
|
152
|
-
? 'alignCenterV'
|
|
153
|
-
: 'alignCenter'
|
|
154
|
-
: align === 'end'
|
|
155
|
-
? vertical
|
|
156
|
-
? 'alignEndV'
|
|
157
|
-
: 'alignEnd'
|
|
158
|
-
: vertical
|
|
159
|
-
? 'alignStartV'
|
|
160
|
-
: 'alignStart'
|
|
161
|
-
}
|
|
162
|
-
styles={{
|
|
163
|
-
color: iconColor,
|
|
164
|
-
cursor:
|
|
165
|
-
(droppable ?? enabled) &&
|
|
166
|
-
align &&
|
|
167
|
-
!!React.Children.count(children)
|
|
168
|
-
? 'pointer'
|
|
169
|
-
: 'default',
|
|
170
|
-
}}
|
|
171
|
-
onClick={
|
|
172
|
-
(droppable ?? enabled) && align && !!React.Children.count(children)
|
|
173
|
-
? () => handleAlignChange(align)
|
|
174
|
-
: undefined
|
|
175
|
-
}
|
|
176
|
-
/>
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
);
|
|
180
|
-
}
|
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
useMemo,
|
|
3
|
-
useRef,
|
|
4
|
-
CSSProperties,
|
|
5
|
-
useState,
|
|
6
|
-
PropsWithChildren,
|
|
7
|
-
} from 'react';
|
|
8
|
-
import { useDrag, useDrop, DragSourceMonitor } from 'react-dnd';
|
|
9
|
-
import { useEditorMode } from '../../context';
|
|
10
|
-
import { DragItem } from '../interfaces';
|
|
11
|
-
|
|
12
|
-
import Icon from '../../Icon';
|
|
13
|
-
|
|
14
|
-
import '../grid.css';
|
|
15
|
-
|
|
16
|
-
export type ItemProps<T = unknown> = {
|
|
17
|
-
className?: string;
|
|
18
|
-
id: string;
|
|
19
|
-
index: number;
|
|
20
|
-
extendable?: boolean;
|
|
21
|
-
extended?: boolean;
|
|
22
|
-
draggable?: boolean; // Optional to override or not use editorMode context. **Needs to be accompanied with GridAreas droppable prop**
|
|
23
|
-
onReorder: (
|
|
24
|
-
id: string,
|
|
25
|
-
originalLocation: T,
|
|
26
|
-
currentIndex: number,
|
|
27
|
-
hoverIndex: number
|
|
28
|
-
) => void;
|
|
29
|
-
onMoveArea: (
|
|
30
|
-
currentItem: string,
|
|
31
|
-
dropLocation: T,
|
|
32
|
-
originalLocation: T
|
|
33
|
-
) => void;
|
|
34
|
-
onExtend?: (id: string, extended: boolean) => void;
|
|
35
|
-
// Props passed from parent.
|
|
36
|
-
location: T;
|
|
37
|
-
end?: boolean;
|
|
38
|
-
vertical?: boolean;
|
|
39
|
-
// Extra customizable parts only for the really picky.
|
|
40
|
-
styles?: CSSProperties;
|
|
41
|
-
editorStyles?: CSSProperties;
|
|
42
|
-
iconSize?: number;
|
|
43
|
-
iconColor?: string;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const ItemType = {
|
|
47
|
-
ITEM: 'react-align_item',
|
|
48
|
-
GROUP: 'react-align_group',
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export default function GridItem<T = unknown>({
|
|
52
|
-
className,
|
|
53
|
-
children,
|
|
54
|
-
id,
|
|
55
|
-
index,
|
|
56
|
-
extendable,
|
|
57
|
-
extended,
|
|
58
|
-
draggable,
|
|
59
|
-
onReorder,
|
|
60
|
-
onMoveArea,
|
|
61
|
-
onExtend,
|
|
62
|
-
// Passed from parent (aka GridArea).
|
|
63
|
-
location,
|
|
64
|
-
end,
|
|
65
|
-
vertical,
|
|
66
|
-
// Picky stuff.
|
|
67
|
-
styles,
|
|
68
|
-
editorStyles,
|
|
69
|
-
iconSize,
|
|
70
|
-
iconColor = 'rgb(255, 255, 255)',
|
|
71
|
-
}: PropsWithChildren<ItemProps<T>>) {
|
|
72
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
73
|
-
const { enabled } = useEditorMode();
|
|
74
|
-
|
|
75
|
-
const [isHovered, setHovered] = useState(false);
|
|
76
|
-
const dragIndexRef = useRef<number | undefined>();
|
|
77
|
-
|
|
78
|
-
const handleExtend = () => {
|
|
79
|
-
if (!extendable || !onExtend) return;
|
|
80
|
-
setHovered(false);
|
|
81
|
-
onExtend(id, !extended);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// ***************************************
|
|
85
|
-
// Drag n drop logic
|
|
86
|
-
const [{ handlerId }, drop] = useDrop({
|
|
87
|
-
accept: [ItemType.ITEM, ItemType.GROUP],
|
|
88
|
-
collect(monitor) {
|
|
89
|
-
return {
|
|
90
|
-
handlerId: monitor.getHandlerId(),
|
|
91
|
-
};
|
|
92
|
-
},
|
|
93
|
-
hover(item: DragItem, monitor) {
|
|
94
|
-
if (!ref.current || !enabled || draggable) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const dragIndex = item.index;
|
|
99
|
-
const hoverIndex = index;
|
|
100
|
-
|
|
101
|
-
if (dragIndex === hoverIndex) {
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const hoverBoundingRect = ref.current?.getBoundingClientRect();
|
|
106
|
-
|
|
107
|
-
const hoverMiddleY =
|
|
108
|
-
(hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
|
|
109
|
-
const hoverMiddleX =
|
|
110
|
-
(hoverBoundingRect.right - hoverBoundingRect.left) / 2;
|
|
111
|
-
|
|
112
|
-
const clientOffset = monitor.getClientOffset();
|
|
113
|
-
if (!clientOffset) return;
|
|
114
|
-
|
|
115
|
-
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
|
|
116
|
-
const hoverClientX = clientOffset.x - hoverBoundingRect.left;
|
|
117
|
-
|
|
118
|
-
if (vertical) {
|
|
119
|
-
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
if (dragIndex < hoverIndex && hoverClientX < hoverMiddleX) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (dragIndex > hoverIndex && hoverClientX > hoverMiddleX) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
dragIndexRef.current = dragIndex;
|
|
137
|
-
},
|
|
138
|
-
drop(item) {
|
|
139
|
-
if (dragIndexRef.current !== undefined) {
|
|
140
|
-
onReorder(item.id, location, dragIndexRef.current, index);
|
|
141
|
-
dragIndexRef.current = undefined;
|
|
142
|
-
}
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
const [{ isDragging }, drag, preview] = useDrag(
|
|
147
|
-
{
|
|
148
|
-
type: ItemType.ITEM,
|
|
149
|
-
item: { id, index },
|
|
150
|
-
canDrag: draggable ?? enabled,
|
|
151
|
-
end: (item, monitor) => {
|
|
152
|
-
const dropResults: {
|
|
153
|
-
location: T;
|
|
154
|
-
} | null = monitor.getDropResult();
|
|
155
|
-
|
|
156
|
-
if (dropResults && dropResults.location !== location) {
|
|
157
|
-
onMoveArea(item.id, dropResults.location, location);
|
|
158
|
-
}
|
|
159
|
-
},
|
|
160
|
-
collect: (monitor: DragSourceMonitor) => ({
|
|
161
|
-
isDragging: monitor.isDragging(),
|
|
162
|
-
}),
|
|
163
|
-
},
|
|
164
|
-
[dragIndexRef]
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
preview(drop(ref));
|
|
168
|
-
// ***************************************
|
|
169
|
-
|
|
170
|
-
// ***************************************
|
|
171
|
-
// External styles for editorMode or the vanilla grid
|
|
172
|
-
const stylesFromProps: CSSProperties | undefined = enabled
|
|
173
|
-
? editorStyles
|
|
174
|
-
: styles;
|
|
175
|
-
|
|
176
|
-
const itemStyles: CSSProperties = useMemo(
|
|
177
|
-
() => ({
|
|
178
|
-
opacity: isDragging ? 0.5 : 1,
|
|
179
|
-
minHeight: isHovered && enabled ? '40px' : undefined,
|
|
180
|
-
width: !vertical && extended ? '100%' : undefined,
|
|
181
|
-
minWidth:
|
|
182
|
-
isHovered && enabled ? (extendable ? '70px' : '30px') : undefined,
|
|
183
|
-
height: vertical && extended ? '100%' : undefined,
|
|
184
|
-
}),
|
|
185
|
-
[isDragging, isHovered, enabled, vertical, extended, extendable]
|
|
186
|
-
);
|
|
187
|
-
|
|
188
|
-
const containerStyle: CSSProperties = useMemo(
|
|
189
|
-
() => ({
|
|
190
|
-
position: 'relative',
|
|
191
|
-
display: 'inline-block',
|
|
192
|
-
minHeight: isHovered && enabled ? '40px' : undefined,
|
|
193
|
-
width: !vertical && extended ? '100%' : undefined,
|
|
194
|
-
minWidth:
|
|
195
|
-
isHovered && enabled ? (extendable ? '70px' : '30px') : undefined,
|
|
196
|
-
height: vertical && extended ? '100%' : undefined,
|
|
197
|
-
}),
|
|
198
|
-
[isHovered, enabled, vertical, extended, extendable]
|
|
199
|
-
);
|
|
200
|
-
|
|
201
|
-
const overlayStyles: CSSProperties = {
|
|
202
|
-
position: 'absolute',
|
|
203
|
-
top: '0',
|
|
204
|
-
left: '0',
|
|
205
|
-
width: '100%',
|
|
206
|
-
height: '100%',
|
|
207
|
-
boxSizing: 'border-box',
|
|
208
|
-
background: 'rgba(0,0,0,0.6)',
|
|
209
|
-
borderRadius: '6px',
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
const buttonStyles: CSSProperties = useMemo(
|
|
213
|
-
() => ({
|
|
214
|
-
display: 'flex',
|
|
215
|
-
alignItems: end ? 'end' : 'start',
|
|
216
|
-
justifyContent: 'space-between',
|
|
217
|
-
padding: '6px',
|
|
218
|
-
float: end ? 'right' : 'left',
|
|
219
|
-
}),
|
|
220
|
-
[end]
|
|
221
|
-
);
|
|
222
|
-
// ***************************************
|
|
223
|
-
|
|
224
|
-
const childrenWithParentProps = React.Children.map(children, child =>
|
|
225
|
-
React.cloneElement(child as React.ReactElement<{ extended: boolean }>, {
|
|
226
|
-
extended: extended,
|
|
227
|
-
})
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
return (
|
|
231
|
-
<div
|
|
232
|
-
id={id}
|
|
233
|
-
ref={ref}
|
|
234
|
-
data-handler-id={handlerId}
|
|
235
|
-
className={`${className} item`}
|
|
236
|
-
style={{ ...itemStyles, ...stylesFromProps }}
|
|
237
|
-
onMouseEnter={() => setHovered(true)}
|
|
238
|
-
onMouseLeave={() => setHovered(false)}
|
|
239
|
-
>
|
|
240
|
-
<div style={containerStyle}>
|
|
241
|
-
{(draggable ?? enabled) && isHovered && (
|
|
242
|
-
<div style={overlayStyles}>
|
|
243
|
-
<div style={buttonStyles}>
|
|
244
|
-
<div ref={drag}>
|
|
245
|
-
<Icon
|
|
246
|
-
name="moveArrows"
|
|
247
|
-
size={iconSize}
|
|
248
|
-
styles={{ color: iconColor }}
|
|
249
|
-
/>
|
|
250
|
-
</div>
|
|
251
|
-
{extendable && (
|
|
252
|
-
<Icon
|
|
253
|
-
name={vertical ? 'verticalExtend' : 'horizontalExtend'}
|
|
254
|
-
size={iconSize}
|
|
255
|
-
styles={{ color: iconColor, marginLeft: '8px' }}
|
|
256
|
-
onClick={handleExtend}
|
|
257
|
-
/>
|
|
258
|
-
)}
|
|
259
|
-
</div>
|
|
260
|
-
</div>
|
|
261
|
-
)}
|
|
262
|
-
{childrenWithParentProps}
|
|
263
|
-
</div>
|
|
264
|
-
</div>
|
|
265
|
-
);
|
|
266
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import React, { CSSProperties } from 'react';
|
|
2
|
-
import { useEditorMode } from '../../context';
|
|
3
|
-
import '../grid.css';
|
|
4
|
-
|
|
5
|
-
export type GridSectionProps = {
|
|
6
|
-
className?: string;
|
|
7
|
-
horizontal?: boolean;
|
|
8
|
-
stretch?: boolean;
|
|
9
|
-
fixedWidth?: number;
|
|
10
|
-
fixedHeight?: number;
|
|
11
|
-
// Extra customizable parts only for the really picky
|
|
12
|
-
styles?: CSSProperties;
|
|
13
|
-
editorStyles?: CSSProperties;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const GridSection: React.FC<GridSectionProps> = ({
|
|
17
|
-
className,
|
|
18
|
-
horizontal,
|
|
19
|
-
stretch,
|
|
20
|
-
fixedWidth,
|
|
21
|
-
fixedHeight,
|
|
22
|
-
styles,
|
|
23
|
-
editorStyles,
|
|
24
|
-
children,
|
|
25
|
-
}) => {
|
|
26
|
-
const { enabled } = useEditorMode();
|
|
27
|
-
const stylesFromProps: CSSProperties | undefined = enabled
|
|
28
|
-
? editorStyles
|
|
29
|
-
: styles;
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<div
|
|
33
|
-
className={`section ${className} ${horizontal &&
|
|
34
|
-
'horizontal'} ${stretch && 'stretch'}`}
|
|
35
|
-
style={{
|
|
36
|
-
...stylesFromProps,
|
|
37
|
-
height: fixedHeight + 'px',
|
|
38
|
-
width: fixedWidth + 'px',
|
|
39
|
-
}}
|
|
40
|
-
>
|
|
41
|
-
{children}
|
|
42
|
-
</div>
|
|
43
|
-
);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export default GridSection;
|