Skip to content

Autocomplete Components#439

Open
nbeatty-gpa wants to merge 23 commits intomasterfrom
Autocomplete
Open

Autocomplete Components#439
nbeatty-gpa wants to merge 23 commits intomasterfrom
Autocomplete

Conversation

@nbeatty-gpa
Copy link
Contributor

add AutoCompleteTextArea and AutoCompleteInput to add autocomplete functionality for given variables wrapped in curly brackets.

Copy link
Contributor

@prestoncraw prestoncraw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whenever you are done addressing the comments on this could you do ctrl + k , ctrl + d to autoformat this file to fix the indentations, etc.?

import { Portal } from 'react-portal'
import * as _ from 'lodash'

interface ILabelValue {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already an interface for this in the Gemstone namespace in application-typings.

Valid={props.Valid}
Record={props.Record}
Setter={props.Setter}
Field={props.Field}
Copy link
Contributor

@prestoncraw prestoncraw Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all props are being passed through, for example Label, Help, Feedback is missing here. Any prop that Input accepts we should also accept in this component and pass through to input unless it is something like Type which we know will be "text"(the default).

}
}, 200);

const handleScroll = (_: Event) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the event arg if we arent using it.

const [autoCompleteOptions, setAutoCompleteOptions] = React.useState<ILabelValue[]>([])
const [position, setPosition] = React.useState<Gemstone.TSX.Interfaces.IElementPosition>({ Top: 0, Left: 0, Width: 0, Height: 0 });

const handleOptionClick = (evt: React.MouseEvent<HTMLTableRowElement, MouseEvent>, option: ILabelValue) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the event arg if we arent using it.

)
}

export const handleAutoComplete = (inputString: string, autoCompletes: string[], autoCompleteSetter: React.Dispatch<React.SetStateAction<ILabelValue[]>>) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks to be the same function as the one used in AutoCompleteInput, they should be utilizing the same function.

textarea.parentNode.appendChild(hiddenDiv);

// Get caret's vertical position relative to textarea
console.log(`text area: ${textarea.scrollLeft}, ${textarea.scrollTop}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is multiple console.log in here for debugging purposes, these need to be removed.

Comment on lines 72 to 77
if (autoCompleteTextArea.current != null) {
if (textAreaElement.current == null) {
const textAreaComponent = autoCompleteTextArea.current.firstChild;
if (textAreaComponent == null) {return}
textAreaComponent.childNodes.forEach((element) => element.nodeName === 'TEXTAREA' ? textAreaElement.current = element as HTMLTextAreaElement : null)
}
Copy link
Contributor

@prestoncraw prestoncraw Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic to assign a ref based on if the nodeName equals TextArea seems very fragile. I think the cleaner way to do this would be to just pass a ref to the TextArea component as an optional prop and have the TextArea component attach that ref to its internal TextArea element.

const [ caret_X, caret_Y ] = getCaretPosition(textAreaElement.current);
console.log(caret_X, caret_Y, rect.top, rect.left)
// we want to offset the position based on the cursor position within the text area.
setPosition({ Top: rect.top + caret_Y - rect.bottom, Left: rect.left + caret_X, Width: rect.width, Height: rect.height });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This positioning logic doesn't look right, during my testing the portal was being positioned at the very top of the screen.

nbeatty-gpa and others added 10 commits February 3, 2026 10:08
Co-authored-by: Preston Crawford <78245034+prestoncraw@users.noreply.github.com>
Signed-off-by: nbeatty-gpa <nbeatty@gridprotectionalliance.org>
Co-authored-by: Preston Crawford <78245034+prestoncraw@users.noreply.github.com>
Signed-off-by: nbeatty-gpa <nbeatty@gridprotectionalliance.org>
Co-authored-by: Preston Crawford <78245034+prestoncraw@users.noreply.github.com>
Signed-off-by: nbeatty-gpa <nbeatty@gridprotectionalliance.org>
@nbeatty-gpa
Copy link
Contributor Author

these past few commits should address everything but the positioning issues. i've been trying to use this approach for positioning, and that's been working well over here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants