From 30a38935ba90f01d84ec9b891fc70544094a195b Mon Sep 17 00:00:00 2001 From: Andis Redmans Date: Thu, 17 Oct 2024 19:10:45 +0300 Subject: [PATCH] feat: first version first version --- .../UIComboBox/dummy/ItemInput.scss | 5 + .../components/UIComboBox/dummy/ItemInput.tsx | 73 ++++++ .../UIComboBox/dummy/UIComboBoxDummy.tsx | 214 ++++++++++++++++++ .../src/components/UIComboBox/dummy/hooks.ts | 139 ++++++++++++ .../src/components/UIComboBox/dummy/index.tsx | 1 + .../src/components/UIComboBox/dummy/types.ts | 9 + .../UIComboBox/dummy/utils/index.ts | 2 + .../UIComboBox/dummy/utils/types.ts | 17 ++ .../UIComboBox/dummy/utils/utils.ts | 104 +++++++++ .../src/components/UIComboBox/index.tsx | 1 + .../stories/UIComboboxWithSubMenu.story.tsx | 141 ++++++++++++ 11 files changed, 706 insertions(+) create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/ItemInput.scss create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/ItemInput.tsx create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/UIComboBoxDummy.tsx create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/hooks.ts create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/index.tsx create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/types.ts create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/utils/index.ts create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/utils/types.ts create mode 100644 packages/ui-components/src/components/UIComboBox/dummy/utils/utils.ts create mode 100644 packages/ui-components/stories/UIComboboxWithSubMenu.story.tsx diff --git a/packages/ui-components/src/components/UIComboBox/dummy/ItemInput.scss b/packages/ui-components/src/components/UIComboBox/dummy/ItemInput.scss new file mode 100644 index 0000000000..5f81bbadd2 --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/ItemInput.scss @@ -0,0 +1,5 @@ +.dropdown-item-input { + input { + display: block !important; + } +} diff --git a/packages/ui-components/src/components/UIComboBox/dummy/ItemInput.tsx b/packages/ui-components/src/components/UIComboBox/dummy/ItemInput.tsx new file mode 100644 index 0000000000..1e033421eb --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/ItemInput.tsx @@ -0,0 +1,73 @@ +import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; +import type { ReactElement } from 'react'; +import { UITextInput } from '../../UIInput'; +import type { UITextInputProps } from '../../UIInput'; +import { UIContextualMenuItem } from '../../UIContextualMenu'; +import { UISelectableOptionWithSubValues } from './types'; +import { RenamedEntry } from './utils'; +import { useEditValue } from './hooks'; + +import './ItemInput.scss'; + +export interface ItemInputProps extends UITextInputProps { + option?: UISelectableOptionWithSubValues; + renamedEntry?: string; +} + +export interface ItemInputRef { + setOption: (option: UISelectableOptionWithSubValues) => void; +} + +function getSubValueText(option?: UISelectableOptionWithSubValues): string | undefined { + return option?.subValue?.text ?? option?.text; +} + +function ItemInputComponent(props: ItemInputProps, ref: React.ForwardedRef): React.ReactElement { + const { option, renamedEntry, ...inputProps } = props; + const { value, onChange, onClick } = inputProps; + const [subValue, setSubValue] = useState(getSubValueText(option)); + const [localValue, placeholder, setLocalValue] = useEditValue('', value, renamedEntry); + + useImperativeHandle(ref, () => ({ + setOption: (option: UISelectableOptionWithSubValues) => { + setSubValue(getSubValueText(option)); + } + })); + + useEffect(() => { + setSubValue(getSubValueText(option)); + }, [option]); + + const onLocalChange = (event: React.FormEvent, newValue?: string) => { + setLocalValue(newValue ?? ''); + onChange?.(event, newValue); + }; + + return ( +
+ { + console.log('mouse down!!'); + const target = event.target as HTMLElement; + (document.activeElement as HTMLElement)?.blur(); + target.focus(); + event.stopPropagation(); + }} + {...inputProps} + onClick={(event) => { + event.preventDefault(); + event.stopPropagation(); + onClick?.(event); + }} + onChange={onLocalChange} + placeholder={placeholder} + value={!placeholder ? localValue : ''} + /> + {subValue} +
+ ); +} +export const ItemInput = forwardRef(ItemInputComponent); + +ItemInput.displayName = 'ItemInput'; diff --git a/packages/ui-components/src/components/UIComboBox/dummy/UIComboBoxDummy.tsx b/packages/ui-components/src/components/UIComboBox/dummy/UIComboBoxDummy.tsx new file mode 100644 index 0000000000..30ab5f6c99 --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/UIComboBoxDummy.tsx @@ -0,0 +1,214 @@ +import React, { Ref, useEffect, useRef, useState } from 'react'; +import { UIComboBox } from '../UIComboBox'; +import type { UIComboBoxProps, UIComboBoxRef, UISelectableOption } from '../UIComboBox'; +import type { IComboBoxOption, ISelectableOption } from '@fluentui/react'; +import { UITextInput } from '../../UIInput'; +import { UIContextualMenu, UIContextualMenuItem } from '../../UIContextualMenu'; +import { useOptions, useSelectedKey } from './hooks'; +import { UISelectableOptionWithSubValues } from './types'; +import { ItemInput, ItemInputRef } from './ItemInput'; +import { isValueValid, RenamedEntries, resolveValue, resolveValueForOption, updateEditableEntry } from './utils'; + +export interface UIComboboxTestProps extends UIComboBoxProps { + /** + * Collection of options for this ComboBox. + */ + options: UISelectableOptionWithSubValues[]; +} + +interface SubMenuData { + target: HTMLElement | null; + option?: UISelectableOptionWithSubValues; +} + +function getOption( + options: UISelectableOptionWithSubValues[], + key?: string | number +): UISelectableOptionWithSubValues | undefined { + return options.find((option) => option.key === key); +} + +export const UIComboBoxDummy = (props: UIComboboxTestProps) => { + const { options, onChange } = props; + const [selectedKey, setSelectedKey, convertedOptions] = useOptions(props.selectedKey, options); + const [subMenu, setSubMenu] = useState(null); + const { target, option: activeOption } = subMenu ?? {}; + const inputItemRefs = useRef<{ [key: string]: ItemInputRef | null }>({}); + const [_pendingText, setPendingText] = useState(undefined); + // console.log('UIComboBoxDummy -> ' + selectedKey); + + const triggerChange = ( + event: React.FormEvent, + selectedOption?: UISelectableOptionWithSubValues, + index?: number, + value?: string + ) => { + if (selectedOption) { + setSelectedKey(selectedOption.key); + } + const option = getOption(convertedOptions, selectedOption?.key); + const resolveValue = option ? resolveValueForOption(option) : selectedOption?.key.toString(); + // console.log(resolveValue); + if (selectedOption?.editable && option && !isValueValid(option)) { + console.log('Invalid!!!'); + onChange?.(event, undefined, undefined, ''); + } else { + console.log('valid!!!'); + onChange?.( + event, + selectedOption ? { ...selectedOption, key: resolveValue ?? selectedOption.key } : undefined, + index, + resolveValue ?? value + ); + } + + // Close submenu + setSubMenu(null); + }; + + return ( + <> + , + selectedOption?: UISelectableOptionWithSubValues, + index?: number, + value?: string + ) => { + console.log('onchange!!!'); + + triggerChange(event, selectedOption, index, value); + }} + onItemClick={( + event: React.FormEvent, + selectedOption?: UISelectableOptionWithSubValues, + index?: number + ) => { + console.log('onItemClick!!! ' + index); + + triggerChange(event, selectedOption, index); + }} + selectedKey={selectedKey} + options={convertedOptions} + onMenuOpen={() => { + console.log('onMenuOpen'); + }} + onMenuDismiss={() => { + console.log('onMenuDismiss'); + setSubMenu(null); + }} + calloutProps={{ + preventDismissOnEvent(event) { + console.log('preventDismissOnEvent ' + event.type); + let prevent = false; + if (event.type === 'focus' || event.type === 'click') { + const target = event.target as HTMLElement; + prevent = !!( + target.closest('.dropdown-submenu') || target.querySelector('.dropdown-submenu') + ); + } + console.log('preventDismissOnEvent ' + prevent); + return prevent; + } + }} + onRenderList={( + props?: UISelectableOptionWithSubValues, + defaultRender?: (props?: UISelectableOptionWithSubValues) => JSX.Element | null + ) => { + return ( +
{ + const target = event.target as HTMLElement; + const element = target.closest('[data-index]') as HTMLElement; + if (element) { + const index = element.getAttribute('data-index'); + if (index !== null) { + setSubMenu({ + target: element, + option: convertedOptions[parseInt(index)] + }); + } + } + }}> + {defaultRender?.(props)} +
+ ); + }} + onRenderOption={( + props?: UISelectableOptionWithSubValues, + defaultRender?: (props?: UISelectableOptionWithSubValues) => JSX.Element | null + ) => { + console.log(props); + if (props?.editable) { + const { subValue } = props; + const option = getOption(convertedOptions, props?.key); + return ( + { + inputItemRefs.current[props.key.toString()] = ref; + }} + renamedEntry={option?.text} + onChange={( + event: React.FormEvent, + value?: string + ) => { + if (option) { + option.text = value ?? option.text; + } + setPendingText(value); + }} + onClick={() => { + setSelectedKey(props.key); + }} + option={props} + /> + ); + } + return defaultRender?.(props); + }} + // onRenderItem={( + // props?: IComboBoxExtendsOption, + // defaultRender?: (props?: IComboBoxExtendsOption) => JSX.Element | null + // ) => { + // console.log('external onRenderItem'); + // return defaultRender?.(props); + // }} + // onChange={() => { + // console.log('change'); + // }} + /> + {target && activeOption?.options && ( + { + // No focus restore + }} + calloutProps={{ + // popupProps: { + // ref: calloutRef + // }, + onMouseLeave: (event) => { + setSubMenu(null); + } + // onPositioned: (positions) => { + // calloutPosition.current = + // positions?.elementPosition.left ?? positions?.elementPosition.right; + // } + }} + onItemClick={(ev, item?: UIContextualMenuItem) => { + if (activeOption && item) { + activeOption.subValue = item; + inputItemRefs.current[activeOption.key]?.setOption(activeOption); + } + setSubMenu(null); + }} + directionalHint={11} + shouldFocusOnMount={false} + items={activeOption.options} + /> + )} + + ); +}; diff --git a/packages/ui-components/src/components/UIComboBox/dummy/hooks.ts b/packages/ui-components/src/components/UIComboBox/dummy/hooks.ts new file mode 100644 index 0000000000..34d5791144 --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/hooks.ts @@ -0,0 +1,139 @@ +import { useEffect, useRef, useState } from 'react'; +import { UISelectableOption } from '../UIComboBox'; +import { isEditableValue, getTypeFromEditableItem, RenamedEntry, resolveValueForOption } from './utils'; +import { UISelectableOptionWithSubValues } from './types'; +import { UIContextualMenuItem } from '../../UIContextualMenu'; + +function convertToEditableOptions(data: UISelectableOption[]): UISelectableOptionWithSubValues[] { + const regularOptions = data.filter((item) => !isEditableValue(item.key)); + const editableOptions: UIContextualMenuItem[] = data + .filter((item) => isEditableValue(item.key)) + .map((option) => ({ + key: option.key.toString(), + text: getTypeFromEditableItem(option.key) + })); + + if (editableOptions.length > 0) { + const defaultOption = + editableOptions.find((options) => { + return getTypeFromEditableItem(options.key) === 'String'; + }) ?? editableOptions[0]; + const editableOption = { + ...defaultOption, + // ToDo - calculate editable option text + text: '', + options: editableOptions, + editable: true, + subValue: defaultOption + } as UISelectableOptionWithSubValues; + regularOptions.push(editableOption); + } + + return regularOptions; +} + +function findOptionByValue( + options: UISelectableOptionWithSubValues[], + value: T +): UISelectableOptionWithSubValues | undefined { + for (const option of options) { + if ( + resolveValueForOption(option) === value || + option.options?.some((subOption) => resolveValueForOption(subOption) === value) + ) { + return option; + } + } + return undefined; +} + +/** + * Hook for editable combobox options. + * + */ +// export function useOptions(originalOptions: UISelectableOption[]): [UISelectableOptionWithSubValues[]] { +// const [options, setOptions] = useState(convertToEditableOptions(originalOptions)); + +// useEffect(() => { +// const convertedOptions = convertToEditableOptions(originalOptions); +// setOptions(convertedOptions); +// }, [originalOptions]); + +// return [options]; +// } +export function useOptions( + externalSelectedKey: T, + originalOptions: UISelectableOption[] +): [T, (selectedKey: T) => void, UISelectableOptionWithSubValues[]] { + const [options, setOptions] = useState(convertToEditableOptions(originalOptions)); + const [selectedKey, setSelectedKey] = useState(externalSelectedKey); + useEffect(() => { + const optionKey = findOptionByValue(options, externalSelectedKey); + setSelectedKey((optionKey?.key as T) ?? externalSelectedKey); + }, [externalSelectedKey]); + + useEffect(() => { + const convertedOptions = convertToEditableOptions(originalOptions); + setOptions(convertedOptions); + }, [originalOptions]); + + return [selectedKey, setSelectedKey, options]; +} + +export function useSelectedKey( + externalSelectedKey: T, + options: UISelectableOptionWithSubValues[] +): [T, (selectedKey: T) => void] { + const [selectedKey, setSelectedKey] = useState(externalSelectedKey); + useEffect(() => { + setSelectedKey(externalSelectedKey); + }, [externalSelectedKey]); + + return [selectedKey, setSelectedKey]; +} + +// DUPLICATE!!!! +export function convertToPlaceholderText(placeholder: string): string { + const type = getTypeFromEditableItem(placeholder); + if (type) { + // return `Enter new ${type} property`; + return `Enter new property`; + } + + return placeholder; +} + +/** + * Hook for value update for input components. + * + * @param initialValue - Initial/default value + * @param propValue - External value from component properties + * @returns Returns a stateful value, and a function to update it. + */ +export function useEditValue( + initialValue?: string, + propValue?: string, + editedValue?: string | undefined +): [string | undefined, string | undefined, (value: string | undefined) => void] { + const [value, setValue] = useState(editedValue ?? propValue ?? initialValue); + const edited = useRef(!!editedValue); + + useEffect(() => { + if (editedValue) { + edited.current = true; + } + // Update the local state value if new value from props is received + // const externalValue = renamedEntry?.displayValue ?? propValue; + const externalValue = editedValue; + if (externalValue && externalValue !== value) { + setValue(externalValue); + } + }, [propValue, editedValue]); + + const updateValue = (newValue: string | undefined) => { + setValue(newValue); + edited.current = true; + }; + const placeholder = propValue && (!edited.current || !value) ? convertToPlaceholderText(propValue) : undefined; + return [value, placeholder, updateValue]; +} diff --git a/packages/ui-components/src/components/UIComboBox/dummy/index.tsx b/packages/ui-components/src/components/UIComboBox/dummy/index.tsx new file mode 100644 index 0000000000..8d8e847aeb --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/index.tsx @@ -0,0 +1 @@ +export * from './UIComboBoxDummy'; diff --git a/packages/ui-components/src/components/UIComboBox/dummy/types.ts b/packages/ui-components/src/components/UIComboBox/dummy/types.ts new file mode 100644 index 0000000000..1a49f9188f --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/types.ts @@ -0,0 +1,9 @@ +import { UIContextualMenuItem } from "../../UIContextualMenu"; +import { UISelectableOption } from "../UIComboBox"; + +export interface UISelectableOptionWithSubValues extends UISelectableOption { + options?: UIContextualMenuItem[]; + subValue?: UIContextualMenuItem; + editable?: boolean; + // editedValue?: string; +} diff --git a/packages/ui-components/src/components/UIComboBox/dummy/utils/index.ts b/packages/ui-components/src/components/UIComboBox/dummy/utils/index.ts new file mode 100644 index 0000000000..f0c4eaa5e0 --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/utils/index.ts @@ -0,0 +1,2 @@ +export * from './utils'; +export * from './types'; diff --git a/packages/ui-components/src/components/UIComboBox/dummy/utils/types.ts b/packages/ui-components/src/components/UIComboBox/dummy/utils/types.ts new file mode 100644 index 0000000000..0844fd8b74 --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/utils/types.ts @@ -0,0 +1,17 @@ +import { UIContextualMenuItem } from "../../../UIContextualMenu"; + +export interface RenamedEntries { + [key: string]: RenamedEntry; +} + +export interface RenamedEntry { + fullValue?: string; + displayValue?: string; + subValue?: UIContextualMenuItem; +} + +export const EDITABLE_ENTRY_PREFIX_REPLACEMENT = ['zz_']; +export const EDITABLE_ENTRY_PREFIXES = ['zz_new']; // TODO reuse PREFIX_NEW from '@sap/ux-fiori-ai-project-generator' ? + +// export const EDITABLE_ENTRY_PREFIX_REPLACEMENT = ['crea']; +// export const EDITABLE_ENTRY_PREFIXES = ['name', 'created']; diff --git a/packages/ui-components/src/components/UIComboBox/dummy/utils/utils.ts b/packages/ui-components/src/components/UIComboBox/dummy/utils/utils.ts new file mode 100644 index 0000000000..e61f2fa03f --- /dev/null +++ b/packages/ui-components/src/components/UIComboBox/dummy/utils/utils.ts @@ -0,0 +1,104 @@ +import { useCallback, useRef } from 'react'; +import { EDITABLE_ENTRY_PREFIXES, type RenamedEntries } from './types'; +import { UIContextualMenuItem } from '../../../UIContextualMenu'; +import { UISelectableOptionWithSubValues } from '../types'; + +export const useRenames = (): [RenamedEntries, (updatedEntries?: RenamedEntries) => void] => { + const renames = useRef({}); + const updateEntries = useCallback( + (updatedEntries?: RenamedEntries) => { + renames.current = updatedEntries ?? {}; + }, + [renames.current] + ); + return [renames.current, updateEntries]; +}; + +export const isValueEmpty = (value: string, renamedEntries: RenamedEntries): boolean => { + if (isEditableValue(value)) { + const renamedValue = renamedEntries[value]; + return !renamedValue?.displayValue; + } + return !value; +}; + +export const resolveValues = (values: string[], renamedEntries: RenamedEntries): string[] => { + const valuesAfterRename = [...values]; + for (let i = 0; i < valuesAfterRename.length; i++) { + valuesAfterRename[i] = resolveValue(valuesAfterRename[i], renamedEntries); + } + return valuesAfterRename; +}; + +export const resolveValue = (value: string | number, renamedEntries: RenamedEntries): string => { + const renamedValue = renamedEntries[value]; + if (renamedValue?.displayValue !== undefined) { + if (renamedValue.subValue) { + value = renamedValue.subValue.key; + } + return `${value}-${renamedValue.displayValue.replace(/\s/g, '')}`; + } + return value.toString(); +}; + +export function isEditableValue(value?: string | number): boolean { + if (!value) { + return false; + } + const segments = value.toString().split('/'); + const editValue = segments[segments.length - 1]; + return EDITABLE_ENTRY_PREFIXES.some((prefix) => editValue.startsWith(prefix)); +} + +export function getTypeFromEditableItem(value: string | number): string | undefined { + const valueStr = value.toString(); + for (const prefix of EDITABLE_ENTRY_PREFIXES) { + if (!valueStr.toLocaleLowerCase().startsWith(prefix)) { + continue; + } + // Text meets prefix requirement - extract data type (after prefix, before first digit character) + const firstNumberIndex = valueStr.search(/\d/); + return firstNumberIndex > prefix.length + ? valueStr.substring(prefix.length, firstNumberIndex) + : valueStr.substring(prefix.length); + } +} + +export const updateEditableEntry = ( + renamedEntries: RenamedEntries, + key: string | number, + value?: string, + subValue?: UIContextualMenuItem +): void => { + const keyStr = key.toString(); + let renamedEntry = renamedEntries[keyStr]; + if (!renamedEntry) { + renamedEntry = renamedEntries[keyStr] = {}; + } + if (value !== undefined) { + renamedEntries[keyStr].fullValue = keyStr; + renamedEntries[keyStr].displayValue = value; + } + if (subValue !== undefined) { + renamedEntries[keyStr].subValue = subValue; + } +}; + +export const resolveValueForOption = (option: UISelectableOptionWithSubValues | UIContextualMenuItem): string => { + if (!option.editable) { + return option.key.toString(); + } + const { text, subValue } = option; + let value = subValue ? subValue.key : option.key; + if (text !== undefined) { + return `${value}-${text.replace(/\s/g, '')}`; + } + return value.toString(); +}; + +export const isValueValid = (option: UISelectableOptionWithSubValues | UIContextualMenuItem): boolean => { + if (option.editable && !option.text) { + return false; + } + return true; +}; diff --git a/packages/ui-components/src/components/UIComboBox/index.tsx b/packages/ui-components/src/components/UIComboBox/index.tsx index 5da8c9e649..ad67285b94 100644 --- a/packages/ui-components/src/components/UIComboBox/index.tsx +++ b/packages/ui-components/src/components/UIComboBox/index.tsx @@ -1 +1,2 @@ export * from './UIComboBox'; +export * from './dummy'; diff --git a/packages/ui-components/stories/UIComboboxWithSubMenu.story.tsx b/packages/ui-components/stories/UIComboboxWithSubMenu.story.tsx new file mode 100644 index 0000000000..172d491134 --- /dev/null +++ b/packages/ui-components/stories/UIComboboxWithSubMenu.story.tsx @@ -0,0 +1,141 @@ +import type { SetStateAction } from 'react'; +import React, { useState } from 'react'; +import { Stack } from '@fluentui/react'; +import type { IComboBox, IComboBoxOption } from '@fluentui/react'; + +import { + UIComboBox, + UIComboBoxLoaderType, + UISelectableOptionMenuItemType, + UIComboBoxDummy, + UIComboBoxOption +} from '../src/components/UIComboBox'; +import { UICheckbox } from '../src/components/UICheckbox'; +import { data, groupsData } from '../test/__mock__/select-data'; + +import { initIcons } from '../src/components/Icons'; +import { UITextInput } from '../src/components'; + +initIcons(); + +export default { title: 'Dropdowns/Combobox SubMenu' }; + +const editableEntries = ['AR', 'BR', 'DK']; + +const tempData = data.map((item) => { + if (editableEntries.includes(item.key)) { + return { + ...item, + editable: true + }; + } + return item; +}); + +export const generic = (): JSX.Element => ( +
+ + +
+ +
+
+); + +const editableSingleData = [ + { key: 'tripName', text: 'tripName' }, + { key: 'employee', text: 'employee' }, + { key: 'status', text: 'status' }, + { key: 'qqqqqq1', text: 'qqqqqq1' }, + { key: 'concattesteeee', text: 'concattesteeee' }, + { key: 'zz_newString', text: 'zz_newString' } +]; + +export const editableSingle = (): JSX.Element => ( +
+ + +
+ +
+
+); + +const editableMultipleData = [ + { key: 'tripName', text: 'tripName' }, + { key: 'employee', text: 'employee' }, + { key: 'status', text: 'status' }, + { key: 'qqqqqq1', text: 'qqqqqq1' }, + { key: 'concattesteeee', text: 'concattesteeee' }, + { key: 'zz_newString', text: 'zz_newString' }, + { key: 'zz_newDouble', text: 'zz_newDouble' }, + { key: 'zz_newInteger', text: 'zz_newInteger' }, + { key: 'zz_newDecimal', text: 'zz_newDecimal' }, + { key: 'zz_newDate', text: 'zz_newDate' } +]; + +export const editableMultiple = (): JSX.Element => { + const [option, setOption] = useState(); + const [selectedKey, setSelectedKey] = useState(); + console.log(`editableMultiple -> ${selectedKey}`); + return ( +
+ { + setOption(option); + setSelectedKey(option?.key); + }} + /> + +
+ {JSON.stringify(option, (key, value) => { + if (['styles', 'options', 'submenuIconProps'].includes(key)) return undefined; + + return value; + })} +
+
+ +
+
+ ); +};