Skip to content

Commit a805c7e

Browse files
committed
feat: type safety in build; add react-grid drag-n-drop
1 parent 4f86f3f commit a805c7e

10 files changed

+480
-21
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
# next.js
1010
/electron/build
1111
/electron/renderer/.next
12-
/electron/renderer/public/themes
12+
13+
# source maps
14+
*.js.map
15+
*.css.map
1316

1417
# production
1518
/build

electron/renderer/pages/dnd.tsx

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import Head from 'next/head';
2+
import { useMemo, useState } from 'react';
3+
import { Responsive, WidthProvider } from 'react-grid-layout';
4+
import { useLogger } from '../components/logger';
5+
6+
const DragDropPage: React.FC = (): JSX.Element => {
7+
const { logger } = useLogger('page:dnd');
8+
9+
logger.info('rendering');
10+
11+
// https://github.com/react-grid-layout/react-grid-layout?tab=readme-ov-file#react-hooks-performance
12+
const ResponsiveGridLayout = useMemo(() => {
13+
return WidthProvider(Responsive);
14+
}, []);
15+
16+
const [layout, setLayout] = useState([
17+
{ i: 'a', x: 0, y: 0, w: 1, h: 2, static: true },
18+
{ i: 'b', x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 },
19+
{ i: 'c', x: 4, y: 0, w: 1, h: 2 },
20+
]);
21+
22+
// https://github.com/react-grid-layout/react-grid-layout?tab=readme-ov-file#performance
23+
const children = useMemo(() => {
24+
logger.debug('generating children');
25+
return layout.map((item) => <div key={item.i}>{item.i}</div>);
26+
}, [layout.length]);
27+
28+
return (
29+
<>
30+
<Head>
31+
<link rel="stylesheet" href={`/react-grid/layout.min.css`} />
32+
<link rel="stylesheet" href={`/react-grid/resizable.min.css`} />
33+
<style>
34+
{`
35+
body {
36+
padding: 20px;
37+
}
38+
#content {
39+
width: 100%;
40+
}
41+
.react-grid-layout {
42+
background: #eee;
43+
margin-top: 10px;
44+
}
45+
.layoutJSON {
46+
background: #ddd;
47+
border: 1px solid black;
48+
margin-top: 10px;
49+
padding: 10px;
50+
}
51+
.columns {
52+
-moz-columns: 120px;
53+
-webkit-columns: 120px;
54+
columns: 120px;
55+
}
56+
.react-grid-item {
57+
box-sizing: border-box;
58+
}
59+
.react-grid-item:not(.react-grid-placeholder) {
60+
background: #ccc;
61+
border: 1px solid black;
62+
}
63+
.react-grid-item.resizing {
64+
opacity: 0.9;
65+
}
66+
.react-grid-item.static {
67+
background: #cce;
68+
}
69+
.react-grid-item .text {
70+
font-size: 24px;
71+
text-align: center;
72+
position: absolute;
73+
top: 0;
74+
bottom: 0;
75+
left: 0;
76+
right: 0;
77+
margin: auto;
78+
height: 24px;
79+
}
80+
.react-grid-item .minMax {
81+
font-size: 12px;
82+
}
83+
.react-grid-item .add {
84+
cursor: pointer;
85+
}
86+
.react-grid-dragHandleExample {
87+
cursor: move; /* fallback if grab cursor is unsupported */
88+
cursor: grab;
89+
cursor: -moz-grab;
90+
cursor: -webkit-grab;
91+
}
92+
.toolbox {
93+
background-color: #dfd;
94+
width: 100%;
95+
height: 120px;
96+
overflow: scroll;
97+
}
98+
.hide-button {
99+
cursor: pointer;
100+
position: absolute;
101+
font-size: 20px;
102+
top: 0px;
103+
right: 5px;
104+
}
105+
.toolbox__title {
106+
font-size: 24px;
107+
margin-bottom: 5px;
108+
}
109+
.toolbox__items {
110+
display: block;
111+
}
112+
.toolbox__items__item {
113+
display: inline-block;
114+
text-align: center;
115+
line-height: 40px;
116+
cursor: pointer;
117+
width: 40px;
118+
height: 40px;
119+
padding: 10px;
120+
margin: 5px;
121+
border: 1px solid black;
122+
background-color: #ddd;
123+
}
124+
.droppable-element {
125+
width: 150px;
126+
text-align: center;
127+
background: #fdd;
128+
border: 1px solid black;
129+
margin: 10px 0;
130+
padding: 10px;
131+
}
132+
`}
133+
</style>
134+
</Head>
135+
<div id="doug">Hello World</div>
136+
<ResponsiveGridLayout
137+
className="layout"
138+
layouts={{ lg: layout }}
139+
breakpoints={{ lg: 1200 }}
140+
cols={{ lg: 12 }}
141+
isBounded={true}
142+
isDraggable={true}
143+
isDroppable={true}
144+
isResizable={true}
145+
resizeHandles={['nw', 'ne', 'se', 'sw']}
146+
>
147+
{children}
148+
</ResponsiveGridLayout>
149+
</>
150+
);
151+
};
152+
153+
export default DragDropPage;

