diff --git a/vuu-ui/packages/vuu-filters/src/custom-filters/CustomFilters.tsx b/vuu-ui/packages/vuu-filters/src/custom-filters/CustomFilters.tsx index 083e0eef9..39260e1df 100644 --- a/vuu-ui/packages/vuu-filters/src/custom-filters/CustomFilters.tsx +++ b/vuu-ui/packages/vuu-filters/src/custom-filters/CustomFilters.tsx @@ -47,7 +47,7 @@ export const CustomFilters = ({ interactedFilterState, onCancelEdit, onSave, - pillProps, + FilterPillProps, promptProps, } = useCustomFilters({ containerRef: rootRef, @@ -74,7 +74,7 @@ export const CustomFilters = ({ filters.forEach((filter, i) => { items.push( { - // editingFilterRef.current = filter; - // }, []); - // TODO handle cancel edit name const handleExitEditFilterName: EditableLabelProps["onExitEditMode"] = useCallback( @@ -285,7 +281,7 @@ export const useCustomFilters = ({ [onToggleFilterActive] ); - const pillProps: Omit = { + const FilterPillProps: Omit = { editLabelApiRef: editPillLabelAPI, // onBeginEdit: handleBeginEditFilterName, onClick: handlePillClick, @@ -326,6 +322,7 @@ export const useCustomFilters = ({ }; return { + FilterPillProps, activeFilterIndex, addButtonProps, columnsByName, @@ -333,7 +330,6 @@ export const useCustomFilters = ({ interactedFilterState, onCancelEdit: handleCancelEdit, onSave: filterSaveHandler, - pillProps, promptProps, }; }; diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx b/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx index b7994d842..6473f1d39 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx @@ -118,22 +118,22 @@ export const EditableLabel = forwardRef(function EditableLabel( [beginEdit] ); - const exitEditMode = ({ - cancelEdit = false, - allowDeactivation = false, - } = {}) => { - setEditing(false); - const originalValue = initialValue.current; - if (originalValue !== value) { - if (cancelEdit) { - setValue(originalValue); - } else { - initialValue.current = value; + const exitEditMode = useCallback( + ({ cancelEdit = false, allowDeactivation = false } = {}) => { + setEditing(false); + const originalValue = initialValue.current; + if (originalValue !== value) { + if (cancelEdit) { + setValue(originalValue); + } else { + initialValue.current = value; + } } - } - onExitEditMode && - onExitEditMode(originalValue, value, allowDeactivation, cancelEdit); - }; + onExitEditMode && + onExitEditMode(originalValue, value, allowDeactivation, cancelEdit); + }, + [onExitEditMode, setEditing, setValue, value] + ); const handleChange = (evt: ChangeEvent) => { const { value } = evt.target; @@ -143,11 +143,11 @@ export const EditableLabel = forwardRef(function EditableLabel( // We need the ref here as the blur fires before setEditing has taken effect, // so we get a double call to exitEditMode if edit is cancelled. - const handleBlur = () => { - if (editingRef.current) { + const handleBlur = useCallback(() => { + if (editing || editingRef.current) { exitEditMode({ allowDeactivation: true }); } - }; + }, [editing, exitEditMode]); const handleKeyDown = (evt: KeyboardEvent) => { if (editing && evt.key === "Enter") { diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx index f62a25302..bbde832b4 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx @@ -46,10 +46,11 @@ export const Tabstrip = ({ const rootRef = useRef(null); const { activeTabIndex, - focusVisible, containerStyle, + focusVisible, draggedItemIndex, onClickAddTab, + interactedTabState, tabProps, ...tabstripHook } = useTabstrip({ @@ -96,6 +97,7 @@ export const Tabstrip = ({ "data-overflow-priority": selected ? "1" : undefined, dragging: draggedItemIndex === index, editable, + editing: interactedTabState?.index === index, focusVisible: focusVisible === index, id: tabId, index, @@ -137,6 +139,7 @@ export const Tabstrip = ({ tabProps, tabClassName, draggedItemIndex, + interactedTabState, focusVisible, location, ] diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/useTabstrip.ts b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/useTabstrip.ts index 6ee38417b..af5e6ae02 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/useTabstrip.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/useTabstrip.ts @@ -1,12 +1,13 @@ import type { MenuActionHandler } from "@finos/vuu-data-types"; import type { OverflowItem } from "@finos/vuu-ui-controls"; -import { dispatchMouseEvent, orientationType } from "@finos/vuu-utils"; +import { orientationType } from "@finos/vuu-utils"; import { KeyboardEvent, MouseEvent as ReactMouseEvent, RefObject, useCallback, useRef, + useState, } from "react"; import { DropOptions, useDragDrop as useDragDrop } from "../drag-drop"; import { isTabMenuOptions } from "./TabMenuOptions"; @@ -39,12 +40,9 @@ export interface TabstripHookProps { const editKeys = new Set(["Enter", " "]); const isEditKey = (key: string) => editKeys.has(key); -const getElementWithIndex = (container: HTMLElement | null, index: number) => { - if (container) { - return container.querySelector(`[data-index="${index}"]`) as HTMLElement; - } else { - return null; - } +type InteractedTabState = { + index: number; + state: "rename"; }; export const useTabstrip = ({ @@ -61,6 +59,9 @@ export const useTabstrip = ({ keyBoardActivation, }: TabstripHookProps) => { const lastSelection = useRef(activeTabIndexProp); + const [interactedTabState, setInteractedTabState] = useState< + InteractedTabState | undefined + >(); const { focusTab: keyboardHookFocusTab, @@ -146,9 +147,7 @@ export const useTabstrip = ({ const handleExitEditMode = useCallback( (originalValue, editedValue, allowDeactivation, tabIndex) => { - console.log( - `handleExitEditMode ${originalValue} ${editedValue} ${allowDeactivation} ${tabIndex}` - ); + setInteractedTabState(undefined); onExitEditMode?.(originalValue, editedValue, allowDeactivation, tabIndex); if (!allowDeactivation) { // this indicates that Enter or Esc key has been pressed, hence we @@ -172,35 +171,12 @@ export const useTabstrip = ({ [keyboardHookHandleClick, selectionHookHandleClick] ); - const getEditableLabel = useCallback( - (tabIndex = highlightedIdx) => { - const targetEl = getElementWithIndex(containerRef.current, tabIndex); - if (targetEl) { - return targetEl.querySelector(".vuuEditableLabel") as HTMLElement; - } - }, - [containerRef, highlightedIdx] - ); - - const tabInEditMode = useCallback( - (tabIndex = highlightedIdx) => { - const editableLabel = getEditableLabel(tabIndex); - if (editableLabel) { - return editableLabel.classList.contains("vuuEditableLabel-editing"); - } - return false; - }, - [getEditableLabel, highlightedIdx] - ); - const editTab = useCallback( (tabIndex = highlightedIdx) => { - const editableLabelEl = getEditableLabel(tabIndex); - if (editableLabelEl) { - dispatchMouseEvent(editableLabelEl, "dblclick"); - } + console.log(`set interacted tab state ${tabIndex}`); + setInteractedTabState({ index: tabIndex, state: "rename" }); }, - [getEditableLabel, highlightedIdx] + [highlightedIdx] ); const handleKeyDown = useCallback( @@ -264,16 +240,16 @@ export const useTabstrip = ({ //TODO( why do we sometimes see this fired twice eg following rename) const handleTabMenuClose = useCallback(() => { - if (!tabInEditMode()) { - keyboardHookFocusTab(highlightedIdx); - } else { + if (interactedTabState?.index === highlightedIdx) { keyboardHookSetHighlightedIndex(highlightedIdx); + } else { + keyboardHookFocusTab(highlightedIdx); } }, [ highlightedIdx, + interactedTabState?.index, keyboardHookFocusTab, keyboardHookSetHighlightedIndex, - tabInEditMode, ]); const onSwitchWrappedItemIntoView = useCallback( @@ -312,12 +288,13 @@ export const useTabstrip = ({ return { activeTabIndex: selectionHookSelected, - containerStyle, - focusVisible: keyboardHook.focusVisible, containerProps: { ...keyboardHook.containerProps, onSwitchWrappedItemIntoView, }, + containerStyle, + focusVisible: keyboardHook.focusVisible, + interactedTabState, navigationProps, onClickAddTab: handleAddTabClick, tabProps, diff --git a/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx b/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx index 5a4b24448..b8560fdee 100644 --- a/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx +++ b/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx @@ -1,3 +1,4 @@ +import { getSchema } from "@finos/vuu-data-test"; import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data-types"; import { ColumnItem, @@ -5,13 +6,14 @@ import { TableSettingsPanel, } from "@finos/vuu-table-extras"; import { TableConfig } from "@finos/vuu-table-types"; -import { getSchema } from "@finos/vuu-data-test"; +import { MoveItemHandler } from "@finos/vuu-ui-controls"; +import { moveItem } from "@finos/vuu-utils"; import { useCallback, useMemo, useState } from "react"; let displaySequence = 1; export const DefaultColumnList = () => { - const columns = useMemo( + const initialColumns = useMemo( () => [ { subscribed: true, @@ -119,11 +121,13 @@ export const DefaultColumnList = () => { [] ); + const [columns, setColumns] = useState(initialColumns); + const handleChange = () => { console.log("handleChange"); }; - const handleMoveListItem = () => { - console.log("handleMoveListItem"); + const handleMoveListItem: MoveItemHandler = (fromIndex, toIndex) => { + setColumns((cols) => moveItem(cols, fromIndex, toIndex)); }; return ( @@ -150,17 +154,7 @@ export const ManyColumnList = () => { const [columns, setColumns] = useState(initialColumns); const handleMoveListItem = useCallback((fromIndex, toIndex) => { - console.log(`drop ${fromIndex} ${toIndex}`); - setColumns((data) => { - const newData = data.slice(); - const [tab] = newData.splice(fromIndex, 1); - if (toIndex === -1) { - return newData.concat(tab); - } else { - newData.splice(toIndex, 0, tab); - return newData; - } - }); + setColumns((cols) => moveItem(cols, fromIndex, toIndex)); }, []); const handleChange = () => {