diff --git a/packages/react-integration/cypress/integration/form.spec.ts b/packages/react-integration/cypress/integration/form.spec.ts index b8b6a684aa3..9268201ff92 100644 --- a/packages/react-integration/cypress/integration/form.spec.ts +++ b/packages/react-integration/cypress/integration/form.spec.ts @@ -1,4 +1,4 @@ -xdescribe('Form Demo Test', () => { +describe('Form Demo Test', () => { it('Navigate to demo section', () => { cy.visit('http://localhost:3000/form-demo-nav-link'); }); @@ -70,21 +70,21 @@ xdescribe('Form Demo Test', () => { }); it('Verify keypress can control the multi-select-typeahead', () => { - cy.get('[id*="pf-select-toggle-id"][id*="select-multi-typeahead-typeahead"]').type('{downarrow}{downarrow}{enter}'); + cy.get('.pf-v6-c-menu-toggle').type('{downarrow}{downarrow}{enter}'); cy.get('.pf-v6-c-label__text').should('exist').and('have.text', 'Florida'); cy.get('.pf-v6-c-label button').click(); - cy.get('[id*="pf-select-toggle-id"][id*="select-multi-typeahead-typeahead"]').type('New J'); + cy.get('.pf-v6-c-text-input-group__text-input').click().type('New J'); - cy.get('.pf-v6-c-select__menu-item').should('exist').and('have.text', 'New Jersey'); + cy.get('.pf-v6-c-menu__item').should('exist').and('have.text', 'New Jersey'); cy.focused().type('{backspace}{backspace}{backspace}{backspace}orth'); - cy.get('.pf-v6-c-select__menu-item').should('exist').and('have.text', 'North Carolina'); + cy.get('.pf-v6-c-menu__item').should('exist').and('have.text', 'North Carolina'); cy.focused().type('{backspace}{backspace}{backspace}{backspace}{backspace}'); // @ts-ignore cy.tab(); - cy.get('.pf-v6-c-select__menu-item').should('not.exist'); + cy.get('.pf-v6-c-menu__item').should('not.exist'); }); it('Verify pressing spacebar selects the checkbox component', () => { diff --git a/packages/react-integration/cypress/integration/page.spec.ts b/packages/react-integration/cypress/integration/page.spec.ts index 454edfd1aed..b482feed013 100644 --- a/packages/react-integration/cypress/integration/page.spec.ts +++ b/packages/react-integration/cypress/integration/page.spec.ts @@ -3,7 +3,7 @@ describe('Page Demo Test', () => { cy.visit('http://localhost:3000/page-demo-nav-link'); }); - xit('Test Page elements', () => { + it('Test Page elements', () => { cy.get('#page-demo').within(() => { cy.get('#nav-toggle').then((hamburgerIcon: JQuery) => { cy.get('.pf-v6-c-page__sidebar.pf-m-expanded').should('exist'); @@ -12,9 +12,11 @@ describe('Page Demo Test', () => { cy.get('.pf-v6-c-page__sidebar.pf-m-collapsed').should('exist'); cy.get('.pf-v6-c-page__sidebar.pf-m-expanded').should('not.exist'); }); - cy.get('#page-demo-header').should('not.have.attr', 'role'); + cy.get('#page-demo-masthead').should('not.have.attr', 'role'); cy.get('#page-demo-page-id').should('not.have.attr', 'role'); - cy.get('div[class="pf-v6-c-page__header-brand-link"]').invoke('text').should('eq', "Logo that's a
"); + cy.get( + '#page-demo-masthead > .pf-v6-c-masthead__main > .pf-v6-c-masthead__brand > .pf-v6-c-masthead__logo' + ).should('exist'); cy.get('.pf-v6-c-page__main-section.pf-m-no-padding').should('exist'); cy.get('.pf-v6-c-page__main-section.pf-m-no-padding-on-md').should('exist'); }); diff --git a/packages/react-integration/cypress/integration/tableeditable.spec.ts b/packages/react-integration/cypress/integration/tableeditable.spec.ts index 9271bcd66e2..dce45244d4d 100644 --- a/packages/react-integration/cypress/integration/tableeditable.spec.ts +++ b/packages/react-integration/cypress/integration/tableeditable.spec.ts @@ -1,4 +1,4 @@ -xdescribe('Table Simple Test', () => { +describe('Table Simple Test', () => { it('Navigate to demo section', () => { cy.visit('http://localhost:3000/table-editable-demo-nav-link'); }); @@ -20,9 +20,9 @@ xdescribe('Table Simple Test', () => { '.pf-m-inline-editable > [data-label="Text input col 1"] > .pf-v6-c-inline-edit__input > .pf-v6-c-form-control > input' ).type('test'); cy.get( - '.pf-m-inline-editable > [data-label="Dropdown col 5"] > .pf-v6-c-inline-edit__input > .pf-v6-c-select > .pf-v6-c-select__toggle > .pf-v6-c-select__toggle-button' + '.pf-m-inline-editable > [data-label="Dropdown col 5"] > .pf-v6-c-inline-edit__input > .pf-v6-c-menu-toggle > .pf-v6-c-menu-toggle__controls' ).click(); - cy.get(':nth-child(4) > .pf-v6-c-check__label').click(); + cy.get('#uniqueIdRow1Cell5Option3').click(); cy.get( '.pf-m-inline-editable > .pf-v6-c-table__inline-edit-action > .pf-v6-c-inline-edit__group > :nth-child(1) > .pf-v6-c-button' ).click(); @@ -46,9 +46,9 @@ xdescribe('Table Simple Test', () => { .clear() .type('xyz'); cy.get( - '.pf-m-inline-editable:nth-of-type(2) > [data-label="Dropdown col 5"] > .pf-v6-c-inline-edit__input > .pf-v6-c-select > .pf-v6-c-select__toggle > .pf-v6-c-select__toggle-button' + '.pf-m-inline-editable > [data-label="Dropdown col 5"] > .pf-v6-c-inline-edit__input > .pf-v6-c-menu-toggle > .pf-v6-c-menu-toggle__controls' ).click(); - cy.get('#uniqueIdRow2Cell5Option3 > .pf-v6-c-select__menu-item').click(); + cy.get('#uniqueIdRow2Cell5Option3').click(); cy.get( '.pf-m-inline-editable:nth-of-type(2) > .pf-v6-c-table__inline-edit-action > .pf-v6-c-inline-edit__group > :nth-child(2) > .pf-v6-c-button' ).click(); diff --git a/packages/react-integration/cypress/integration/toolbar.spec.ts b/packages/react-integration/cypress/integration/toolbar.spec.ts index e03f34570f1..ca68288c0d4 100644 --- a/packages/react-integration/cypress/integration/toolbar.spec.ts +++ b/packages/react-integration/cypress/integration/toolbar.spec.ts @@ -1,4 +1,4 @@ -xdescribe('Data Toolbar Demo Test', () => { +describe('Data Toolbar Demo Test', () => { it('Navigate to demo section', () => { cy.visit('http://localhost:3000/toolbar-demo-nav-link'); }); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/FormDemo/FormDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/FormDemo/FormDemo.tsx index c23e1009574..4ec2c07d163 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/FormDemo/FormDemo.tsx +++ b/packages/react-integration/demo-app-ts/src/components/demos/FormDemo/FormDemo.tsx @@ -1,12 +1,12 @@ import React, { Component } from 'react'; import { + Button, Divider, Form, FormGroup, FormGroupLabelHelp, FormProps, FormSection, - TextInput, Checkbox, Popover, ValidatedOptions, @@ -16,19 +16,42 @@ import { Select, SelectList, SelectOption, - MenuToggle + SelectOptionProps, + TextInput, + TextInputGroup, + TextInputGroupUtilities, + TextInputGroupMain, + Label, + LabelGroup, + MenuToggle, + MenuToggleElement } from '@patternfly/react-core'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon'; +import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon'; import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing'; +const initialSelectOptions = [ + { value: 'Alabama', children: 'Alabama' }, + { value: 'Florida', children: 'Florida' }, + { value: 'New Jersey', children: 'New Jersey' }, + { value: 'New Mexico', children: 'New Mexico' }, + { value: 'New York', children: 'New York' }, + { value: 'North Carolina', children: 'North Carolina' } +]; + +const NO_RESULTS = 'no results'; export interface FormState { value: string; isValid: boolean; isOpen: boolean; selected: string[]; + selectOptions: SelectOptionProps[]; validatedValue: string; validated: ValidatedOptions.default | ValidatedOptions.error | ValidatedOptions.warning | ValidatedOptions.success; checkboxChecked: boolean; + inputValue: string; + focusedItemIndex: number | null; + activeItemId: string | null; } export class FormDemo extends Component { @@ -39,19 +62,25 @@ export class FormDemo extends Component { isValid: false, isOpen: false, selected: [], + selectOptions: initialSelectOptions, validatedValue: '', validated: ValidatedOptions.default, - checkboxChecked: false + checkboxChecked: false, + inputValue: '', + focusedItemIndex: null, + activeItemId: null }; this.handleCheckboxChange = this.handleCheckboxChange.bind(this); } labelHelpRef: React.RefObject = React.createRef(); + textInputRef: React.RefObject = React.createRef(); handleTextInputChange = (_event: React.FormEvent, value: string) => { this.setState({ value, isValid: /^\d+$/.test(value) }); }; + handleValidatedTextInputChange = (_event: React.FormEvent, value: string) => { let validated = ValidatedOptions.default; if (value.length === 0) { @@ -61,12 +90,29 @@ export class FormDemo extends Component { } this.setState({ validatedValue: value, validated }); }; - onToggle = (_event: any) => { + + createItemId = (value: any) => `select-multi-typeahead-${value.replace(' ', '-')}`; + + setActiveAndFocusedItem = (itemIndex: number) => { this.setState({ - isOpen: !this.state.isOpen + focusedItemIndex: itemIndex + }); + const focusedItem = this.state.selectOptions[itemIndex]; + this.setState({ + activeItemId: this.createItemId(focusedItem.value) + }); + }; + + resetActiveAndFocusedItem = () => { + this.setState({ + focusedItemIndex: null + }); + this.setState({ + activeItemId: null }); }; - onSelect = (_event: React.MouseEvent | undefined, selection: string | number | undefined) => { + + onSelect = (_ev: any, selection: string | number | undefined) => { const { selected } = this.state; if (selection) { if (selected.includes(selection.toString())) { @@ -83,6 +129,129 @@ export class FormDemo extends Component { ); } } + this.textInputRef.current?.focus(); + }; + + handleMenuArrowKeys = (key: string) => { + const { selectOptions, isOpen, focusedItemIndex } = this.state; + let indexToFocus = 0; + + if (!isOpen) { + this.setState({ + isOpen: true + }); + } + + if (selectOptions.every((option) => option.isDisabled)) { + return; + } + + if (key === 'ArrowUp') { + // When no index is set or at the first index, focus to the last, otherwise decrement focus index + if (focusedItemIndex === null || focusedItemIndex === 0) { + indexToFocus = selectOptions.length - 1; + } else { + indexToFocus = focusedItemIndex - 1; + } + + // Skip disabled options + while (selectOptions[indexToFocus].isDisabled) { + indexToFocus--; + if (indexToFocus === -1) { + indexToFocus = selectOptions.length - 1; + } + } + } + + if (key === 'ArrowDown') { + // When no index is set or at the last index, focus to the first, otherwise increment focus index + if (focusedItemIndex === null || focusedItemIndex === selectOptions.length - 1) { + indexToFocus = 0; + } else { + indexToFocus = focusedItemIndex + 1; + } + + // Skip disabled options + while (selectOptions[indexToFocus].isDisabled) { + indexToFocus++; + if (indexToFocus === selectOptions.length) { + indexToFocus = 0; + } + } + } + + this.setActiveAndFocusedItem(indexToFocus); + }; + + onInputKeyDown = (event: React.KeyboardEvent) => { + const { selectOptions, isOpen, focusedItemIndex } = this.state; + const focusedItem = focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null; + + switch (event.key) { + case 'Enter': + if (isOpen && focusedItem && focusedItem.value !== NO_RESULTS && !focusedItem.isAriaDisabled) { + this.onSelect(event, focusedItem.value); + } + + if (!isOpen) { + this.setState({ + isOpen: true + }); + } + + break; + case 'ArrowUp': + case 'ArrowDown': + event.preventDefault(); + this.handleMenuArrowKeys(event.key); + break; + } + }; + + onToggle = (_event: any) => { + this.setState({ + isOpen: !this.state.isOpen + }); + this.textInputRef?.current?.focus(); + }; + + closeMenu = () => { + this.setState({ + isOpen: false + }); + this.resetActiveAndFocusedItem(); + }; + + onInputClick = () => { + if (!this.state.isOpen) { + this.setState({ isOpen: true }); + } else if (!this.state.inputValue) { + this.closeMenu(); + } + }; + + onTextInputChange = (_event: React.FormEvent, value: string) => { + let newSelectOptions: SelectOptionProps[] = initialSelectOptions; + if (value) { + newSelectOptions = initialSelectOptions.filter((menuItem) => + String(menuItem.children).toLowerCase().includes(value.toLowerCase()) + ); + if (!newSelectOptions.length) { + newSelectOptions = [{ isAriaDisabled: true, children: `No results found for "${value}"`, value: NO_RESULTS }]; + } + if (!this.state.isOpen) { + this.setState({ isOpen: true }); + } + } + this.setState({ inputValue: value }); + this.setState({ selectOptions: newSelectOptions }); + this.resetActiveAndFocusedItem(); + }; + onClearButtonClick = () => { + this.setState({ selected: [] }); + this.setState({ inputValue: '' }); + this.resetActiveAndFocusedItem(); + this.textInputRef?.current?.focus(); }; componentDidMount() { @@ -96,16 +265,70 @@ export class FormDemo extends Component { } render() { - const { value, isValid, isOpen, selected, validatedValue, validated, checkboxChecked } = this.state; + const { + value, + isValid, + isOpen, + selectOptions, + selected, + validatedValue, + validated, + checkboxChecked, + inputValue, + activeItemId + } = this.state; const titleId = 'multi-typeahead-select-id'; - const options = [ - { value: 'Alabama', disabled: false }, - { value: 'Florida', disabled: false }, - { value: 'New Jersey', disabled: false }, - { value: 'New Mexico', disabled: false }, - { value: 'New York', disabled: false }, - { value: 'North Carolina', disabled: false } - ]; + + const toggle = (toggleRef: React.Ref) => ( + + + + + {selected.map((selection, index) => ( + + ))} + + + +
} - bodyContent={ -
- Age is typically measured in years. It is also common to measure age in months for newborns, e.g. 18 - months. -
- } + headerContent="The age of a person" + bodyContent="Age is typically measured in years. It is also common to measure age in months for newborns, e.g. 18months." > @@ -153,27 +371,29 @@ export class FormDemo extends Component {
- - + <> + + + diff --git a/packages/react-integration/demo-app-ts/src/components/demos/PageDemo/PageDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/PageDemo/PageDemo.tsx index a8ef56f3122..91e8d09867c 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/PageDemo/PageDemo.tsx +++ b/packages/react-integration/demo-app-ts/src/components/demos/PageDemo/PageDemo.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import { Component } from 'react'; import { Page, PageSidebar, @@ -25,7 +25,7 @@ export class PageDemo extends Component { isKebabDropdownOpen: false }; - onNavToggle = (_event: React.MouseEvent) => { + onNavToggle = () => { this.setState({ isNavOpen: !this.state.isNavOpen }); @@ -72,10 +72,15 @@ export class PageDemo extends Component { ); const masthead = ( - + - + diff --git a/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableEditableDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableEditableDemo.tsx index 15963c692c2..3e42ebc8565 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableEditableDemo.tsx +++ b/packages/react-integration/demo-app-ts/src/components/demos/TableDemo/TableEditableDemo.tsx @@ -138,10 +138,12 @@ export class TableEditableDemo extends React.Component { clearSelection={this.clearSelection} isOpen={updatedProps.isSelectOpen} options={(updatedProps as any).options.map((option: any, index: number) => ( - + + {option.value} + ))} - onToggle={(event: any) => { - this.onToggle(event); + onToggle={(_event: any) => { + this.onToggle(rowIndex as number, cellIndex as number); }} selections={updatedProps.selected} /> @@ -161,7 +163,8 @@ export class TableEditableDemo extends React.Component { ], editableSelectProps: { variant: 'checkbox', - 'aria-label': 'Row 1 cell 5 content' + 'aria-label': 'Row 1 cell 5 content', + onOpenChange: () => this.onOpenChange(0, 4) } } } @@ -249,10 +252,12 @@ export class TableEditableDemo extends React.Component { clearSelection={this.clearSelection} isOpen={updatedProps.isSelectOpen} options={(updatedProps as any).options.map((option: any, index: number) => ( - + + {option.value} + ))} onToggle={(_event: any) => { - this.onToggle(_event); + this.onToggle(rowIndex as number, cellIndex as number); }} selections={updatedProps.selected} /> @@ -272,7 +277,8 @@ export class TableEditableDemo extends React.Component { ], editableSelectProps: { variant: 'single', - 'aria-label': 'Row 2 cell 5 content' + 'aria-label': 'Row 2 cell 5 content', + onOpenChange: () => this.onOpenChange(1, 4) } } } @@ -362,6 +368,7 @@ export class TableEditableDemo extends React.Component { newCellProps.editableValue = newSelected; newCellProps.selected = newSelected; + newCellProps.isSelectOpen = false; } this.setState({ @@ -369,11 +376,33 @@ export class TableEditableDemo extends React.Component { }); }; - onToggle = (_event: any) => { + // set open state if component closes menu on click (e.g. when you click outside of the menu) + onOpenChange = (rowIndex: number, cellIndex: number) => { const newRows = Array.from(this.state.rows); - this.setState({ - rows: newRows - }); + const rowCells = newRows[rowIndex as number].cells; + if (rowCells) { + const cell = rowCells[cellIndex as number]; + if (cell) { + (cell as IRowCell).props.isSelectOpen = !(cell as IRowCell).props.isSelectOpen; + this.setState({ + rows: newRows + }); + } + } + }; + + onToggle = (rowIndex: number, cellIndex: number) => { + const newRows = Array.from(this.state.rows); + const rowCells = newRows[rowIndex].cells; + if (rowCells) { + const cell = rowCells[cellIndex as number]; + if (cell) { + (cell as IRowCell).props.isSelectOpen = !(cell as IRowCell).props.isSelectOpen; + this.setState({ + rows: newRows + }); + } + } }; clearSelection = (_event: React.MouseEvent, rowIndex: number, cellIndex: number) => { diff --git a/packages/react-table/src/components/Table/EditableSelectInputCell.tsx b/packages/react-table/src/components/Table/EditableSelectInputCell.tsx index e139f3b1524..668d337e3ef 100644 --- a/packages/react-table/src/components/Table/EditableSelectInputCell.tsx +++ b/packages/react-table/src/components/Table/EditableSelectInputCell.tsx @@ -25,6 +25,8 @@ export interface IEditableSelectInputCell extends Omit {}, clearSelection, isOpen = false, + isPlaceholder = false, onToggle = () => {}, selections = [''], options = [] as React.ReactElement[], props }: IEditableSelectInputCell) => { - const onSelectHandler = ( - event: React.MouseEvent | React.ChangeEvent, - newValue: any | any[] - // isPlaceholder: boolean - ) => { - onSelect(event, newValue, rowIndex, cellIndex); + const onSelectHandler = (event: React.MouseEvent | React.ChangeEvent, newValue: any | any[]) => { + onSelect(event, newValue, rowIndex, cellIndex, isPlaceholder); }; const onClear = (event: React.MouseEvent) => { @@ -61,16 +60,16 @@ export const EditableSelectInputCell: React.FunctionComponent ( - + {isOpen ? 'Expanded' : 'Collapsed'} )} + {...props.editableSelectProps} > {options} diff --git a/packages/react-table/src/deprecated/components/Table/examples/Table.md b/packages/react-table/src/deprecated/components/Table/examples/Table.md index e8fd613ec9c..e7c7f92eb2f 100644 --- a/packages/react-table/src/deprecated/components/Table/examples/Table.md +++ b/packages/react-table/src/deprecated/components/Table/examples/Table.md @@ -325,9 +325,10 @@ import { applyCellEdits, EditableTextCell, EditableSelectInputCell, - SelectOption } from '@patternfly/react-table'; +import { SelectOption as NewSelectOption} from '@patternfly/react-core/dist/esm/components/Select'; + class EditableRowsTable extends React.Component { constructor(props) { super(props); @@ -412,12 +413,12 @@ class EditableRowsTable extends React.Component { onSelect={this.onSelect} isOpen={props.isSelectOpen} options={props.options.map((option, index) => ( - + {option.value} - + ))} - onToggle={(event, isOpen) => { - this.onToggle(isOpen, rowIndex, cellIndex); + onToggle={(event) => { + this.onToggle(props.isSelectOpen, rowIndex, cellIndex); }} selections={props.selected} /> @@ -435,8 +436,8 @@ class EditableRowsTable extends React.Component { { value: 'Option 5' } ], editableSelectProps: { - variant: 'single', - 'aria-label': 'Row 1 cell 4 content' + 'aria-label': 'Row 1 cell 4 content', + onOpenChange: (isOpen: boolean) => this.onOpenChange(isOpen, 0, 3) } } } @@ -505,13 +506,13 @@ class EditableRowsTable extends React.Component { isOpen={props.isSelectOpen} options={props.options.map((option, index) => { return ( - + {option.value} - + ); })} - onToggle={(event, isOpen) => { - this.onToggle(isOpen, rowIndex, cellIndex); + onToggle={(event) => { + this.onToggle(props.isSelectOpen, rowIndex, cellIndex); }} selections={props.selected} /> @@ -521,8 +522,9 @@ class EditableRowsTable extends React.Component { name: 'uniqueIdRow2Cell4', isSelectOpen: props.isSelectOpen || false, selected: props.selected || [], + isPlaceholder: true, options: [ - { value: 'Placeholder...', isPlaceholder: true }, + { value: 'Placeholder...', isPlaceholder: true}, { value: 'Option 1' }, { value: 'Option 2' }, { value: 'Option 3' }, @@ -530,9 +532,10 @@ class EditableRowsTable extends React.Component { { value: 'Option 5' } ], editableSelectProps: { - variant: 'typeaheadmulti', 'aria-label': 'Row 2 cell 4 content', - toggleId: 'editable-toggle' + toggleId: 'editable-toggle', + onOpenChange: (isOpen: boolean) => this.onOpenChange(isOpen, 1, 3) + } } } @@ -622,12 +625,12 @@ class EditableRowsTable extends React.Component { clearSelection={this.clearSelection} isOpen={props.isSelectOpen} options={props.options.map((option, index) => ( - + {option.value} - + ))} - onToggle={(event, isOpen) => { - this.onToggle(isOpen, rowIndex, cellIndex); + onToggle={(event) => { + this.onToggle(props.isSelectOpen, rowIndex, cellIndex); }} selections={props.selected} /> @@ -637,8 +640,9 @@ class EditableRowsTable extends React.Component { name: 'uniqueIdRow3Cell4', isSelectOpen: props.isSelectOpen || false, selected: props.selected || ['Option 3'], + isPlaceholder: false, options: [ - { value: 'Placeholder...', isPlaceholder: true }, + { value: 'Placeholder...', isPlaceholder: true}, { value: 'Option 1' }, { value: 'Option 2' }, { value: 'Option 3' }, @@ -646,8 +650,9 @@ class EditableRowsTable extends React.Component { { value: 'Option 5' } ], editableSelectProps: { - variant: 'checkbox', - 'aria-label': 'Row 3 cell 4 content' + 'aria-label': 'Row 3 cell 4 content', + onOpenChange: (isOpen: boolean) => this.onOpenChange(isOpen, 2, 3) + } } } @@ -735,10 +740,19 @@ class EditableRowsTable extends React.Component { }); }; + // set open state if component closes menu on click (e.g. when you click outside of the menu) + this.onOpenChange = (isOpen: boolean, rowIndex: string | number | undefined, cellIndex: string | number | undefined) => { + const newRows = Array.from(this.state.rows); + newRows[rowIndex].cells[cellIndex].props.isSelectOpen = isOpen; + this.setState({ + rows: newRows + }); + } + this.onToggle = (isOpen, rowIndex, cellIndex) => { console.log('isOpen', isOpen); let newRows = Array.from(this.state.rows); - newRows[rowIndex].cells[cellIndex].props.isSelectOpen = isOpen; + newRows[rowIndex].cells[cellIndex].props.isSelectOpen = !newRows[rowIndex].cells[cellIndex].props.isSelectOpen; this.setState({ rows: newRows });