mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-23 09:51:28 +01:00
Add .oxfmtignore to skip generated bindings and wasm-pack output. Add npm format script, update DEVELOPMENT.md for Vite+ toolchain, and format all non-generated files with oxfmt. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
114 lines
3.2 KiB
TypeScript
114 lines
3.2 KiB
TypeScript
import type { HttpRequest } from "@yaakapp-internal/models";
|
|
import classNames from "classnames";
|
|
import type { FormEvent, ReactNode } from "react";
|
|
import { memo, useCallback, useRef, useState } from "react";
|
|
import { useHotKey } from "../hooks/useHotKey";
|
|
import type { IconProps } from "./core/Icon";
|
|
import { IconButton } from "./core/IconButton";
|
|
import type { InputHandle, InputProps } from "./core/Input";
|
|
import { Input } from "./core/Input";
|
|
import { HStack } from "./core/Stacks";
|
|
|
|
type Props = Pick<HttpRequest, "url"> & {
|
|
className?: string;
|
|
placeholder: string;
|
|
onSend: () => void;
|
|
onUrlChange: (url: string) => void;
|
|
onPaste?: (v: string) => void;
|
|
onPasteOverwrite?: InputProps["onPasteOverwrite"];
|
|
onCancel: () => void;
|
|
submitIcon?: IconProps["icon"] | null;
|
|
isLoading: boolean;
|
|
forceUpdateKey: string;
|
|
rightSlot?: ReactNode;
|
|
leftSlot?: ReactNode;
|
|
autocomplete?: InputProps["autocomplete"];
|
|
stateKey: InputProps["stateKey"];
|
|
};
|
|
|
|
export const UrlBar = memo(function UrlBar({
|
|
forceUpdateKey,
|
|
onUrlChange,
|
|
url,
|
|
placeholder,
|
|
className,
|
|
onSend,
|
|
onCancel,
|
|
onPaste,
|
|
onPasteOverwrite,
|
|
submitIcon = "send_horizontal",
|
|
autocomplete,
|
|
leftSlot,
|
|
rightSlot,
|
|
isLoading,
|
|
stateKey,
|
|
}: Props) {
|
|
const inputRef = useRef<InputHandle>(null);
|
|
const [isFocused, setIsFocused] = useState<boolean>(false);
|
|
|
|
const handleInitInputRef = useCallback((h: InputHandle | null) => {
|
|
inputRef.current = h;
|
|
}, []);
|
|
|
|
useHotKey("url_bar.focus", () => {
|
|
inputRef.current?.selectAll();
|
|
});
|
|
|
|
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
|
|
e.preventDefault();
|
|
if (isLoading) onCancel();
|
|
else onSend();
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} className={classNames("x-theme-urlBar", className)}>
|
|
<Input
|
|
setRef={handleInitInputRef}
|
|
autocompleteFunctions
|
|
autocompleteVariables
|
|
stateKey={stateKey}
|
|
size="sm"
|
|
wrapLines={isFocused}
|
|
hideLabel
|
|
language="url"
|
|
className="px-1.5 py-0.5"
|
|
label="Enter URL"
|
|
name="url"
|
|
autocomplete={autocomplete}
|
|
forceUpdateKey={forceUpdateKey}
|
|
onFocus={() => setIsFocused(true)}
|
|
onBlur={() => setIsFocused(false)}
|
|
onPaste={onPaste}
|
|
onPasteOverwrite={onPasteOverwrite}
|
|
onChange={onUrlChange}
|
|
defaultValue={url}
|
|
placeholder={placeholder}
|
|
leftSlot={leftSlot}
|
|
rightSlot={
|
|
<HStack space={0.5}>
|
|
{rightSlot && <div className="py-0.5 h-full">{rightSlot}</div>}
|
|
{submitIcon !== null && (
|
|
<div className="py-0.5 h-full">
|
|
<IconButton
|
|
size="xs"
|
|
iconSize="md"
|
|
title="Send Request"
|
|
type="submit"
|
|
className="w-8 mr-0.5 !h-full"
|
|
iconColor="secondary"
|
|
icon={isLoading ? "x" : submitIcon}
|
|
hotkeyAction="request.send"
|
|
onMouseDown={(e) => {
|
|
// Prevent the button from taking focus
|
|
e.preventDefault();
|
|
}}
|
|
/>
|
|
</div>
|
|
)}
|
|
</HStack>
|
|
}
|
|
/>
|
|
</form>
|
|
);
|
|
});
|