Refactor proxy codebase

This commit is contained in:
Gregory Schier
2026-03-12 08:31:05 -07:00
parent 4968237ece
commit 5e3ef70d93
21 changed files with 437 additions and 408 deletions

View File

@@ -1,4 +1,4 @@
import { useTimedBoolean } from '../hooks/useTimedBoolean';
import { useTimedBoolean } from '@yaakapp-internal/ui';
import { copyToClipboard } from '../lib/copy';
import { showToast } from '../lib/toast';
import type { ButtonProps } from './core/Button';

View File

@@ -1,8 +1,6 @@
import { useTimedBoolean } from '../hooks/useTimedBoolean';
import { IconButton, type IconButtonProps, useTimedBoolean } from '@yaakapp-internal/ui';
import { copyToClipboard } from '../lib/copy';
import { showToast } from '../lib/toast';
import type { IconButtonProps } from './core/IconButton';
import { IconButton } from './core/IconButton';
interface Props extends Omit<IconButtonProps, 'onClick' | 'icon'> {
text: string | (() => Promise<string | null>);

View File

@@ -1,93 +1,37 @@
import classNames from 'classnames';
import type { MouseEvent } from 'react';
import { forwardRef, useCallback } from 'react';
import { useTimedBoolean } from '../../hooks/useTimedBoolean';
import type { ButtonProps } from './Button';
import { Button } from './Button';
import { Icon, LoadingIcon, type IconProps } from '@yaakapp-internal/ui';
import {
IconButton as BaseIconButton,
type IconButtonProps as BaseIconButtonProps,
} from '@yaakapp-internal/ui';
import { forwardRef, useImperativeHandle, useRef } from 'react';
import type { HotkeyAction } from '../../hooks/useHotKey';
import { useFormattedHotkey, useHotKey } from '../../hooks/useHotKey';
export type IconButtonProps = IconProps &
ButtonProps & {
showConfirm?: boolean;
iconClassName?: string;
iconSize?: IconProps['size'];
iconColor?: IconProps['color'];
title: string;
showBadge?: boolean;
};
export type IconButtonProps = BaseIconButtonProps & {
hotkeyAction?: HotkeyAction;
hotkeyLabelOnly?: boolean;
hotkeyPriority?: number;
};
export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(function IconButton(
{
showConfirm,
icon,
color = 'default',
spin,
onClick,
className,
iconClassName,
tabIndex,
size = 'md',
iconSize,
showBadge,
iconColor,
isLoading,
type = 'button',
...props
}: IconButtonProps,
{ hotkeyAction, hotkeyPriority, hotkeyLabelOnly, title, ...props }: IconButtonProps,
ref,
) {
const [confirmed, setConfirmed] = useTimedBoolean();
const handleClick = useCallback(
(e: MouseEvent<HTMLButtonElement>) => {
if (showConfirm) setConfirmed();
onClick?.(e);
},
[onClick, setConfirmed, showConfirm],
const hotkeyTrigger = useFormattedHotkey(hotkeyAction ?? null)?.join('');
const fullTitle = hotkeyTrigger ? `${title ?? ''} ${hotkeyTrigger}`.trim() : title;
const buttonRef = useRef<HTMLButtonElement>(null);
useImperativeHandle<HTMLButtonElement | null, HTMLButtonElement | null>(
ref,
() => buttonRef.current,
);
return (
<Button
ref={ref}
aria-hidden={icon === 'empty'}
disabled={icon === 'empty'}
tabIndex={(tabIndex ?? icon === 'empty') ? -1 : undefined}
onClick={handleClick}
innerClassName="flex items-center justify-center"
size={size}
color={color}
type={type}
className={classNames(
className,
'group/button relative flex-shrink-0',
'!px-0',
size === 'md' && 'w-md',
size === 'sm' && 'w-sm',
size === 'xs' && 'w-xs',
size === '2xs' && 'w-5',
)}
{...props}
>
{showBadge && (
<div className="absolute top-0 right-0 w-1/2 h-1/2 flex items-center justify-center">
<div className="w-2.5 h-2.5 bg-pink-500 rounded-full" />
</div>
)}
{isLoading ? (
<LoadingIcon size={iconSize} className={iconClassName} />
) : (
<Icon
size={iconSize}
icon={confirmed ? 'check' : icon}
spin={spin}
color={iconColor}
className={classNames(
iconClassName,
'group-hover/button:text-text',
confirmed && '!text-success', // Don't use Icon.color here because it won't override the hover color
props.disabled && 'opacity-70',
)}
/>
)}
</Button>
useHotKey(
hotkeyAction ?? null,
() => {
buttonRef.current?.click();
},
{ priority: hotkeyPriority, enable: !hotkeyLabelOnly },
);
return <BaseIconButton ref={buttonRef} title={fullTitle} {...props} />;
});