From f4860a4a3ffb354170c3e09f44b8d3acf78b5fe6 Mon Sep 17 00:00:00 2001 From: Ruben Thoms Date: Tue, 24 Oct 2023 17:02:18 +0200 Subject: [PATCH] First iteration --- frontend/src/lib/components/Select/select.tsx | 56 +++++++++++-------- .../Virtualization/virtualization.tsx | 1 + 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/frontend/src/lib/components/Select/select.tsx b/frontend/src/lib/components/Select/select.tsx index ce4288aca..c68aa38c4 100644 --- a/frontend/src/lib/components/Select/select.tsx +++ b/frontend/src/lib/components/Select/select.tsx @@ -3,6 +3,8 @@ import React, { Key } from "react"; import { resolveClassNames } from "@lib/utils/resolveClassNames"; import { getTextWidth } from "@lib/utils/textSize"; +import { isEqual } from "lodash"; + import { BaseComponent, BaseComponentProps } from "../BaseComponent"; import { Input } from "../Input"; import { Virtualization } from "../Virtualization"; @@ -45,7 +47,7 @@ export const Select = withDefaults()(defaultProps, (props) => { const [startIndex, setStartIndex] = React.useState(0); const [lastShiftIndex, setLastShiftIndex] = React.useState(-1); const [currentIndex, setCurrentIndex] = React.useState(0); - const [minWidth, setMinWidth] = React.useState(0); + const [prevFilteredOptions, setPrevFilteredOptions] = React.useState([]); const ref = React.useRef(null); const noOptionsText = props.placeholder ?? "No options"; @@ -56,24 +58,25 @@ export const Select = withDefaults()(defaultProps, (props) => { return props.options.filter((option) => option.label.toLowerCase().includes(filter.toLowerCase())); }, [props.options, filter]); - React.useEffect(() => { - let longestOptionWidth = props.options.reduce((prev, current) => { - const labelWidth = getTextWidth(current.label, document.body); - if (labelWidth > prev) { - return labelWidth; - } - return prev; - }, 0); - - if (longestOptionWidth === 0) { - if (props.options.length === 0 || filter === "") { - longestOptionWidth = getTextWidth(noOptionsText, document.body); - } else { - longestOptionWidth = getTextWidth(noMatchingOptionsText, document.body); + if (!isEqual(filteredOptions, prevFilteredOptions)) { + let newCurrentIndex = 0; + let newStartIndex = 0; + const indexOffset = currentIndex - startIndex; + let oldCurrentValue = prevFilteredOptions[currentIndex]?.value; + if (props.value?.length >= 1) { + oldCurrentValue = props.value[0]; + } + setPrevFilteredOptions(filteredOptions); + if (oldCurrentValue) { + const newIndex = filteredOptions.findIndex((option) => option.value === oldCurrentValue); + if (newIndex !== -1) { + newCurrentIndex = newIndex; + newStartIndex = Math.max(0, newIndex - indexOffset); } } - setMinWidth(longestOptionWidth + 40); - }, [props.options, noOptionsText, filter]); + setCurrentIndex(newCurrentIndex); + setStartIndex(newStartIndex); + } const toggleValue = React.useCallback( (option: SelectOption, index: number) => { @@ -121,10 +124,12 @@ export const Select = withDefaults()(defaultProps, (props) => { const handleKeyDown = (e: KeyboardEvent) => { setKeysPressed((keysPressed) => [...keysPressed, e.key]); + if (e.key === "Shift") { + console.debug("Shift pressed", currentIndex); + setLastShiftIndex(currentIndex); + } + if (hasFocus) { - if (e.key === "Shift") { - setLastShiftIndex(currentIndex); - } if (e.key === "ArrowUp") { e.preventDefault(); const newIndex = Math.max(0, currentIndex - 1); @@ -186,6 +191,8 @@ export const Select = withDefaults()(defaultProps, (props) => { } }; + console.debug("startIndex", startIndex, "currentIndex", currentIndex); + return (
()(defaultProps, (props) => { "pointer-events-none": props.disabled, "opacity-30": props.disabled, })} - style={{ width: props.width, minWidth: props.width ?? minWidth }} + style={{ width: props.width, minWidth: props.width }} > {props.filter && ( ()(defaultProps, (props) => { style={{ height: 24 }} > {option.icon} - - {option.label} + + {option.label}
); diff --git a/frontend/src/lib/components/Virtualization/virtualization.tsx b/frontend/src/lib/components/Virtualization/virtualization.tsx index 4a3477c0e..85b4729c1 100644 --- a/frontend/src/lib/components/Virtualization/virtualization.tsx +++ b/frontend/src/lib/components/Virtualization/virtualization.tsx @@ -41,6 +41,7 @@ export const Virtualization = withDefaults()(defaultProps, props.direction, props.startIndex, props.itemSize, + props.items, containerSize.height, containerSize.width, ]);