Skip to content

Commit 7fc2570

Browse files
committed
Fix: prevent sidebar item rename from toggling open state
1 parent 9fe97bc commit 7fc2570

File tree

4 files changed

+335
-275
lines changed

4 files changed

+335
-275
lines changed

src/commons/sidebar/collections/collection_item.tsx

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import useRequestStore from "@src/stores/request_store";
21
import * as stylex from "@stylexjs/stylex";
2+
import { styles } from "./styles";
3+
4+
import useRequestStore from "@src/stores/request_store";
35

46
import RecursiveTree from "./recursive_tree";
57

@@ -19,52 +21,6 @@ import {
1921
Label,
2022
} from "@controlkit/ui";
2123

22-
const styles = stylex.create({
23-
row: {
24-
padding: "0.0625rem 0",
25-
26-
cursor: "pointer",
27-
28-
borderLeft: "0.125rem solid transparent",
29-
30-
// transition: "background-color var(--transition-speed) ease",
31-
32-
":hover": {
33-
backgroundColor: "#0E0F10",
34-
},
35-
},
36-
37-
rowActive: {
38-
backgroundColor: "#1F252D",
39-
borderLeft: "0.125rem solid #2558BC",
40-
},
41-
42-
title_input: {
43-
color: "#A6A6A6",
44-
fontSize: "0.875rem",
45-
textWrap: "nowrap",
46-
overflow: "hidden",
47-
textOverflow: "ellipsis",
48-
fontWeight: "bold",
49-
backgroundColor: "transparent",
50-
border: "none",
51-
outline: "none",
52-
cursor: "pointer",
53-
},
54-
55-
title_input_active: {
56-
color: "var(--text-color)",
57-
fontSize: "0.875rem",
58-
textWrap: "nowrap",
59-
overflow: "hidden",
60-
textOverflow: "ellipsis",
61-
fontWeight: "bold",
62-
backgroundColor: "var(--background-sub)",
63-
border: "0.0625rem solid var(--cds-blue-300)",
64-
outline: "none",
65-
},
66-
});
67-
6824
export default function CollectionItem(props: any) {
6925
const item = props.item;
7026
const original_name = useRef<string>(item.name);
@@ -185,6 +141,10 @@ export default function CollectionItem(props: any) {
185141
setRenaming(false);
186142
}
187143
}}
144+
onClick={(e) => {
145+
// e.preventDefault();
146+
e.stopPropagation();
147+
}}
188148
/>
189149
) : (
190150
<p {...stylex.props(styles.title_input)}>{item.name}</p>
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
import * as stylex from "@stylexjs/stylex";
2+
import { styles } from "./styles";
3+
import useRequestStore from "@src/stores/request_store";
4+
5+
import RecursiveTree from "./recursive_tree";
6+
7+
import { useRef, useState } from "react";
8+
9+
import ArrowRightSVG from "../../../assets/arrow-right.svg?react";
10+
import ArrowDownSVG from "../../../assets/arrow-down.svg?react";
11+
import MoreHorSVG from "../../../assets/more-hor.svg?react";
12+
import FolderSVG from "../../../assets/folder.svg?react";
13+
14+
import {
15+
Button,
16+
ButtonVariants,
17+
DropdownMenu,
18+
DropdownMenuContent,
19+
DropdownMenuItem,
20+
DropdownMenuTrigger,
21+
Label,
22+
} from "@controlkit/ui";
23+
24+
export default function FolderItem(props: any) {
25+
const item = props.item;
26+
const original_name = useRef<string>(item.name);
27+
28+
const collection = useRequestStore((state) => state.collection);
29+
const setCollection = useRequestStore((state) => state.setCollection);
30+
31+
const addFolder = useRequestStore((state) => state.addFolder);
32+
const addRequest = useRequestStore((state) => state.addRequest);
33+
const deleteItem = useRequestStore((state) => state.deleteItem);
34+
35+
const [_isHoveredFolder, setIsHoveredFolder] = useState<boolean>(false);
36+
const [_isHoveredOther, setIsHoveredOther] = useState<boolean>(false);
37+
38+
const [renaming, setRenaming] = useState<boolean>(false);
39+
40+
function updateTargetIfExists(
41+
nc: any,
42+
id: string,
43+
field: string,
44+
value: any,
45+
) {
46+
for (let i = 0; i < nc.length; ++i) {
47+
// console.log("NC", nc[i].id);
48+
49+
if (nc[i].id === id) {
50+
nc[i][field] = value;
51+
// console.log("FOUND", nc[i]);
52+
return;
53+
}
54+
55+
if (nc[i].items) {
56+
updateTargetIfExists(nc[i].items, id, field, value);
57+
}
58+
}
59+
}
60+
61+
function toggleField(id: string, field: string, value: any) {
62+
const nc = structuredClone(collection);
63+
// console.log("START", id, nc);
64+
updateTargetIfExists(nc, id, field, value);
65+
// console.log("END", nc);
66+
setCollection(nc);
67+
}
68+
69+
return (
70+
<div>
71+
<div {...stylex.props(styles.row)}>
72+
<div
73+
style={{
74+
display: "grid",
75+
gridTemplateColumns: "1fr 1.5rem",
76+
}}
77+
>
78+
{/* biome-ignore lint/a11y/useKeyWithClickEvents: <explanation> */}
79+
<div
80+
style={{
81+
display: "grid",
82+
gridTemplateColumns: "0.75rem 1rem 1fr",
83+
gap: "0.5rem",
84+
alignItems: "center",
85+
padding: "0.125rem 0.5rem",
86+
marginLeft: `${props.depth * 0.75}rem`,
87+
}}
88+
onClick={(e) => {
89+
e.preventDefault();
90+
e.stopPropagation();
91+
92+
toggleField(item.id, "open", !item.open);
93+
}}
94+
onMouseEnter={(e) => {
95+
e.preventDefault();
96+
e.stopPropagation();
97+
98+
setIsHoveredFolder(true);
99+
}}
100+
onMouseLeave={(e) => {
101+
e.preventDefault();
102+
e.stopPropagation();
103+
104+
setIsHoveredFolder(false);
105+
}}
106+
>
107+
{/* <ArrowRightSVG width={8} height={12} /> */}
108+
{/* biome-ignore lint/a11y/useKeyWithClickEvents: <explanation> */}
109+
<div
110+
// onClick={() => {
111+
// toggleField(item.id, "open", !item.open);
112+
// }}
113+
// // biome-ignore lint/a11y/useSemanticElements: <explanation>
114+
// role="button"
115+
// tabIndex={0}
116+
>
117+
{item.open ? (
118+
<ArrowDownSVG width={12} height={12} />
119+
) : (
120+
<ArrowRightSVG width={12} height={12} />
121+
)}
122+
</div>
123+
124+
<FolderSVG width={14} height={14} />
125+
126+
{renaming ? (
127+
<input
128+
{...stylex.props(styles.title_input_active)}
129+
value={item.name}
130+
onChange={(e) => {
131+
toggleField(item.id, "name", e.target.value);
132+
}}
133+
onKeyDown={(e) => {
134+
if (e.key === "Enter") {
135+
setRenaming(false);
136+
return;
137+
}
138+
139+
if (e.key === "Escape") {
140+
toggleField(item.id, "name", original_name.current);
141+
setRenaming(false);
142+
}
143+
}}
144+
onClick={(e) => {
145+
// e.preventDefault();
146+
e.stopPropagation();
147+
}}
148+
/>
149+
) : (
150+
<p {...stylex.props(styles.title_input)}>{item.name}</p>
151+
)}
152+
</div>
153+
154+
{/* biome-ignore lint/a11y/useKeyWithClickEvents: <explanation> */}
155+
{/* <div
156+
onClick={() => {
157+
toggleField(item.id, "favorite", !item.favorite);
158+
}}
159+
// biome-ignore lint/a11y/useSemanticElements: <explanation>
160+
role="button"
161+
tabIndex={0}
162+
>
163+
{item.favorite ? (
164+
<FavoriteSVG width={15} height={15} />
165+
) : (
166+
<FavoriteInactiveSVG width={15} height={15} />
167+
)}
168+
</div> */}
169+
170+
<div>
171+
{/* {isHoveredFolder ? ( */}
172+
{true ? (
173+
<DropdownMenu>
174+
<DropdownMenuTrigger asChild>
175+
<div
176+
style={{
177+
// backgroundColor: "red",
178+
display: "grid",
179+
placeItems: "center",
180+
height: "100%",
181+
// borderRadius: "0.25rem",
182+
padding: "0 0.125rem",
183+
zIndex: 1000,
184+
}}
185+
>
186+
<MoreHorSVG width={16} />
187+
</div>
188+
</DropdownMenuTrigger>
189+
<DropdownMenuContent align="end">
190+
{/* <DropdownMenuItem>Share</DropdownMenuItem> */}
191+
{/* <DropdownMenuItem>Open In Tab</DropdownMenuItem> */}
192+
{/* <DropdownMenuItem>Add Example</DropdownMenuItem> */}
193+
{/* <DropdownMenuItem>View Documentation</DropdownMenuItem> */}
194+
{/* <DropdownMenuItem>View Info</DropdownMenuItem> */}
195+
{/* <DropdownMenuItem>Add Pre-Run</DropdownMenuItem> */}
196+
<DropdownMenuItem
197+
onClick={() => {
198+
setRenaming(true);
199+
}}
200+
>
201+
Rename
202+
</DropdownMenuItem>
203+
204+
<DropdownMenuItem
205+
onClick={() => {
206+
addFolder(item.id);
207+
}}
208+
>
209+
Add Folder
210+
</DropdownMenuItem>
211+
212+
<DropdownMenuItem
213+
onClick={() => {
214+
addRequest(item.id);
215+
}}
216+
>
217+
Add Request
218+
</DropdownMenuItem>
219+
{/* <DropdownMenuItem>Rename</DropdownMenuItem>
220+
<DropdownMenuItem>Duplicate</DropdownMenuItem>
221+
<DropdownMenuItem>Paste</DropdownMenuItem> */}
222+
<DropdownMenuItem
223+
onClick={() => {
224+
deleteItem(item.id);
225+
}}
226+
>
227+
Delete
228+
</DropdownMenuItem>
229+
</DropdownMenuContent>
230+
</DropdownMenu>
231+
) : (
232+
<div />
233+
)}
234+
</div>
235+
</div>
236+
</div>
237+
238+
{item.open && (
239+
// biome-ignore lint/complexity/noUselessFragments: <explanation>
240+
<>
241+
{item.items.length > 0 ? (
242+
<RecursiveTree data={item.items} depth={props.depth + 1} />
243+
) : (
244+
<div
245+
style={{
246+
marginLeft: `${props.depth * 0.75}rem`,
247+
}}
248+
>
249+
<Label
250+
style={{
251+
marginLeft: "1rem",
252+
fontSize: "0.75rem",
253+
color: "var(--text-sub)",
254+
}}
255+
>
256+
This folder is empty. To start:
257+
</Label>
258+
259+
<Button
260+
variant={ButtonVariants.LINK}
261+
onClick={() => {
262+
addRequest(item.id);
263+
}}
264+
>
265+
Add a request
266+
</Button>
267+
</div>
268+
)}
269+
</>
270+
)}
271+
</div>
272+
);
273+
}

0 commit comments

Comments
 (0)