mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-24 01:28:35 +02:00
Port some stuff from sync PR
This commit is contained in:
@@ -31,7 +31,7 @@ export function ResizeHandle({
|
|||||||
onDoubleClick={onReset}
|
onDoubleClick={onReset}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
className,
|
className,
|
||||||
'group z-10 flex',
|
'group z-10 flex select-none',
|
||||||
// 'bg-fg-info', // For debugging
|
// 'bg-fg-info', // For debugging
|
||||||
vertical ? 'w-full h-3 cursor-row-resize' : 'h-full w-3 cursor-col-resize',
|
vertical ? 'w-full h-3 cursor-row-resize' : 'h-full w-3 cursor-col-resize',
|
||||||
justify === 'center' && 'justify-center',
|
justify === 'center' && 'justify-center',
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
import { Icon } from './Icon';
|
import { Icon } from './Icon';
|
||||||
import { HStack } from './Stacks';
|
import { HStack } from './Stacks';
|
||||||
|
|
||||||
interface Props {
|
export interface CheckboxProps {
|
||||||
checked: boolean;
|
checked: boolean | 'indeterminate';
|
||||||
title: string;
|
title: ReactNode;
|
||||||
onChange: (checked: boolean) => void;
|
onChange: (checked: boolean) => void;
|
||||||
disabled?: boolean;
|
|
||||||
className?: string;
|
className?: string;
|
||||||
|
disabled?: boolean;
|
||||||
inputWrapperClassName?: string;
|
inputWrapperClassName?: string;
|
||||||
indeterminate?: boolean;
|
|
||||||
hideLabel?: boolean;
|
hideLabel?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Checkbox({
|
export function Checkbox({
|
||||||
checked,
|
checked,
|
||||||
indeterminate,
|
|
||||||
onChange,
|
onChange,
|
||||||
className,
|
className,
|
||||||
inputWrapperClassName,
|
inputWrapperClassName,
|
||||||
disabled,
|
disabled,
|
||||||
title,
|
title,
|
||||||
hideLabel,
|
hideLabel,
|
||||||
}: Props) {
|
}: CheckboxProps) {
|
||||||
return (
|
return (
|
||||||
<HStack
|
<HStack
|
||||||
as="label"
|
as="label"
|
||||||
@@ -38,10 +37,13 @@ export function Checkbox({
|
|||||||
)}
|
)}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={() => onChange(!checked)}
|
onChange={() => onChange(checked === 'indeterminate' ? true : !checked)}
|
||||||
/>
|
/>
|
||||||
<div className="absolute inset-0 flex items-center justify-center">
|
<div className="absolute inset-0 flex items-center justify-center">
|
||||||
<Icon size="sm" icon={indeterminate ? 'minus' : checked ? 'check' : 'empty'} />
|
<Icon
|
||||||
|
size="sm"
|
||||||
|
icon={checked === 'indeterminate' ? 'minus' : checked ? 'check' : 'empty'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{!hideLabel && title}
|
{!hideLabel && title}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export function Dialog({
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'h-full w-full grid grid-cols-[minmax(0,1fr)]',
|
'h-full w-full grid grid-cols-[minmax(0,1fr)] grid-rows-1',
|
||||||
!noPadding && 'px-6 py-2',
|
!noPadding && 'px-6 py-2',
|
||||||
!noScroll && 'overflow-y-auto overflow-x-hidden',
|
!noScroll && 'overflow-y-auto overflow-x-hidden',
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
|
|||||||
labelClassName,
|
labelClassName,
|
||||||
labelPosition = 'top',
|
labelPosition = 'top',
|
||||||
leftSlot,
|
leftSlot,
|
||||||
name,
|
|
||||||
onBlur,
|
onBlur,
|
||||||
onChange,
|
onChange,
|
||||||
onFocus,
|
onFocus,
|
||||||
@@ -91,7 +90,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
|
|||||||
onBlur?.();
|
onBlur?.();
|
||||||
}, [onBlur]);
|
}, [onBlur]);
|
||||||
|
|
||||||
const id = `input-${name}`;
|
const id = `input-${label}`;
|
||||||
const editorClassName = classNames(
|
const editorClassName = classNames(
|
||||||
className,
|
className,
|
||||||
'!bg-transparent min-w-0 h-auto w-full focus:outline-none placeholder:text-placeholder',
|
'!bg-transparent min-w-0 h-auto w-full focus:outline-none placeholder:text-placeholder',
|
||||||
|
|||||||
@@ -1,51 +1,54 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { forwardRef, useCallback, useMemo, useRef, useState } from 'react';
|
import type { HTMLAttributes } from 'react';
|
||||||
|
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||||
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
|
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
|
||||||
import { IconButton } from './IconButton';
|
import { IconButton } from './IconButton';
|
||||||
import type { InputProps } from './Input';
|
import type { InputProps } from './Input';
|
||||||
import { HStack } from './Stacks';
|
import { HStack } from './Stacks';
|
||||||
|
|
||||||
export type PlainInputProps = Omit<InputProps, 'wrapLines' | 'onKeyDown' | 'type'> & {
|
export type PlainInputProps = Omit<InputProps, 'wrapLines' | 'onKeyDown' | 'type'> &
|
||||||
type?: 'text' | 'password' | 'number';
|
Pick<HTMLAttributes<HTMLInputElement>, 'onKeyDownCapture'> & {
|
||||||
step?: number;
|
type?: 'text' | 'password' | 'number';
|
||||||
};
|
step?: number;
|
||||||
|
};
|
||||||
|
|
||||||
export const PlainInput = forwardRef<HTMLInputElement, PlainInputProps>(function Input(
|
export function PlainInput({
|
||||||
{
|
className,
|
||||||
className,
|
containerClassName,
|
||||||
containerClassName,
|
defaultValue,
|
||||||
defaultValue,
|
forceUpdateKey,
|
||||||
forceUpdateKey,
|
hideLabel,
|
||||||
hideLabel,
|
label,
|
||||||
label,
|
labelClassName,
|
||||||
labelClassName,
|
labelPosition = 'top',
|
||||||
labelPosition = 'top',
|
leftSlot,
|
||||||
leftSlot,
|
name,
|
||||||
name,
|
onBlur,
|
||||||
onBlur,
|
onChange,
|
||||||
onChange,
|
onFocus,
|
||||||
onFocus,
|
onPaste,
|
||||||
onPaste,
|
placeholder,
|
||||||
placeholder,
|
require,
|
||||||
require,
|
rightSlot,
|
||||||
rightSlot,
|
size = 'md',
|
||||||
size = 'md',
|
type = 'text',
|
||||||
type = 'text',
|
validate,
|
||||||
validate,
|
autoSelect,
|
||||||
autoSelect,
|
step,
|
||||||
...props
|
autoFocus,
|
||||||
}: PlainInputProps,
|
readOnly,
|
||||||
ref,
|
}: PlainInputProps) {
|
||||||
) {
|
|
||||||
const [obscured, setObscured] = useStateWithDeps(type === 'password', [type]);
|
const [obscured, setObscured] = useStateWithDeps(type === 'password', [type]);
|
||||||
const [currentValue, setCurrentValue] = useState(defaultValue ?? '');
|
const [currentValue, setCurrentValue] = useState(defaultValue ?? '');
|
||||||
const [focused, setFocused] = useState(false);
|
const [focused, setFocused] = useState(false);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
|
||||||
const handleFocus = useCallback(() => {
|
const handleFocus = useCallback(() => {
|
||||||
setFocused(true);
|
setFocused(true);
|
||||||
if (autoSelect) {
|
if (autoSelect) {
|
||||||
inputRef.current?.select();
|
inputRef.current?.select();
|
||||||
|
textareaRef.current?.select();
|
||||||
}
|
}
|
||||||
onFocus?.();
|
onFocus?.();
|
||||||
}, [autoSelect, onFocus]);
|
}, [autoSelect, onFocus]);
|
||||||
@@ -56,9 +59,9 @@ export const PlainInput = forwardRef<HTMLInputElement, PlainInputProps>(function
|
|||||||
}, [onBlur]);
|
}, [onBlur]);
|
||||||
|
|
||||||
const id = `input-${name}`;
|
const id = `input-${name}`;
|
||||||
const inputClassName = classNames(
|
const commonClassName = classNames(
|
||||||
className,
|
className,
|
||||||
'!bg-transparent min-w-0 h-auto w-full focus:outline-none placeholder:text-placeholder',
|
'!bg-transparent min-w-0 w-full focus:outline-none placeholder:text-placeholder',
|
||||||
'px-2 text-xs font-mono cursor-text',
|
'px-2 text-xs font-mono cursor-text',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -122,7 +125,7 @@ export const PlainInput = forwardRef<HTMLInputElement, PlainInputProps>(function
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
ref={ref}
|
ref={inputRef}
|
||||||
key={forceUpdateKey}
|
key={forceUpdateKey}
|
||||||
id={id}
|
id={id}
|
||||||
type={type === 'password' && !obscured ? 'text' : type}
|
type={type === 'password' && !obscured ? 'text' : type}
|
||||||
@@ -133,10 +136,12 @@ export const PlainInput = forwardRef<HTMLInputElement, PlainInputProps>(function
|
|||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
onChange={(e) => handleChange(e.target.value)}
|
onChange={(e) => handleChange(e.target.value)}
|
||||||
onPaste={(e) => onPaste?.(e.clipboardData.getData('Text'))}
|
onPaste={(e) => onPaste?.(e.clipboardData.getData('Text'))}
|
||||||
className={inputClassName}
|
className={classNames(commonClassName, 'h-auto')}
|
||||||
onFocus={handleFocus}
|
onFocus={handleFocus}
|
||||||
onBlur={handleBlur}
|
onBlur={handleBlur}
|
||||||
{...props}
|
autoFocus={autoFocus}
|
||||||
|
step={step}
|
||||||
|
readOnly={readOnly}
|
||||||
/>
|
/>
|
||||||
</HStack>
|
</HStack>
|
||||||
{type === 'password' && (
|
{type === 'password' && (
|
||||||
@@ -154,7 +159,7 @@ export const PlainInput = forwardRef<HTMLInputElement, PlainInputProps>(function
|
|||||||
</HStack>
|
</HStack>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
function validateRequire(v: string) {
|
function validateRequire(v: string) {
|
||||||
return v.length > 0;
|
return v.length > 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user