import React from 'react'; import { LabelGroup, Label, Button, Form, FormGroup, TextInput, Menu, MenuContent, MenuList, MenuItem, MenuToggle, Radio, Popper } from '@patternfly/react-core'; import { Modal as ModalDeprecated, ModalVariant as ModalVariantDeprecated } from '@patternfly/react-core/deprecated'; import InfoCircleIcon from '@patternfly/react-icons/dist/esm/icons/info-circle-icon'; export const LabelGroupEditableAddModal: React.FunctionComponent = () => { const [isModalOpen, setModalOpen] = React.useState(false); const [idIndex, setIdIndex] = React.useState(7); const [labelText, setLabelText] = React.useState(''); const [color, setColor] = React.useState(); const [icon, setIcon] = React.useState(); const [labelType, setLabelType] = React.useState('filled'); const [isClosable, setIsCloseable] = React.useState(false); const [isEditable, setIsEditable] = React.useState(false); const labelInputRef = React.useRef(null); const [isColorOpen, setIsColorOpen] = React.useState(false); const colorMenuRef = React.useRef(null); const colorContainerRef = React.useRef(null); const colorToggleRef = React.useRef(null); const [isIconOpen, setIsIconOpen] = React.useState(false); const iconMenuRef = React.useRef(null); const iconContainerRef = React.useRef(null); const iconToggleRef = React.useRef(null); const [labels, setLabels] = React.useState([ { name: 'Label 1', id: 4 }, { name: 'Label 2', id: 5 }, { name: 'Label 3', props: { isEditable: true, editableProps: { 'aria-label': 'Editable label with text Label 3' } }, id: 6 } ]); const onClose = (labelId: string) => { setLabels(labels.filter((l: any) => l.id !== labelId)); }; const onEdit = (nextText: string, index: number) => { const copy = [...labels]; const updatedProps = { ...labels[index].props, editableProps: { 'aria-label': `Editable label with text ${nextText}` } }; copy[index] = { name: nextText, props: updatedProps, id: labels[index].id }; setLabels(copy); }; const onAdd = () => { let labelIcon: any; if (icon === 'Info circle icon') { labelIcon = ; } setLabels([ { name: labelText || 'New Label', props: { color: color ? color.toLowerCase() : 'gray', icon: labelIcon, variant: labelType || 'filled', ...(!isClosable && isClosable !== undefined && { onClose: null }), isEditable: isEditable !== undefined ? isEditable : true, ...(isEditable && { editableProps: { 'aria-label': `Editable label with text ${labelText || 'New Label'}` } }) }, id: idIndex }, ...labels ]); setModalOpen(!isModalOpen); setIdIndex(idIndex + 1); setLabelText(''); setColor(''); setIcon(null); setLabelType('filled'); setIsCloseable(false); setIsEditable(false); }; const handleModalToggle = (_event: KeyboardEvent | React.MouseEvent) => { setModalOpen(!isModalOpen); }; React.useEffect(() => { if (isModalOpen && labelInputRef && labelInputRef.current) { (labelInputRef.current as HTMLInputElement).focus(); } }, [isModalOpen]); const handleMenuKeys = (event: KeyboardEvent) => { if (isColorOpen && colorMenuRef?.current?.contains(event.target as Node)) { if (event.key === 'Escape' || event.key === 'Tab') { setIsColorOpen(!isColorOpen); colorToggleRef?.current?.focus(); } } if (isIconOpen && iconMenuRef?.current?.contains(event.target as Node)) { if (event.key === 'Escape' || event.key === 'Tab') { setIsIconOpen(!isIconOpen); iconToggleRef?.current?.focus(); } } }; const handleClickOutside = (event: MouseEvent) => { if (isColorOpen && !colorMenuRef?.current?.contains(event.target as Node)) { setIsColorOpen(false); } if (isIconOpen && !iconMenuRef?.current?.contains(event.target as Node)) { setIsIconOpen(false); } }; React.useEffect(() => { window.addEventListener('keydown', handleMenuKeys); window.addEventListener('click', handleClickOutside); return () => { window.removeEventListener('keydown', handleMenuKeys); window.removeEventListener('click', handleClickOutside); }; }, [isColorOpen, isIconOpen, colorMenuRef, iconMenuRef]); const onColorToggleClick = (ev: React.MouseEvent) => { ev.stopPropagation(); // Stop handleClickOutside from handling setTimeout(() => { if (colorMenuRef.current) { const firstElement = colorMenuRef.current.querySelector('li > button:not(:disabled)'); firstElement && (firstElement as HTMLElement).focus(); } }, 0); setIsColorOpen(!isColorOpen); }; const colorToggle = ( {color || 'Select'} ); const colorMenu = ( { setColor(itemId?.toString()); colorToggleRef?.current?.focus(); setIsColorOpen(false); }} selected={color} > Gray Blue Green Orange Red Purple Teal ); const onIconToggleClick = (ev: React.MouseEvent) => { ev.stopPropagation(); // Stop handleClickOutside from handling setTimeout(() => { if (iconMenuRef.current) { const firstElement = iconMenuRef.current.querySelector('li > button:not(:disabled)'); firstElement && (firstElement as HTMLElement).focus(); } }, 0); setIsIconOpen(!isIconOpen); }; const iconToggle = ( {icon ? '' : 'Select'} ); const iconMenu = ( { setIcon(itemId?.toString()); iconToggleRef?.current?.focus(); setIsIconOpen(false); }} selected={icon} > No icon Info circle icon ); return (
Add label } > {labels.map((label: { name: string; id: string; props: any }, index: number) => ( onClose(label.id)} onEditCancel={(_event, prevText) => onEdit(prevText, index)} onEditComplete={(_event, newText) => onEdit(newText, index)} {...label.props} > {label.name} ))} Save ,