Fix selection of HTTP Request on create dropdown hotkey

This commit is contained in:
Gregory Schier
2024-05-14 00:17:33 -07:00
parent 31147475f3
commit a7bb5605ab
4 changed files with 49 additions and 36 deletions

View File

@@ -118,7 +118,7 @@ const ae = "curl", se = "cURL", ie = "cURL command line tool", H = ["d", "data",
function oe(n) { function oe(n) {
if (!n.match(/^\s*curl /)) if (!n.match(/^\s*curl /))
return null; return null;
const s = [], e = n.replace(/([^\\])\n/g, "$1; "); const s = [], e = n.replace(/\ncurl/g, "; curl");
let t = []; let t = [];
const m = Z(e).flatMap((r) => typeof r == "string" && r.startsWith("-") && !r.startsWith("--") && r.length > 2 ? [r.slice(0, 2), r.slice(2)] : r); const m = Z(e).flatMap((r) => typeof r == "string" && r.startsWith("-") && !r.startsWith("--") && r.length > 2 ? [r.slice(0, 2), r.slice(2)] : r);
for (const r of m) { for (const r of m) {
@@ -158,13 +158,13 @@ function te(n, s) {
for (let o = 1; o < n.length; o++) { for (let o = 1; o < n.length; o++) {
let l = n[o]; let l = n[o];
if (typeof l == "string" && (l = l.trim()), typeof l == "string" && l.match(/^-{1,2}[\w-]+/)) { if (typeof l == "string" && (l = l.trim()), typeof l == "string" && l.match(/^-{1,2}[\w-]+/)) {
const $ = l[0] === "-" && l[1] !== "-"; const y = l[0] === "-" && l[1] !== "-";
let h = l.replace(/^-{1,2}/, ""); let h = l.replace(/^-{1,2}/, "");
if (!ee.includes(h)) if (!ee.includes(h))
continue; continue;
let y; let $;
const S = n[o + 1]; const S = n[o + 1];
$ && h.length > 1 ? (y = h.slice(1), h = h.slice(0, 1)) : typeof S == "string" && !S.startsWith("-") ? (y = S, o++) : y = !0, e[h] = e[h] || [], e[h].push(y); y && h.length > 1 ? ($ = h.slice(1), h = h.slice(0, 1)) : typeof S == "string" && !S.startsWith("-") ? ($ = S, o++) : $ = !0, e[h] = e[h] || [], e[h].push($);
} else } else
l && t.push(l); l && t.push(l);
} }
@@ -181,10 +181,10 @@ function te(n, s) {
...e.header || [], ...e.header || [],
...e.H || [] ...e.H || []
].map((o) => { ].map((o) => {
const [l, $] = o.split(/:(.*)$/); const [l, y] = o.split(/:(.*)$/);
return $ ? { return y ? {
name: (l ?? "").trim(), name: (l ?? "").trim(),
value: $.trim() value: y.trim()
} : { } : {
name: (l ?? "").trim().replace(/;$/, ""), name: (l ?? "").trim().replace(/;$/, ""),
value: "" value: ""
@@ -193,8 +193,8 @@ function te(n, s) {
...e.cookie || [], ...e.cookie || [],
...e.b || [] ...e.b || []
].map((o) => { ].map((o) => {
const l = o.split("=", 1)[0], $ = o.replace(`${l}=`, ""); const l = o.split("=", 1)[0], y = o.replace(`${l}=`, "");
return `${l}=${$}`; return `${l}=${y}`;
}).join("; "), u = i.find((o) => o.name.toLowerCase() === "cookie"); }).join("; "), u = i.find((o) => o.name.toLowerCase() === "cookie");
b && u ? u.value += `; ${b}` : b && i.push({ b && u ? u.value += `; ${b}` : b && i.push({
name: "Cookie", name: "Cookie",
@@ -204,11 +204,11 @@ function te(n, s) {
...e.form || [], ...e.form || [],
...e.F || [] ...e.F || []
].map((o) => { ].map((o) => {
const l = o.split("="), $ = l[0] ?? "", h = l[1] ?? "", y = { const l = o.split("="), y = l[0] ?? "", h = l[1] ?? "", $ = {
name: $, name: y,
enabled: !0 enabled: !0
}; };
return h.indexOf("@") === 0 ? y.file = h.slice(1) : y.value = h, y; return h.indexOf("@") === 0 ? $.file = h.slice(1) : $.value = h, $;
}); });
let g = {}, I = null; let g = {}, I = null;
const B = C(e, !1, ["G", "get"]); const B = C(e, !1, ["G", "get"]);

View File

@@ -2,12 +2,15 @@ import { useCreateDropdownItems } from '../hooks/useCreateDropdownItems';
import type { DropdownProps } from './core/Dropdown'; import type { DropdownProps } from './core/Dropdown';
import { Dropdown } from './core/Dropdown'; import { Dropdown } from './core/Dropdown';
interface Props { interface Props extends Omit<DropdownProps, 'items'> {
hideFolder?: boolean; hideFolder?: boolean;
children: DropdownProps['children'];
} }
export function CreateDropdown({ hideFolder, children }: Props) { export function CreateDropdown({ hideFolder, children, ...props }: Props) {
const items = useCreateDropdownItems({ hideFolder, hideIcons: true }); const items = useCreateDropdownItems({ hideFolder, hideIcons: true });
return <Dropdown items={items}>{children}</Dropdown>; return (
<Dropdown items={items} {...props}>
{children}
</Dropdown>
);
} }

View File

@@ -34,13 +34,8 @@ export function SidebarActions() {
hotkeyAction="sidebar.toggle" hotkeyAction="sidebar.toggle"
icon={hidden ? 'leftPanelHidden' : 'leftPanelVisible'} icon={hidden ? 'leftPanelHidden' : 'leftPanelVisible'}
/> />
<CreateDropdown> <CreateDropdown hotKeyAction="http_request.create">
<IconButton <IconButton size="sm" icon="plusCircle" title="Add Resource" />
size="sm"
icon="plusCircle"
title="Add Resource"
hotkeyAction="http_request.create"
/>
</CreateDropdown> </CreateDropdown>
</HStack> </HStack>
); );

View File

@@ -30,6 +30,7 @@ import { HotKey } from './HotKey';
import { Separator } from './Separator'; import { Separator } from './Separator';
import { HStack, VStack } from './Stacks'; import { HStack, VStack } from './Stacks';
import { Icon } from './Icon'; import { Icon } from './Icon';
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
export type DropdownItemSeparator = { export type DropdownItemSeparator = {
type: 'separator'; type: 'separator';
@@ -58,6 +59,7 @@ export interface DropdownProps {
items: DropdownItem[]; items: DropdownItem[];
onOpen?: () => void; onOpen?: () => void;
onClose?: () => void; onClose?: () => void;
hotKeyAction?: HotkeyAction;
} }
export interface DropdownRef { export interface DropdownRef {
@@ -71,7 +73,7 @@ export interface DropdownRef {
} }
export const Dropdown = forwardRef<DropdownRef, DropdownProps>(function Dropdown( export const Dropdown = forwardRef<DropdownRef, DropdownProps>(function Dropdown(
{ children, items, onOpen, onClose }: DropdownProps, { children, items, onOpen, onClose, hotKeyAction }: DropdownProps,
ref, ref,
) { ) {
const [isOpen, _setIsOpen] = useState<boolean>(false); const [isOpen, _setIsOpen] = useState<boolean>(false);
@@ -88,18 +90,33 @@ export const Dropdown = forwardRef<DropdownRef, DropdownProps>(function Dropdown
[onClose, onOpen], [onClose, onOpen],
); );
const handleClose = useCallback(() => {
setIsOpen(false);
buttonRef.current?.focus();
// Reset so it triggers a render if opening sets to 0, for example
setDefaultSelectedIndex(undefined);
}, [setIsOpen]);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
...menuRef.current, ...menuRef.current,
isOpen: isOpen, isOpen: isOpen,
toggle() { toggle() {
if (!isOpen) this.open(); if (!isOpen) this.open();
else setIsOpen(false); else this.close();
}, },
open() { open() {
setIsOpen(true); setIsOpen(true);
}, },
close() {
handleClose();
},
})); }));
useHotKey(hotKeyAction ?? null, () => {
setDefaultSelectedIndex(0);
setIsOpen(true);
});
const child = useMemo(() => { const child = useMemo(() => {
const existingChild = Children.only(children); const existingChild = Children.only(children);
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -119,11 +136,6 @@ export const Dropdown = forwardRef<DropdownRef, DropdownProps>(function Dropdown
return cloneElement(existingChild, props); return cloneElement(existingChild, props);
}, [children, setIsOpen]); }, [children, setIsOpen]);
const handleClose = useCallback(() => {
setIsOpen(false);
buttonRef.current?.focus();
}, [setIsOpen]);
useEffect(() => { useEffect(() => {
buttonRef.current?.setAttribute('aria-expanded', isOpen.toString()); buttonRef.current?.setAttribute('aria-expanded', isOpen.toString());
}, [isOpen]); }, [isOpen]);
@@ -206,7 +218,10 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
}: MenuProps, }: MenuProps,
ref, ref,
) { ) {
const [selectedIndex, setSelectedIndex] = useState<number | null>(defaultSelectedIndex ?? null); const [selectedIndex, setSelectedIndex] = useStateWithDeps<number | null>(
defaultSelectedIndex ?? null,
[defaultSelectedIndex],
);
const [menuStyles, setMenuStyles] = useState<CSSProperties>({}); const [menuStyles, setMenuStyles] = useState<CSSProperties>({});
const [filter, setFilter] = useState<string>(''); const [filter, setFilter] = useState<string>('');
const [containerWidth, setContainerWidth] = useState<number | null>(null); const [containerWidth, setContainerWidth] = useState<number | null>(null);
@@ -223,7 +238,7 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
onClose(); onClose();
setSelectedIndex(null); setSelectedIndex(null);
setFilter(''); setFilter('');
}, [onClose]); }, [onClose, setSelectedIndex]);
// Close menu on space bar // Close menu on space bar
const handleMenuKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => { const handleMenuKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
@@ -265,7 +280,7 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
} }
return nextIndex; return nextIndex;
}); });
}, [items]); }, [items, setSelectedIndex]);
const handleNext = useCallback(() => { const handleNext = useCallback(() => {
setSelectedIndex((currIndex) => { setSelectedIndex((currIndex) => {
@@ -282,7 +297,7 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
} }
return nextIndex; return nextIndex;
}); });
}, [items]); }, [items, setSelectedIndex]);
useKey( useKey(
'ArrowUp', 'ArrowUp',
@@ -316,7 +331,7 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
i.onSelect(); i.onSelect();
} }
}, },
[handleClose], [handleClose, setSelectedIndex],
); );
useImperativeHandle( useImperativeHandle(
@@ -377,7 +392,7 @@ const Menu = forwardRef<Omit<DropdownRef, 'open' | 'isOpen' | 'toggle'>, MenuPro
const index = filteredItems.findIndex((item) => item === i) ?? null; const index = filteredItems.findIndex((item) => item === i) ?? null;
setSelectedIndex(index); setSelectedIndex(index);
}, },
[filteredItems], [filteredItems, setSelectedIndex],
); );
if (items.length === 0) return null; if (items.length === 0) return null;