Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Commit

Permalink
Merge branch 'main' into NavigationSideMenuKeyboardNavigation
Browse files Browse the repository at this point in the history
  • Loading branch information
MadanKumarGovindaswamy authored Apr 29, 2024
2 parents bbb33f6 + 05f7d4f commit 7ff7865
Show file tree
Hide file tree
Showing 499 changed files with 5,803 additions and 989 deletions.
400 changes: 173 additions & 227 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions packages/terra-application-layout/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

## 5.91.0 - (April 15, 2024)

* Changed
* Minor dependency version bump.

## 5.90.0 - (April 4, 2024)

* Changed
Expand Down
4 changes: 2 additions & 2 deletions packages/terra-application-layout/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "terra-application-layout",
"version": "5.90.0",
"version": "5.91.0",
"description": "The Terra Application Layout is a responsive, themeable layout for building applications.",
"author": "Cerner Corporation",
"repository": {
Expand Down Expand Up @@ -36,7 +36,7 @@
"prop-types": "^15.5.8",
"react-router-dom": "^5.0.0",
"terra-application-header-layout": "^3.41.0",
"terra-application-links": "^6.80.0",
"terra-application-links": "^6.81.0",
"terra-application-menu-layout": "^3.32.0",
"terra-application-name": "^3.45.0",
"terra-application-utility": "^2.58.0",
Expand Down
5 changes: 5 additions & 0 deletions packages/terra-application-links/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

## 6.81.0 - (April 15, 2024)

* Added
* Added `onTabClick` property to ApplicationLinks interface.

## 6.80.0 - (April 4, 2024)

* Changed
Expand Down
2 changes: 1 addition & 1 deletion packages/terra-application-links/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "terra-application-links",
"version": "6.80.0",
"version": "6.81.0",
"description": "This packages contains a list and tab form of ApplicationLinks, to be used in horizontal and vertical display styles. Selection is managed by react-router.",
"author": "Cerner Corporation",
"repository": {
Expand Down
4 changes: 4 additions & 0 deletions packages/terra-application-links/src/ApplicationLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ const ApplicationLinksPropType = PropTypes.shape({
*/
icon: PropTypes.node,
})),
/**
* The click callback of the tab.
*/
onTabClick: PropTypes.func,
});

const ApplicationLinks = {
Expand Down
6 changes: 6 additions & 0 deletions packages/terra-application-links/src/tabs/ApplicationTabs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ const propTypes = {

icon: PropTypes.icon,
})),
/**
* The click callback of the tab.
*/
onTabClick: PropTypes.func,
/**
* The location as provided by the `withRouter()` HOC.
*/
Expand Down Expand Up @@ -150,6 +154,7 @@ class ApplicationTabs extends React.Component {
history,
staticContext,
hasIcons,
onTabClick,
...customProps
} = this.props;

Expand All @@ -165,6 +170,7 @@ class ApplicationTabs extends React.Component {
externalLink: link.externalLink,
icon: link.icon,
location,
onTabClick,
history,
};

