This is an automated email from the ASF dual-hosted git repository.
thiagoelg pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git
The following commit(s) were added to refs/heads/main by this push:
new 326a7fd2fd7 kie-issues#2296: BPMN Editor: Process Variables - cannot
close tag dropdown to add another tag without reopening panel (#3581)
326a7fd2fd7 is described below
commit 326a7fd2fd757a9fa859113e82cb1ca4b748091d
Author: Adarsh vk <[email protected]>
AuthorDate: Fri May 22 06:33:09 2026 +0530
kie-issues#2296: BPMN Editor: Process Variables - cannot close tag dropdown
to add another tag without reopening panel (#3581)
---
.../src/typeaheadSelect/TypeaheadSelect.tsx | 89 ++++++++++++++--------
1 file changed, 58 insertions(+), 31 deletions(-)
diff --git a/packages/bpmn-editor/src/typeaheadSelect/TypeaheadSelect.tsx
b/packages/bpmn-editor/src/typeaheadSelect/TypeaheadSelect.tsx
index 2a6c3c0d19e..47b2eeb510a 100644
--- a/packages/bpmn-editor/src/typeaheadSelect/TypeaheadSelect.tsx
+++ b/packages/bpmn-editor/src/typeaheadSelect/TypeaheadSelect.tsx
@@ -35,6 +35,14 @@ import { useBpmnEditorI18n } from "../i18n";
export type TypeaheadSelectOption = SelectOptionProps & { customLabel?: string
| React.ReactElement };
+const hasRenderableOptionLabel = (option: TypeaheadSelectOption) => {
+ return (
+ !!option.customLabel ||
+ React.isValidElement(option.children) ||
+ (option.children !== undefined && option.children !== null &&
String(option.children).trim().length > 0)
+ );
+};
+
// Based on
https://v5-archive.patternfly.org/components/menus/select/#typeahead-with-create-option
export function TypeaheadSelect({
id,
@@ -71,10 +79,10 @@ export function TypeaheadSelect({
const [isOpen, setIsOpen] = React.useState(false);
const [inputValue, setInputValue] = React.useState<string | undefined>();
const [filterValue, setFilterValue] = React.useState<string>("");
- const [selectOptions, setSelectOptions] =
React.useState<TypeaheadSelectOption[]>(options);
const [focusedItemIndex, setFocusedItemIndex] = React.useState<number |
null>(null);
const [activeItemId, setActiveItemId] = React.useState<string | null>(null);
const textInputRef = React.useRef<HTMLInputElement>();
+ const keepOpenRef = React.useRef(false);
const CREATE_NEW = useMemo(() => generateUuid(), []);
@@ -97,33 +105,35 @@ export function TypeaheadSelect({
[filterValue, options, selected, showCreateOptionWhen]
);
- React.useEffect(() => {
- let newSelectOptions: TypeaheadSelectOption[] = options;
+ const renderableOptions = useMemo(() =>
options.filter(hasRenderableOptionLabel), [options]);
+
+ const selectOptions = useMemo(() => {
+ let filtered: TypeaheadSelectOption[] = renderableOptions;
- // Filter menu items based on the text input value when one exists
if (filterValue) {
- newSelectOptions = options.filter((menuItem) =>
+ filtered = renderableOptions.filter((menuItem) =>
String(menuItem.children).toLowerCase().includes(filterValue.toLowerCase())
);
}
if (showCreateOption) {
- newSelectOptions = [
+ filtered = [
{
children: <i style={{ color: "#0067cc" }}>{`${createNewOptionLabel}
"${filterValue}"`}</i>,
value: CREATE_NEW,
},
- ...newSelectOptions,
+ ...filtered,
];
}
- // Open the menu when the input value changes and the new value is not
empty
- if (!isOpen && filterValue) {
- setIsOpen(true);
- }
+ return filtered;
+ }, [CREATE_NEW, createNewOptionLabel, filterValue, renderableOptions,
showCreateOption]);
- setSelectOptions(newSelectOptions);
- }, [CREATE_NEW, createNewOptionLabel, filterValue, isOpen, options,
showCreateOption]);
+ const selectedOptionExists = useMemo(
+ () => renderableOptions.some((option) => option.value === selected),
+ [renderableOptions, selected]
+ );
+ const safeSelected = selectedOptionExists ? selected : undefined;
const getSelectOptionId = (value: any) =>
`select-typeahead-${value?.replace(" ", "-")}`;
@@ -156,18 +166,28 @@ export function TypeaheadSelect({
const onSelect = (_event: React.MouseEvent<Element, MouseEvent> | undefined,
value: string | number | undefined) => {
if (value) {
if (value === CREATE_NEW) {
- const newValue = onCreateNewOption?.(filterValue);
- setSelected(newValue, filterValue, { triggeredByCreateNewOption: true
});
- setFilterValue("");
- closeMenu();
+ const newOptionLabel = filterValue;
+ const newValue = onCreateNewOption?.(newOptionLabel);
+ setSelected(newValue, newOptionLabel, { triggeredByCreateNewOption:
true });
+
+ if (isMultiple) {
+ keepOpenRef.current = true;
+ setInputValue("");
+ } else {
+ setInputValue(newOptionLabel);
+ closeMenu();
+ }
+ } else if (isMultiple) {
+ keepOpenRef.current = true;
+ const optionText = selectOptions.find((option) => option.value ===
value)?.children;
+ setSelected(String(value), String(optionText), {
triggeredByCreateNewOption: false });
} else {
const optionText = selectOptions.find((option) => option.value ===
value)?.children;
setInputValue(String(optionText));
setSelected(String(value), String(optionText), {
triggeredByCreateNewOption: false });
-
- setFilterValue("");
closeMenu();
}
+ setFilterValue("");
}
};
@@ -175,6 +195,10 @@ export function TypeaheadSelect({
setInputValue(value);
setFilterValue(value);
+ if (!isOpen && value) {
+ setIsOpen(true);
+ }
+
resetActiveAndFocusedItem();
setActiveAndFocusedItem(0);
};
@@ -276,18 +300,23 @@ export function TypeaheadSelect({
textInputRef?.current?.focus();
};
- const onBlur = (e: React.MouseEvent) => {
- if ((e.relatedTarget as HTMLElement |
undefined)?.id?.includes(CREATE_NEW)) {
- // If we're blurring the typeahead input because we're creating
- // a new element with a mouse click, then we don't need to do anything.
- return;
- }
-
+ const onBlur = () => {
const optionText = options.find((option) => option.value ===
selected)?.children;
setInputValue(optionText as string);
setFilterValue("");
};
+ const onOpenChange = (nextOpen: boolean) => {
+ if (!nextOpen && keepOpenRef.current) {
+ keepOpenRef.current = false;
+ return;
+ }
+ setIsOpen(nextOpen);
+ if (!nextOpen) {
+ resetActiveAndFocusedItem();
+ }
+ };
+
const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle
ref={toggleRef}
@@ -330,19 +359,17 @@ export function TypeaheadSelect({
<Select
id={id}
isOpen={isOpen}
- selected={selected}
+ selected={safeSelected}
onSelect={onSelect}
className={"kie-bpmn-editor--typeahead-selector"}
- onOpenChange={(isOpen) => {
- !isOpen && closeMenu();
- }}
+ onOpenChange={onOpenChange}
popperProps={{
appendTo: document.body,
}}
toggle={toggle}
shouldFocusFirstItemOnOpen={false}
>
- <SelectList id="select-create-typeahead-listbox">
+ <SelectList id="select-create-typeahead-listbox" onMouseDown={(e) =>
e.preventDefault()}>
{selectOptions.length <= 0 && (
<>
{(!filterValue && (
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]