Updates
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
import React, {
|
||||
ComponentProps,
|
||||
DetailedHTMLProps,
|
||||
InputHTMLAttributes,
|
||||
LabelHTMLAttributes,
|
||||
ReactNode,
|
||||
RefObject,
|
||||
TextareaHTMLAttributes,
|
||||
type ComponentProps,
|
||||
type DetailedHTMLProps,
|
||||
type InputHTMLAttributes,
|
||||
type LabelHTMLAttributes,
|
||||
type ReactNode,
|
||||
type RefObject,
|
||||
type TextareaHTMLAttributes,
|
||||
useRef,
|
||||
} from "react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import Span from "../../layout/Span";
|
||||
import { Eye, EyeOff, Info, InfoIcon, X } from "lucide-react";
|
||||
import { Copy, Eye, EyeOff, Info, InfoIcon, X } from "lucide-react";
|
||||
import { AutocompleteOptions } from "../../types";
|
||||
import twuiNumberfy from "../../utils/numberfy";
|
||||
import Dropdown from "../../elements/Dropdown";
|
||||
@@ -19,7 +19,7 @@ import NumberInputButtons from "./NumberInputButtons";
|
||||
import twuiSlugToNormalText from "../../utils/slug-to-normal-text";
|
||||
import Row from "../../layout/Row";
|
||||
import Paper from "../../elements/Paper";
|
||||
import { TWUISelectValidityObject } from "../Select";
|
||||
import type { TWUISelectValidityObject } from "../Select";
|
||||
|
||||
export type InputProps<KeyType extends string> = Omit<
|
||||
DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>,
|
||||
@@ -75,6 +75,7 @@ export type InputProps<KeyType extends string> = Omit<
|
||||
HTMLDivElement
|
||||
>;
|
||||
// refreshDefaultValue?: number;
|
||||
copy?: boolean;
|
||||
};
|
||||
|
||||
let refreshes = 0;
|
||||
@@ -117,6 +118,7 @@ export default function Input<KeyType extends string>(
|
||||
clearInputProps,
|
||||
rawNumber,
|
||||
// refreshDefaultValue,
|
||||
copy,
|
||||
...props
|
||||
} = inputProps;
|
||||
|
||||
@@ -163,7 +165,7 @@ export default function Input<KeyType extends string>(
|
||||
numberText ? "text" : props.type,
|
||||
);
|
||||
|
||||
const DEFAULT_DEBOUNCE = 500;
|
||||
const DEFAULT_DEBOUNCE = 200;
|
||||
const finalDebounce = debounce || DEFAULT_DEBOUNCE;
|
||||
const finalLabel =
|
||||
label ||
|
||||
@@ -225,11 +227,12 @@ export default function Input<KeyType extends string>(
|
||||
}
|
||||
};
|
||||
|
||||
const isControlled = props.value !== undefined && props.value !== null;
|
||||
|
||||
React.useEffect(() => {
|
||||
// if (!existingReady) return;
|
||||
if (typeof props.value !== "string" || !props.value.match(/./)) return;
|
||||
setValue(String(props.value));
|
||||
}, [props.value]);
|
||||
if (!isControlled) return;
|
||||
setValue(String(props.value ?? ""));
|
||||
}, [props.value, isControlled]);
|
||||
|
||||
// React.useEffect(() => {
|
||||
// if (!refreshDefaultValue) return;
|
||||
@@ -290,8 +293,8 @@ export default function Input<KeyType extends string>(
|
||||
onChange={handleValueChange}
|
||||
autoComplete={autoComplete}
|
||||
rows={props.height ? Number(props.height) : props.rows || 2}
|
||||
defaultValue={defaultInitialValue}
|
||||
value={props.value ? getFinalValue(props.value) : undefined}
|
||||
defaultValue={isControlled ? undefined : defaultInitialValue}
|
||||
value={isControlled ? getFinalValue(props.value) : undefined}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
@@ -318,9 +321,9 @@ export default function Input<KeyType extends string>(
|
||||
}}
|
||||
onChange={handleValueChange}
|
||||
type={inputType}
|
||||
defaultValue={defaultInitialValue}
|
||||
defaultValue={isControlled ? undefined : defaultInitialValue}
|
||||
autoComplete={autoComplete}
|
||||
value={props.value ? getFinalValue(props.value) : undefined}
|
||||
value={isControlled ? getFinalValue(props.value) : undefined}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -393,7 +396,29 @@ export default function Input<KeyType extends string>(
|
||||
|
||||
{targetComponent}
|
||||
|
||||
{props.type == "search" || props.readOnly ? null : (
|
||||
{copy ? (
|
||||
<>
|
||||
<div
|
||||
title="Copy value"
|
||||
className="cursor-pointer opacity-50 hover:opacity-100"
|
||||
onClick={() => {
|
||||
const text =
|
||||
inputRef.current.value ||
|
||||
textAreaRef.current.value;
|
||||
|
||||
if (text) {
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.then(() => {
|
||||
// window.alert(`Text Copied`);
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Copy size={17} />
|
||||
</div>
|
||||
</>
|
||||
) : props.type == "search" || props.readOnly ? null : (
|
||||
<div
|
||||
title="Clear Input Field"
|
||||
{...clearInputProps}
|
||||
@@ -502,3 +527,26 @@ export default function Input<KeyType extends string>(
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
const updateInput = ({
|
||||
newValue,
|
||||
inputRef,
|
||||
}: {
|
||||
newValue: string;
|
||||
inputRef: RefObject<HTMLInputElement & HTMLTextAreaElement>;
|
||||
}) => {
|
||||
const input = inputRef.current;
|
||||
if (!input) return;
|
||||
|
||||
// Get the native setter (React overrides the default one)
|
||||
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
|
||||
window.HTMLInputElement.prototype,
|
||||
"value",
|
||||
)?.set;
|
||||
|
||||
// Call it directly on the input
|
||||
nativeInputValueSetter?.call(input, newValue);
|
||||
|
||||
// Dispatch the event - React listens for 'input', not 'change'
|
||||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user