Expand Down
4 changes: 3 additions & 1 deletion packages/terra-application-links/src/tabs/_Tab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ class ApplicationTab extends Component {

if (!this.isCurrentPath()) {
this.props.history.push(this.props.path);
} else if (this.props.onTabClick) {
}

if (this.props.onTabClick) {
this.props.onTabClick(event);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';

import ThemeContextProvider from 'terra-theme-context/lib/ThemeContextProvider';
import { BrowserRouter } from 'react-router-dom';
import ApplicationTabs from '../../src/tabs/ApplicationTabs';
import testLinkConfig from './testLinkConfig';
import testLinksWithIconsConfig from './testLinksWithIconsConfig';
Expand All @@ -11,6 +12,19 @@ it('should render ApplicationTabs with links and alignment', () => {
expect(wrapper).toMatchSnapshot();
});

it('should trigger onTabClick handler', () => {
const onTabClickHandler = jest.fn();
const wrapper = enzymeIntl.mountWithIntl(
<BrowserRouter>
<ApplicationTabs links={testLinkConfig} alignment="start" onTabClick={onTabClickHandler} />
</BrowserRouter>,
);

wrapper.find('.tab').first().simulate('click');

expect(onTabClickHandler).toHaveBeenCalled();
});

it('should render ApplicationTabs with icons', () => {
const subject = (
<div>
Expand Down
15 changes: 15 additions & 0 deletions packages/terra-collapsible-menu-view/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@

## Unreleased

## 6.99.0 - (April 23, 2024)

* Changed
* Minor dependency version bump.

## 6.98.0 - (April 18, 2024)

* Changed
* Minor dependency version bump.

## 6.97.1 - (April 17, 2024)

* Fixed
* Set aria-haspopup value to boolean.

## 6.97.0 - (April 4, 2024)

* Changed
Expand Down
4 changes: 2 additions & 2 deletions packages/terra-collapsible-menu-view/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "terra-collapsible-menu-view",
"version": "6.97.0",
"version": "6.99.0",
"description": "The collapsible menu view is a mechanism that can be used in toolbar scenarios where actionable items will be displayed face-up and flex based on the space available. Any items that can not fit in the available space will be rolled into an ellipsis menu.",
"author": "Cerner Corporation",
"repository": {
Expand Down Expand Up @@ -40,7 +40,7 @@
"terra-hyperlink": "^2.61.0",
"terra-icon": "^3.57.1",
"terra-list": "^4.0.0",
"terra-menu": "^6.91.0",
"terra-menu": "^6.94.0",
"terra-mixins": "^1.0.0",
"terra-theme-context": "^1.9.0"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class CollapsibleMenuViewItem extends React.Component {
button={(
<Button
{...attributes}
aria-haspopup="dialog"
aria-haspopup
icon={icon}
text={text}
isReversed={isReversed}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('CollapsibleMenuViewItem', () => {
<CollapsibleMenuViewItem text="Default Item 2" key="defaultItem2" />,
]}
/>);
expect(wrapper.find('Button').prop('aria-haspopup')).toEqual('dialog');
expect(wrapper.find('Button').prop('aria-haspopup')).toBe(true);
});

it('should render a disabled button when isDisabled is set', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ exports[`CollapsibleMenuViewItem should render a menu when subMenuItems are give
<CollapsibleMenu
button={
<Button
aria-haspopup="dialog"
aria-haspopup={true}
intl={
Object {
"defaultFormats": Object {},
Expand Down
30 changes: 29 additions & 1 deletion packages/terra-compact-interactive-list/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,34 @@

## Unreleased

* Changed
* Keyboard navigation updated to wrap to the next/previous line at the end/start of a visual row.

## 1.20.0 - (April 23, 2024)

* Changed
* Minor dependency version bump.

## 1.19.0 - (April 18, 2024)

* Changed
* Minor dependency version bump.

## 1.18.0 - (April 17, 2024)

* Changed
* Minor dependency version bump.

## 1.17.0 - (April 15, 2024)

* Changed
* Minor dependency version bump.

## 1.16.0 - (April 10, 2024)

* Changed
* Changed to avoid focus being set to the first cell on multiple re-renders.

## 1.15.0 - (April 4, 2024)

* Changed
Expand Down Expand Up @@ -122,4 +150,4 @@

## 1.0.0-alpha.1 - (November 22, 2023)

* Initial package release.
* Initial package release.
4 changes: 2 additions & 2 deletions packages/terra-compact-interactive-list/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "terra-compact-interactive-list",
"version": "1.15.0",
"version": "1.20.0",
"description": "The Terra Compact Interactive List component provides users a way to render a collection of interactive data in a list format into a single tab stop.",
"author": "Cerner Corporation",
"repository": {
Expand Down Expand Up @@ -37,7 +37,7 @@
"keycode-js": "^3.1.0",
"prop-types": "^15.5.8",
"terra-icon": "^3.58.0",
"terra-table": "^5.18.0",
"terra-table": "^5.22.0",
"terra-theme-context": "^1.9.0"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ const CompactInteractiveList = (props) => {
if (listRef?.current && focusedCell?.current) {
focusedCell.current = getFocusedCellIds(listRef?.current, columns, { row: 0, cell: 0 });
}
}, [listRef, focusedCell, columns]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const focusCell = ({ row, cell }) => {
// add 1 to the row number to accommodate for hidden header
Expand Down
102 changes: 67 additions & 35 deletions packages/terra-compact-interactive-list/src/utils/keyHandlerUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,29 @@ const getFirstSemanticRowIndexInVisualRow = (rowsLength, numberOfColumns, flowHo
return firstItemInVisualRow;
};

/**
* Finds the last semantic row index in a visual row, where the given row is located
* @param {number} rowsLength - a total number of seamntic rows in the list.
* @param {number} numberOfColumns - a number of visual columns.
* @param {boolean} flowHorizontally - sematic rows horizontal flow direction
* @param {number} row - an index of the currently focused semantic row.
* @returns - the index of the last semantic row in the same visual row as currently focused row.
*/
const getLastSemanticRowIndexInVisualRow = (rowsLength, numberOfColumns, flowHorizontally, row) => {
if (row === undefined || row === null) {
// If current row omitted, return the index of the last element
return rowsLength - 1;
}
if (flowHorizontally) {
const lastItemInVisualRow = (Math.ceil((row + 1) / numberOfColumns) * numberOfColumns) - 1;
return lastItemInVisualRow < rowsLength - 1 ? lastItemInVisualRow : rowsLength - 1;
}
const rowsPerColumn = Math.ceil(rowsLength / numberOfColumns);
const rowsToTop = row % rowsPerColumn;
const lastItemInVisualRow = (numberOfColumns - 1) * rowsPerColumn + rowsToTop;
return lastItemInVisualRow < rowsLength ? lastItemInVisualRow : lastItemInVisualRow - rowsPerColumn;
};

/**
* Calculates new semantic row and cell indexes to focus on per LEFT ARROW KEY press.
* @param {KeyboardEvent} event - keyboard event.
Expand All @@ -156,15 +179,28 @@ export const handleLeftKey = (event, focusedCell, numberOfColumns, flowHorizonta
// Focus moves to the first cell in the first item in the visual row.
return { row: firstItemInVisualRow, cell: 0 };
}
// Focus should go till the start of the visual row, and should not break to the previous visual row.

if (cell === 0) {
// Focus reached the beginning of the the semantic row.
// Check if focus reached the beginning of the visual row.
let nextCell = cell;
let nextRow = row;
if (row === 0 || row === firstItemInVisualRow) {
// The first item in the list, or the first item in the visual row.
// Focus should stay where it is.
if (row === 0) {
// The first item in the list. Focus should stay where it is.
return focusedCell;
}
if (!flowHorizontally) {
// VERTICAL FLOW
// Check if the first semantic row in a VISUAL row has been reached.
const rowsPerColumn = Math.ceil(rowsLength / numberOfColumns);
if (row < rowsPerColumn) {
// Focus should wrap to the previous visual row.
const rowsToTop = row % rowsPerColumn;
const previousVisualRow = rowsToTop - 1;
const previousVisualRowlastSemanticRowIndex = getLastSemanticRowIndexInVisualRow(rowsLength, numberOfColumns, flowHorizontally, previousVisualRow);
return { row: previousVisualRowlastSemanticRowIndex, cell: cellsLength - 1 };
}
}
// The first cell. Focus moves to the last cell of the semantic row to the left.
nextCell = cellsLength - 1;
nextRow -= flowHorizontally ? 1 : Math.ceil(rowsLength / numberOfColumns);
Expand All @@ -174,29 +210,6 @@ export const handleLeftKey = (event, focusedCell, numberOfColumns, flowHorizonta
return { row, cell: cell - 1 };
};

/**
* Finds the last semantic row index in a visual row, where the given row is located
* @param {number} rowsLength - a total number of seamntic rows in the list.
* @param {number} numberOfColumns - a number of visual columns.
* @param {boolean} flowHorizontally - sematic rows horizontal flow direction
* @param {number} row - an index of the currently focused semantic row.
* @returns - the index of the last semantic row in the same visual row as currently focused row.
*/
const getLastSemanticRowIndexInVisualRow = (rowsLength, numberOfColumns, flowHorizontally, row) => {
if (row === undefined || row === null) {
// If current row omitted, return the index of the last element
return rowsLength - 1;
}
if (flowHorizontally) {
const lastItemInVisualRow = (Math.ceil((row + 1) / numberOfColumns) * numberOfColumns) - 1;
return lastItemInVisualRow < rowsLength - 1 ? lastItemInVisualRow : rowsLength - 1;
}
const rowsPerColumn = Math.ceil(rowsLength / numberOfColumns);
const rowsToTop = row % rowsPerColumn;
const lastItemInVisualRow = (numberOfColumns - 1) * rowsPerColumn + rowsToTop;
return lastItemInVisualRow < rowsLength ? lastItemInVisualRow : lastItemInVisualRow - rowsPerColumn;
};

/**
* Calculates new semantic row and cell indexes to focus on per RIGHT ARROW KEY press.
* @param {KeyboardEvent} event - keyboard event.
Expand Down Expand Up @@ -229,17 +242,36 @@ export const handleRightKey = (event, focusedCell, numberOfColumns, flowHorizont
nextRow = getLastSemanticRowIndexInVisualRow(rowsLength, numberOfColumns, flowHorizontally, row);
return { row: nextRow, cell: nextCell };
}
// Focus should go till the end of the visual row, and should not break to the next visual row.

if (cell === (cellsLength - 1)) {
// The last semantic column in the row.
// Check if the last item in visual row.
const lastRowIndex = getLastSemanticRowIndexInVisualRow(rowsLength, numberOfColumns, flowHorizontally, row);
if (row === lastRowIndex) {
// The last item in the visual row or next semantic row to the right is a placeholder.
// Focus should not move anywhere.
// Focus reached the end of the semantic row.
if (!flowHorizontally) {
// VERTICAL FLOW
// Check if the last semantic row in the LAST VISUAL row has been reached.
const rowsPerColumn = Math.ceil(rowsLength / numberOfColumns);
const lastVisualRowIndex = rowsPerColumn - 1;
const lastSemanticRowInLastVisualRow = getLastSemanticRowIndexInVisualRow(rowsLength, numberOfColumns, flowHorizontally, lastVisualRowIndex);
if (row === lastSemanticRowInLastVisualRow) {
// Focus should stay where it is and NOT move to the right.
return { row, cell };
}

// Check if the last semantic row in ANY VISUAL row has been reached.
const lastSemanticRowIndex = getLastSemanticRowIndexInVisualRow(rowsLength, numberOfColumns, flowHorizontally, row);
if (row === lastSemanticRowIndex) {
// Focus should wrap to the next next visual row.
const rowsToTop = row % rowsPerColumn;
return { row: rowsToTop + 1, cell: 0 };
}
}

if (flowHorizontally && row === rowsLength - 1) {
// HORIZONTAL FLOW
// The last row in the list has been reached, focus should not move to the right.
return { row, cell };
}
// Focus moves to the first cell of the next semantic row.

// Not the end of the visual row, focus moves to the first cell of the next semantic row.
nextCell = 0;
nextRow += flowHorizontally ? 1 : Math.ceil(rowsLength / numberOfColumns);
} else {
Expand Down
Loading

0 comments on commit 7ff7865

Please sign in to comment.