Schema filtering and a bunch of fixes

This commit is contained in:
Gregory Schier
2025-07-09 12:39:27 -07:00
parent a03ec8875c
commit 036e85d006
6 changed files with 473 additions and 129 deletions

View File

@@ -42,6 +42,7 @@ const icons = {
copy: lucide.CopyIcon,
copy_check: lucide.CopyCheck,
download: lucide.DownloadIcon,
ellipsis: lucide.EllipsisIcon,
external_link: lucide.ExternalLinkIcon,
eye: lucide.EyeIcon,
eye_closed: lucide.EyeOffIcon,
@@ -97,6 +98,7 @@ const icons = {
shield: lucide.ShieldIcon,
shield_check: lucide.ShieldCheckIcon,
shield_off: lucide.ShieldOffIcon,
square_terminal: lucide.SquareTerminalIcon,
sparkles: lucide.SparklesIcon,
sun: lucide.SunIcon,
table: lucide.TableIcon,

View File

@@ -1,6 +1,6 @@
import classNames from 'classnames';
import type { FocusEvent, HTMLAttributes } from 'react';
import { useCallback, useRef, useState } from 'react';
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from 'react';
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
import { IconButton } from './IconButton';
import type { InputProps } from './Input';
@@ -15,39 +15,46 @@ export type PlainInputProps = Omit<InputProps, 'wrapLines' | 'onKeyDown' | 'type
hideObscureToggle?: boolean;
};
export function PlainInput({
autoFocus,
autoSelect,
className,
containerClassName,
defaultValue,
forceUpdateKey,
help,
hideLabel,
hideObscureToggle,
label,
labelClassName,
labelPosition = 'top',
leftSlot,
name,
onBlur,
onChange,
onFocus,
onFocusRaw,
onKeyDownCapture,
onPaste,
placeholder,
required,
rightSlot,
size = 'md',
tint,
type = 'text',
validate,
}: PlainInputProps) {
export const PlainInput = forwardRef<{ focus: () => void }, PlainInputProps>(function PlainInput(
{
autoFocus,
autoSelect,
className,
containerClassName,
defaultValue,
forceUpdateKey,
help,
hideLabel,
hideObscureToggle,
label,
labelClassName,
labelPosition = 'top',
leftSlot,
name,
onBlur,
onChange,
onFocus,
onFocusRaw,
onKeyDownCapture,
onPaste,
placeholder,
required,
rightSlot,
size = 'md',
tint,
type = 'text',
validate,
},
ref,
) {
const [obscured, setObscured] = useStateWithDeps(type === 'password', [type]);
const [focused, setFocused] = useState(false);
const [hasChanged, setHasChanged] = useState<boolean>(false);
const [hasChanged, setHasChanged] = useStateWithDeps<boolean>(false, [forceUpdateKey]);
const inputRef = useRef<HTMLInputElement>(null);
useImperativeHandle<{ focus: () => void } | null, { focus: () => void } | null>(
ref,
() => inputRef.current,
);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const handleFocus = useCallback(
@@ -87,7 +94,7 @@ export function PlainInput({
};
inputRef.current?.setCustomValidity(isValid(value) ? '' : 'Invalid value');
},
[onChange, required, validate],
[onChange, required, setHasChanged, validate],
);
const wrapperRef = useRef<HTMLDivElement>(null);
@@ -102,7 +109,13 @@ export function PlainInput({
labelPosition === 'top' && 'flex-row gap-0.5',
)}
>
<Label htmlFor={id} className={labelClassName} visuallyHidden={hideLabel} required={required} help={help}>
<Label
htmlFor={id}
className={labelClassName}
visuallyHidden={hideLabel}
required={required}
help={help}
>
{label}
</Label>
<HStack
@@ -149,7 +162,7 @@ export function PlainInput({
autoCorrect="off"
onChange={(e) => handleChange(e.target.value)}
onPaste={(e) => onPaste?.(e.clipboardData.getData('Text'))}
className={classNames(commonClassName, 'h-auto')}
className={classNames(commonClassName, 'h-full')}
onFocus={handleFocus}
onBlur={handleBlur}
required={required}
@@ -173,7 +186,7 @@ export function PlainInput({
</HStack>
</div>
);
}
});
function validateRequire(v: string) {
return v.length > 0;