Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 33x 2332x 457x 33x 2332x 2332x 2332x 2332x 2332x 132x 132x 2332x 205x 2332x 207x 2332x 457x 44x 44x 44x 44x 2332x 163x 163x 163x 2332x 207x 204x 2332x 571x 241x 241x 2332x 821x 20x 2332x 447x 44x 2332x | import React, { useRef, useEffect } from "react";
import { Input, InputProps } from "./input";
import { cn } from "@/lib/utils";
import { PropertySelectionSummary } from "@/pages/flowsheet-page/flowsheet/PropertiesSidebar/components/PropertySelectionSummary";
interface DebouncedInputProps extends InputProps {
value: string | number;
onUpdate: (update: string | number) => void;
isFixed?: boolean; // if not fixed, show a red border
autoSelect?: boolean;
unitType?: string;
className?: string;
ariaLabel?: string;
}
const useUnmount = (fn: () => void) => {
useEffect(() => {
return fn;
}, []);
};
const DebouncedInput = ({
value,
onUpdate,
isFixed = true,
autoSelect = false,
className,
ariaLabel,
...props
}: DebouncedInputProps) => {
const inputRef = useRef<HTMLInputElement | null>(null);
const currentValue = useRef(value);
const wasActive = useRef(false);
const wasDisabled = useRef(props.disabled);
const handleEnterPressed = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (inputRef.current && e.key === "Enter") {
inputRef.current.blur();
}
};
const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {
currentValue.current = e.target.value; // This is used to avoid calling onBlur with stale data
};
const handleFocus = () => {
wasActive.current = true;
};
useEffect(() => {
if (autoSelect && inputRef.current) {
setTimeout(() => {
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.select();
}
}, 1);
}
}, [autoSelect]);
const handleBlur = () => {
handleUpdate();
wasActive.current = false;
wasDisabled.current = false;
};
const handleUpdate = () => {
// only call onUpdate if the value has changed or if the input was previously disabled
if (currentValue.current !== value || wasDisabled.current || !isFixed) {
onUpdate(currentValue.current);
}
};
useEffect(() => {
if (
value !== undefined &&
value !== null &&
inputRef.current &&
inputRef.current.value !== value
) {
// handle external updates
currentValue.current = value;
inputRef.current.value = value.toString();
}
}, [value]);
useEffect(() => {
// we want to allow the input to be fixed after it becomes un-disabled
// if the input was previously disabled, we should update the value this one time
if (inputRef.current?.disabled) {
wasDisabled.current = true;
}
}, [inputRef.current?.disabled]);
useUnmount(() => {
if (wasActive.current) {
// handle unmounting while active
handleUpdate();
}
});
return (
<Input
placeholder="Enter a value"
name="debounced-input"
ref={inputRef}
type="text"
onInput={handleInput}
onBlur={handleBlur}
onFocus={handleFocus}
onKeyDown={handleEnterPressed}
className={cn(
!isFixed
? "border-rose-700"
: (props.disabled && value !== undefined) ||
(props.disabled && value === 0)
? "border-0"
: "",
className,
)}
aria-label={ariaLabel}
{...props}
/>
);
};
export default DebouncedInput;
|