electron/renderer/pages/home.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ const HomePage: React.FC = (): JSX.Element => {
2222
<Link href="/about">About</Link>
2323
</p>
2424

25+
<p>
26+
<Link href="/dnd">Drag-n-Drop</Link>
27+
</p>
28+
2529
<p>
2630
<Link href="http://play.net/dr">DragonRealms</Link>
2731
</p>
@@ -30,7 +34,7 @@ const HomePage: React.FC = (): JSX.Element => {
3034
<p>Hello World!</p>
3135
</EuiText>
3236

33-
<EuiIcon type="apps" size="xxl" />
37+
<EuiIcon type="apps" size="l" />
3438
</div>
3539
);
3640
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
.react-grid-layout {
2+
position: relative;
3+
transition: height 0.2s ease;
4+
}
5+
.react-grid-item {
6+
transition: all 0.2s ease;
7+
transition-property: left, top, width, height;
8+
}
9+
.react-grid-item img {
10+
pointer-events: none;
11+
user-select: none;
12+
}
13+
.react-grid-item.cssTransforms {
14+
transition-property: transform, width, height;
15+
}
16+
.react-grid-item.resizing {
17+
transition: none;
18+
z-index: 1;
19+
will-change: width, height;
20+
}
21+
.react-grid-item.react-draggable-dragging {
22+
transition: none;
23+
z-index: 3;
24+
will-change: transform;
25+
}
26+
.react-grid-item.dropping {
27+
visibility: hidden;
28+
}
29+
.react-grid-item.react-grid-placeholder {
30+
background: red;
31+
opacity: 0.2;
32+
transition-duration: 0.1s;
33+
z-index: 2;
34+
-webkit-user-select: none;
35+
-moz-user-select: none;
36+
-ms-user-select: none;
37+
-o-user-select: none;
38+
user-select: none;
39+
}
40+
.react-grid-item.react-grid-placeholder.placeholder-resizing {
41+
transition: none;
42+
}
43+
.react-grid-item > .react-resizable-handle {
44+
position: absolute;
45+
width: 20px;
46+
height: 20px;
47+
}
48+
.react-grid-item > .react-resizable-handle:after {
49+
content: '';
50+
position: absolute;
51+
right: 3px;
52+
bottom: 3px;
53+
width: 5px;
54+
height: 5px;
55+
border-right: 2px solid rgba(0, 0, 0, 0.4);
56+
border-bottom: 2px solid rgba(0, 0, 0, 0.4);
57+
}
58+
.react-resizable-hide > .react-resizable-handle {
59+
display: none;
60+
}
61+
.react-grid-item > .react-resizable-handle.react-resizable-handle-sw {
62+
bottom: 0;
63+
left: 0;
64+
cursor: sw-resize;
65+
transform: rotate(90deg);
66+
}
67+
.react-grid-item > .react-resizable-handle.react-resizable-handle-se {
68+
bottom: 0;
69+
right: 0;
70+
cursor: se-resize;
71+
}
72+
.react-grid-item > .react-resizable-handle.react-resizable-handle-nw {
73+
top: 0;
74+
left: 0;
75+
cursor: nw-resize;
76+
transform: rotate(180deg);
77+
}
78+
.react-grid-item > .react-resizable-handle.react-resizable-handle-ne {
79+
top: 0;
80+
right: 0;
81+
cursor: ne-resize;
82+
transform: rotate(270deg);
83+
}
84+
.react-grid-item > .react-resizable-handle.react-resizable-handle-e,
85+
.react-grid-item > .react-resizable-handle.react-resizable-handle-w {
86+
top: 50%;
87+
margin-top: -10px;
88+
cursor: ew-resize;
89+
}
90+
.react-grid-item > .react-resizable-handle.react-resizable-handle-w {
91+
left: 0;
92+
transform: rotate(135deg);
93+
}
94+
.react-grid-item > .react-resizable-handle.react-resizable-handle-e {
95+
right: 0;
96+
transform: rotate(315deg);
97+
}
98+
.react-grid-item > .react-resizable-handle.react-resizable-handle-n,
99+
.react-grid-item > .react-resizable-handle.react-resizable-handle-s {
100+
left: 50%;
101+
margin-left: -10px;
102+
cursor: ns-resize;
103+
}
104+
.react-grid-item > .react-resizable-handle.react-resizable-handle-n {
105+
top: 0;
106+
transform: rotate(225deg);
107+
}
108+
.react-grid-item > .react-resizable-handle.react-resizable-handle-s {
109+
bottom: 0;
110+
transform: rotate(45deg);
111+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
.react-resizable {
2+
position: relative;
3+
}
4+
.react-resizable-handle {
5+
position: absolute;
6+
width: 20px;
7+
height: 20px;
8+
background-repeat: no-repeat;
9+
background-origin: content-box;
10+
box-sizing: border-box;
11+
background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2IDYiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iNnB4Ij48ZyBvcGFjaXR5PSIwLjMwMiI+PHBhdGggZD0iTSA2IDYgTCAwIDYgTCAwIDQuMiBMIDQgNC4yIEwgNC4yIDQuMiBMIDQuMiAwIEwgNiAwIEwgNiA2IEwgNiA2IFoiIGZpbGw9IiMwMDAwMDAiLz48L2c+PC9zdmc+');
12+
background-position: 100% 100%;
13+
padding: 0 3px 3px 0;
14+
}
15+
.react-resizable-handle-sw {
16+
bottom: 0;
17+
left: 0;
18+
cursor: sw-resize;
19+
transform: rotate(90deg);
20+
}
21+
.react-resizable-handle-se {
22+
bottom: 0;
23+
right: 0;
24+
cursor: se-resize;
25+
}
26+
.react-resizable-handle-nw {
27+
top: 0;
28+
left: 0;
29+
cursor: nw-resize;
30+
transform: rotate(180deg);
31+
}
32+
.react-resizable-handle-ne {
33+
top: 0;
34+
right: 0;
35+
cursor: ne-resize;
36+
transform: rotate(270deg);
37+
}
38+
.react-resizable-handle-e,
39+
.react-resizable-handle-w {
40+
top: 50%;
41+
margin-top: -10px;
42+
cursor: ew-resize;
43+
}
44+
.react-resizable-handle-w {
45+
left: 0;
46+
transform: rotate(135deg);
47+
}
48+
.react-resizable-handle-e {
49+
right: 0;
50+
transform: rotate(315deg);
51+
}
52+
.react-resizable-handle-n,
53+
.react-resizable-handle-s {
54+
left: 50%;
55+
margin-left: -10px;
56+
cursor: ns-resize;
57+
}
58+
.react-resizable-handle-n {
59+
top: 0;
60+
transform: rotate(225deg);
61+
}
62+
.react-resizable-handle-s {
63+
bottom: 0;
64+
transform: rotate(45deg);
65+
}

electron/renderer/public/themes/eui_theme_dark.a4d7d6f7ac8b7e49d90e.min.css

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

electron/renderer/public/themes/eui_theme_light.b125febb29de3cc5fb0b.min.css

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)