box-ui-elements 23.4.0-beta.17 → 23.4.0-beta.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/explorer.css +1 -1
- package/dist/explorer.js +1 -1
- package/dist/preview.css +1 -1
- package/dist/preview.js +1 -1
- package/dist/sidebar.css +1 -1
- package/dist/sidebar.js +1 -1
- package/es/elements/common/back-button/BackButton.js.map +1 -0
- package/es/elements/common/back-button/index.js +3 -0
- package/es/elements/common/{nav-button → back-button}/index.js.flow +1 -1
- package/es/elements/common/back-button/index.js.map +1 -0
- package/{src/elements/common/types/SidebarNavigation.flow.js → es/elements/common/types/SidebarNavigation.js.flow} +9 -23
- package/es/elements/content-sidebar/SidebarNavButton.js +29 -22
- package/es/elements/content-sidebar/SidebarNavButton.js.flow +28 -21
- package/es/elements/content-sidebar/SidebarNavButton.js.map +1 -1
- package/es/elements/content-sidebar/SidebarNavButton.scss +13 -0
- package/es/elements/content-sidebar/versions/StaticVersionSidebar.js +1 -1
- package/es/elements/content-sidebar/versions/StaticVersionSidebar.js.flow +1 -1
- package/es/elements/content-sidebar/versions/StaticVersionSidebar.js.map +1 -1
- package/es/elements/content-sidebar/versions/VersionsGroup.js.flow +3 -0
- package/es/elements/content-sidebar/versions/VersionsGroup.js.map +1 -1
- package/es/elements/content-sidebar/versions/VersionsList.js +16 -8
- package/es/elements/content-sidebar/versions/VersionsList.js.flow +35 -17
- package/es/elements/content-sidebar/versions/VersionsList.js.map +1 -1
- package/es/elements/content-sidebar/versions/VersionsMenu.js.flow +3 -0
- package/es/elements/content-sidebar/versions/VersionsMenu.js.map +1 -1
- package/es/elements/content-sidebar/versions/VersionsSidebar.js +1 -1
- package/es/elements/content-sidebar/versions/VersionsSidebar.js.flow +1 -1
- package/es/elements/content-sidebar/versions/VersionsSidebar.js.map +1 -1
- package/package.json +3 -3
- package/src/elements/common/{nav-button → back-button}/__tests__/BackButton.test.js +1 -1
- package/src/elements/common/{nav-button → back-button}/index.js +1 -1
- package/{es/elements/common/types/SidebarNavigation.flow.js.flow → src/elements/common/types/SidebarNavigation.js.flow} +9 -23
- package/src/elements/content-sidebar/SidebarNavButton.js +28 -21
- package/src/elements/content-sidebar/SidebarNavButton.scss +13 -0
- package/src/elements/content-sidebar/__tests__/SidebarNavButton.test.js +208 -26
- package/src/elements/content-sidebar/versions/StaticVersionSidebar.js +1 -1
- package/src/elements/content-sidebar/versions/VersionsGroup.js +3 -0
- package/src/elements/content-sidebar/versions/VersionsList.js +35 -17
- package/src/elements/content-sidebar/versions/VersionsMenu.js +3 -0
- package/src/elements/content-sidebar/versions/VersionsSidebar.js +1 -1
- package/src/elements/content-sidebar/versions/__tests__/StaticVersionSidebar.test.js +5 -7
- package/src/elements/content-sidebar/versions/__tests__/VersionsList.test.js +138 -13
- package/src/elements/content-sidebar/versions/__tests__/VersionsMenu.test.js +75 -23
- package/src/elements/content-sidebar/versions/__tests__/VersionsSidebar.test.js +5 -7
- package/es/elements/common/nav-button/BackButton.js.map +0 -1
- package/es/elements/common/nav-button/NavButton.js +0 -63
- package/es/elements/common/nav-button/NavButton.js.flow +0 -80
- package/es/elements/common/nav-button/NavButton.js.map +0 -1
- package/es/elements/common/nav-button/index.js +0 -3
- package/es/elements/common/nav-button/index.js.map +0 -1
- package/es/elements/common/types/SidebarNavigation.flow.js +0 -14
- package/es/elements/common/types/SidebarNavigation.flow.js.map +0 -1
- package/src/elements/common/nav-button/NavButton.js +0 -80
- package/src/elements/common/nav-button/__tests__/NavButton.test.js +0 -265
- package/src/elements/content-sidebar/versions/__tests__/__snapshots__/VersionsList.test.js.snap +0 -45
- /package/es/elements/common/{nav-button → back-button}/BackButton.js +0 -0
- /package/es/elements/common/{nav-button → back-button}/BackButton.js.flow +0 -0
- /package/es/elements/common/{nav-button → back-button}/BackButton.scss +0 -0
- /package/src/elements/common/{nav-button → back-button}/BackButton.js +0 -0
- /package/src/elements/common/{nav-button → back-button}/BackButton.scss +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VersionsSidebar.js","names":["React","FormattedMessage","Route","InlineError","messages","SidebarContent","VersionsMenu","BackButton","DEFAULT_FETCH_END","LoadingIndicatorWrapper","MAX_VERSIONS","VersionsSidebar","_ref","error","isLoading","parentName","versions","rest","_objectWithoutProperties","_excluded","showLimit","length","showVersions","showEmpty","showError","createElement","history","className","title","Fragment","onClick","push","versionsTitle","crawlerPosition","versionServerError","versionsEmpty","_extends","versionMaxEntries","values","maxVersions"],"sources":["../../../../src/elements/content-sidebar/versions/VersionsSidebar.js"],"sourcesContent":["/**\n * @flow\n * @file Versions Sidebar component\n * @author Box\n */\n\nimport * as React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport { Route } from 'react-router-dom';\nimport type { MessageDescriptor } from 'react-intl';\nimport InlineError from '../../../components/inline-error';\nimport messages from './messages';\nimport SidebarContent from '../SidebarContent';\nimport VersionsMenu from './VersionsMenu';\nimport
|
|
1
|
+
{"version":3,"file":"VersionsSidebar.js","names":["React","FormattedMessage","Route","InlineError","messages","SidebarContent","VersionsMenu","BackButton","DEFAULT_FETCH_END","LoadingIndicatorWrapper","MAX_VERSIONS","VersionsSidebar","_ref","error","isLoading","parentName","versions","rest","_objectWithoutProperties","_excluded","showLimit","length","showVersions","showEmpty","showError","createElement","history","className","title","Fragment","onClick","push","versionsTitle","crawlerPosition","versionServerError","versionsEmpty","_extends","versionMaxEntries","values","maxVersions"],"sources":["../../../../src/elements/content-sidebar/versions/VersionsSidebar.js"],"sourcesContent":["/**\n * @flow\n * @file Versions Sidebar component\n * @author Box\n */\n\nimport * as React from 'react';\nimport { FormattedMessage } from 'react-intl';\nimport { Route } from 'react-router-dom';\nimport type { MessageDescriptor } from 'react-intl';\nimport InlineError from '../../../components/inline-error';\nimport messages from './messages';\nimport SidebarContent from '../SidebarContent';\nimport VersionsMenu from './VersionsMenu';\nimport BackButton from '../../common/back-button';\nimport { DEFAULT_FETCH_END } from '../../../constants';\nimport { LoadingIndicatorWrapper } from '../../../components/loading-indicator';\nimport type { BoxItemVersion } from '../../../common/types/core';\nimport './VersionsSidebar.scss';\n\nconst MAX_VERSIONS = DEFAULT_FETCH_END;\n\ntype Props = {\n error?: MessageDescriptor,\n fileId: string,\n isLoading: boolean,\n parentName: string,\n versionCount: number,\n versionLimit: number,\n versions: Array<BoxItemVersion>,\n};\n\nconst VersionsSidebar = ({ error, isLoading, parentName, versions, ...rest }: Props) => {\n const showLimit = versions.length >= MAX_VERSIONS;\n const showVersions = !!versions.length;\n const showEmpty = !isLoading && !showVersions;\n const showError = !!error;\n\n return (\n <Route>\n {({ history }) => (\n <SidebarContent\n className=\"bcs-Versions\"\n data-resin-component=\"preview\"\n data-resin-feature=\"versions\"\n title={\n <>\n <BackButton data-resin-target=\"back\" onClick={() => history.push(`/${parentName}`)} />\n <FormattedMessage {...messages.versionsTitle} />\n </>\n }\n >\n <LoadingIndicatorWrapper\n className=\"bcs-Versions-content\"\n crawlerPosition=\"top\"\n isLoading={isLoading}\n >\n {showError && (\n <InlineError title={<FormattedMessage {...messages.versionServerError} />}>\n <FormattedMessage {...error} />\n </InlineError>\n )}\n\n {showEmpty && (\n <div className=\"bcs-Versions-empty\">\n <FormattedMessage {...messages.versionsEmpty} />\n </div>\n )}\n\n {showVersions && (\n <div className=\"bcs-Versions-menu\" data-testid=\"bcs-Versions-menu\">\n <VersionsMenu versions={versions} {...rest} />\n </div>\n )}\n {showLimit && (\n <div className=\"bcs-Versions-maxEntries\" data-testid=\"max-versions\">\n <FormattedMessage\n {...messages.versionMaxEntries}\n values={{\n maxVersions: MAX_VERSIONS,\n }}\n />\n </div>\n )}\n </LoadingIndicatorWrapper>\n </SidebarContent>\n )}\n </Route>\n );\n};\n\nexport default VersionsSidebar;\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "box-ui-elements",
|
|
3
|
-
"version": "23.4.0-beta.
|
|
3
|
+
"version": "23.4.0-beta.19",
|
|
4
4
|
"description": "Box UI Elements",
|
|
5
5
|
"author": "Box (https://www.box.com/)",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
"@box/frontend": "^11.0.1",
|
|
138
138
|
"@box/item-icon": "^0.9.83",
|
|
139
139
|
"@box/languages": "^1.0.0",
|
|
140
|
-
"@box/metadata-editor": "^0.
|
|
140
|
+
"@box/metadata-editor": "^0.115.0",
|
|
141
141
|
"@box/react-virtualized": "9.22.3-rc-box.9",
|
|
142
142
|
"@cfaester/enzyme-adapter-react-18": "^0.8.0",
|
|
143
143
|
"@chromatic-com/storybook": "^1.6.1",
|
|
@@ -306,7 +306,7 @@
|
|
|
306
306
|
"@box/cldr-data": ">=34.2.0",
|
|
307
307
|
"@box/combobox-with-api": "^0.34.9",
|
|
308
308
|
"@box/item-icon": "^0.9.83",
|
|
309
|
-
"@box/metadata-editor": "^0.
|
|
309
|
+
"@box/metadata-editor": "^0.115.0",
|
|
310
310
|
"@box/react-virtualized": "9.22.3-rc-box.9",
|
|
311
311
|
"@hapi/address": "^2.1.4",
|
|
312
312
|
"axios": "^0.30.0",
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import { render, screen, userEvent } from '../../../../test-utils/testing-library';
|
|
3
3
|
import { BackButton } from '..';
|
|
4
4
|
|
|
5
|
-
describe('elements/common/
|
|
5
|
+
describe('elements/common/back-button/BackButton', () => {
|
|
6
6
|
const mockOnClick = jest.fn();
|
|
7
7
|
|
|
8
8
|
beforeEach(() => {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as BackButton } from './BackButton';
|
|
2
|
-
export { default } from './
|
|
2
|
+
export { default } from './BackButton';
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/* @flow */
|
|
2
2
|
|
|
3
|
+
// flow version is simplified compared to Type Script due to difficult to resolve problems with Union Types
|
|
4
|
+
// Type Script works better with Union Types
|
|
5
|
+
|
|
3
6
|
export const ViewType = Object.freeze({
|
|
4
7
|
BOXAI: 'boxai',
|
|
5
8
|
SKILLS: 'skills',
|
|
@@ -18,30 +21,13 @@ export const FeedEntryType = Object.freeze({
|
|
|
18
21
|
export type ViewTypeValues = $Values<typeof ViewType>;
|
|
19
22
|
export type FeedEntryTypeValues = $Values<typeof FeedEntryType>;
|
|
20
23
|
|
|
21
|
-
type
|
|
22
|
-
sidebar:
|
|
23
|
-
versionId
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
sidebar: 'activity',
|
|
28
|
-
activeFeedEntryType: 'annotations',
|
|
29
|
-
fileVersionId: string,
|
|
30
|
-
activeFeedEntryId: string,
|
|
24
|
+
export type SidebarNavigation = {
|
|
25
|
+
sidebar: ViewTypeValues,
|
|
26
|
+
versionId?: string,
|
|
27
|
+
activeFeedEntryType?: FeedEntryTypeValues,
|
|
28
|
+
activeFeedEntryId?: string,
|
|
29
|
+
fileVersionId?: string,
|
|
31
30
|
};
|
|
32
|
-
type ActivityCommentsSidebarView = {
|
|
33
|
-
sidebar: 'activity',
|
|
34
|
-
activeFeedEntryType: 'comments' | 'tasks',
|
|
35
|
-
activeFeedEntryId: string,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export type SidebarNavigation =
|
|
39
|
-
| {|
|
|
40
|
-
sidebar: ViewTypeValues,
|
|
41
|
-
|}
|
|
42
|
-
| VersionSidebarView
|
|
43
|
-
| ActivityCommentsSidebarView
|
|
44
|
-
| ActivityAnnotationsSidebarView;
|
|
45
31
|
|
|
46
32
|
export type InternalSidebarNavigation = SidebarNavigation & {
|
|
47
33
|
open: boolean,
|
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
import * as React from 'react';
|
|
8
8
|
import { Route } from 'react-router-dom';
|
|
9
9
|
import noop from 'lodash/noop';
|
|
10
|
-
import
|
|
10
|
+
import classNames from 'classnames';
|
|
11
|
+
import { Button } from '@box/blueprint-web';
|
|
11
12
|
import Tooltip from '../../components/tooltip/Tooltip';
|
|
13
|
+
import { isLeftClick } from '../../utils/dom';
|
|
12
14
|
import './SidebarNavButton.scss';
|
|
13
15
|
|
|
14
16
|
type Props = {
|
|
@@ -37,45 +39,50 @@ const SidebarNavButton = React.forwardRef<Props, React.Ref<any>>((props: Props,
|
|
|
37
39
|
} = props;
|
|
38
40
|
const sidebarPath = `/${sidebarView}`;
|
|
39
41
|
|
|
40
|
-
const handleNavButtonClick = () => {
|
|
41
|
-
onClick(sidebarView);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
42
|
return (
|
|
45
43
|
<Route path={sidebarPath}>
|
|
46
|
-
{({ match }) => {
|
|
44
|
+
{({ match, history }) => {
|
|
47
45
|
const isMatch = !!match;
|
|
48
|
-
const
|
|
49
|
-
const isActiveValue = isActive();
|
|
46
|
+
const isActiveValue = isMatch && !!isOpen;
|
|
50
47
|
const isExactMatch = isMatch && match.isExact;
|
|
51
48
|
const id = `${elementId}${elementId === '' ? '' : '_'}${sidebarView}`;
|
|
52
49
|
|
|
50
|
+
const handleNavButtonClick = event => {
|
|
51
|
+
onClick(sidebarView);
|
|
52
|
+
|
|
53
|
+
if (!event.defaultPrevented && isLeftClick(event)) {
|
|
54
|
+
const method = isExactMatch ? history.replace : history.push;
|
|
55
|
+
method({
|
|
56
|
+
pathname: sidebarPath,
|
|
57
|
+
state: { open: true },
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
53
62
|
return (
|
|
54
63
|
<Tooltip position="middle-left" text={tooltip} isTabbable={false}>
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
aria-selected={isActiveValue}
|
|
64
|
+
<Button
|
|
65
|
+
accessibleWhenDisabled={true}
|
|
58
66
|
aria-controls={`${id}-content`}
|
|
59
67
|
aria-label={tooltip}
|
|
60
|
-
|
|
68
|
+
aria-selected={isActiveValue}
|
|
69
|
+
className={classNames('bcs-NavButton', {
|
|
70
|
+
'bcs-is-selected': isActiveValue,
|
|
71
|
+
'bdl-is-disabled': isDisabled,
|
|
72
|
+
})}
|
|
61
73
|
data-resin-target={dataResinTarget}
|
|
62
74
|
data-testid={dataTestId}
|
|
63
|
-
|
|
75
|
+
ref={ref}
|
|
64
76
|
id={id}
|
|
65
|
-
|
|
66
|
-
isDisabled={isDisabled}
|
|
77
|
+
disabled={isDisabled}
|
|
67
78
|
onClick={handleNavButtonClick}
|
|
68
|
-
replace={isExactMatch}
|
|
69
79
|
role="tab"
|
|
70
80
|
tabIndex={isActiveValue ? '0' : '-1'}
|
|
71
|
-
to={{
|
|
72
|
-
pathname: sidebarPath,
|
|
73
|
-
state: { open: true },
|
|
74
|
-
}}
|
|
75
81
|
type="button"
|
|
82
|
+
variant="tertiary"
|
|
76
83
|
>
|
|
77
84
|
{children}
|
|
78
|
-
</
|
|
85
|
+
</Button>
|
|
79
86
|
</Tooltip>
|
|
80
87
|
);
|
|
81
88
|
}}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
.bcs .bcs-NavButton {
|
|
5
5
|
@include bdl-SidebarNavButton;
|
|
6
|
+
|
|
7
|
+
border-radius: 0;
|
|
6
8
|
|
|
7
9
|
&::before {
|
|
8
10
|
position: absolute;
|
|
@@ -21,6 +23,11 @@
|
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
// Style disabled buttons with proper visual feedback
|
|
27
|
+
&[aria-disabled="true"] {
|
|
28
|
+
cursor: default;
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
&.bcs-is-selected {
|
|
25
32
|
&::before {
|
|
26
33
|
background-color: $blue;
|
|
@@ -30,6 +37,12 @@
|
|
|
30
37
|
fill: $blue;
|
|
31
38
|
}
|
|
32
39
|
}
|
|
40
|
+
|
|
41
|
+
// Blueprint button focus override
|
|
42
|
+
&:not(:disabled)[data-focus-visible] {
|
|
43
|
+
border-radius: var(--radius-1);
|
|
44
|
+
box-shadow: 0 0 0 var(--border-2) var(--outline-focus-on-light);
|
|
45
|
+
}
|
|
33
46
|
}
|
|
34
47
|
|
|
35
48
|
@include breakpoint($medium-screen) {
|
|
@@ -1,26 +1,40 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { MemoryRouter } from 'react-router-dom';
|
|
3
|
-
import {
|
|
4
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
5
|
-
import PlainButton from '../../../components/plain-button';
|
|
2
|
+
import { MemoryRouter, Router } from 'react-router-dom';
|
|
3
|
+
import { render, screen, fireEvent } from '../../../test-utils/testing-library';
|
|
6
4
|
import SidebarNavButton from '../SidebarNavButton';
|
|
7
|
-
import Tooltip from '../../../components/tooltip/Tooltip';
|
|
8
5
|
|
|
9
6
|
describe('elements/content-sidebar/SidebarNavButton', () => {
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
jest.clearAllMocks();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const renderWrapper = ({ children, ref, ...props }, path = '/') =>
|
|
12
|
+
render(
|
|
12
13
|
<MemoryRouter initialEntries={[path]}>
|
|
13
|
-
<SidebarNavButton {...props}>
|
|
14
|
+
<SidebarNavButton ref={ref} {...props}>
|
|
15
|
+
{children}
|
|
16
|
+
</SidebarNavButton>
|
|
14
17
|
</MemoryRouter>,
|
|
15
18
|
);
|
|
16
|
-
const getButton = wrapper => wrapper.find(PlainButton).first();
|
|
17
19
|
|
|
18
20
|
test('should render nav button properly', () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
renderWrapper({
|
|
22
|
+
tooltip: 'foo',
|
|
23
|
+
sidebarView: 'activity',
|
|
24
|
+
children: 'test button',
|
|
25
|
+
});
|
|
26
|
+
const button = screen.getByRole('tab');
|
|
21
27
|
|
|
22
|
-
expect(
|
|
23
|
-
expect(button.
|
|
28
|
+
expect(button).toHaveAttribute('aria-label', 'foo');
|
|
29
|
+
expect(button).toHaveAttribute('aria-selected', 'false');
|
|
30
|
+
expect(button).toHaveAttribute('aria-controls', 'activity-content');
|
|
31
|
+
expect(button).toHaveAttribute('role', 'tab');
|
|
32
|
+
expect(button).toHaveAttribute('tabindex', '-1');
|
|
33
|
+
expect(button).toHaveAttribute('type', 'button');
|
|
34
|
+
expect(button).toHaveAttribute('id', 'activity');
|
|
35
|
+
expect(button).toHaveClass('bcs-NavButton');
|
|
36
|
+
expect(button).not.toHaveClass('bcs-is-selected');
|
|
37
|
+
expect(button).toHaveTextContent('test button');
|
|
24
38
|
});
|
|
25
39
|
|
|
26
40
|
test.each`
|
|
@@ -33,11 +47,20 @@ describe('elements/content-sidebar/SidebarNavButton', () => {
|
|
|
33
47
|
isOpen,
|
|
34
48
|
sidebarView: 'activity',
|
|
35
49
|
tooltip: 'foo',
|
|
50
|
+
children: 'test button',
|
|
36
51
|
};
|
|
37
|
-
|
|
38
|
-
const button =
|
|
52
|
+
renderWrapper(props, '/activity');
|
|
53
|
+
const button = screen.getByRole('tab');
|
|
39
54
|
|
|
40
|
-
|
|
55
|
+
if (expected) {
|
|
56
|
+
expect(button).toHaveClass('bcs-is-selected');
|
|
57
|
+
expect(button).toHaveAttribute('aria-selected', 'true');
|
|
58
|
+
expect(button).toHaveAttribute('tabindex', '0');
|
|
59
|
+
} else {
|
|
60
|
+
expect(button).not.toHaveClass('bcs-is-selected');
|
|
61
|
+
expect(button).toHaveAttribute('aria-selected', 'false');
|
|
62
|
+
expect(button).toHaveAttribute('tabindex', '-1');
|
|
63
|
+
}
|
|
41
64
|
});
|
|
42
65
|
|
|
43
66
|
test.each`
|
|
@@ -48,26 +71,185 @@ describe('elements/content-sidebar/SidebarNavButton', () => {
|
|
|
48
71
|
${'/activity/test'} | ${true}
|
|
49
72
|
${'/skills'} | ${false}
|
|
50
73
|
`('should reflect active state ($expected) correctly based on active path', ({ expected, path }) => {
|
|
51
|
-
|
|
52
|
-
|
|
74
|
+
renderWrapper(
|
|
75
|
+
{
|
|
76
|
+
isOpen: true,
|
|
77
|
+
sidebarView: 'activity',
|
|
78
|
+
tooltip: 'foo',
|
|
79
|
+
children: 'test button',
|
|
80
|
+
},
|
|
81
|
+
path,
|
|
82
|
+
);
|
|
83
|
+
const button = screen.getByRole('tab');
|
|
53
84
|
|
|
54
|
-
|
|
85
|
+
if (expected) {
|
|
86
|
+
expect(button).toHaveClass('bcs-is-selected');
|
|
87
|
+
expect(button).toHaveAttribute('aria-selected', 'true');
|
|
88
|
+
expect(button).toHaveAttribute('tabindex', '0');
|
|
89
|
+
} else {
|
|
90
|
+
expect(button).not.toHaveClass('bcs-is-selected');
|
|
91
|
+
expect(button).toHaveAttribute('aria-selected', 'false');
|
|
92
|
+
expect(button).toHaveAttribute('tabindex', '-1');
|
|
93
|
+
}
|
|
55
94
|
});
|
|
56
95
|
|
|
57
96
|
test('should call onClick with sidebarView when clicked', () => {
|
|
58
97
|
const mockOnClick = jest.fn();
|
|
59
98
|
const mockSidebarView = 'activity';
|
|
60
99
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
);
|
|
100
|
+
renderWrapper({
|
|
101
|
+
onClick: mockOnClick,
|
|
102
|
+
sidebarView: mockSidebarView,
|
|
103
|
+
tooltip: 'test',
|
|
104
|
+
children: 'button',
|
|
105
|
+
});
|
|
68
106
|
const button = screen.getByText('button');
|
|
69
107
|
|
|
70
108
|
fireEvent.click(button);
|
|
71
109
|
expect(mockOnClick).toBeCalledWith(mockSidebarView);
|
|
72
110
|
});
|
|
111
|
+
|
|
112
|
+
test.each`
|
|
113
|
+
isDisabled | expected
|
|
114
|
+
${true} | ${true}
|
|
115
|
+
${false} | ${false}
|
|
116
|
+
${undefined} | ${false}
|
|
117
|
+
`('should apply bdl-is-disabled class when isDisabled is $isDisabled', ({ isDisabled, expected }) => {
|
|
118
|
+
const content = 'Activity';
|
|
119
|
+
renderWrapper({
|
|
120
|
+
isDisabled,
|
|
121
|
+
sidebarView: 'activity',
|
|
122
|
+
tooltip: 'Activity',
|
|
123
|
+
children: content,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const button = screen.getByRole('tab');
|
|
127
|
+
if (expected) {
|
|
128
|
+
expect(button).toHaveClass('bdl-is-disabled');
|
|
129
|
+
} else {
|
|
130
|
+
expect(button).not.toHaveClass('bdl-is-disabled');
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test.each`
|
|
135
|
+
elementId | sidebarView | expectedId | expectedAriaControls
|
|
136
|
+
${undefined} | ${'activity'} | ${'activity'} | ${'activity-content'}
|
|
137
|
+
${''} | ${'activity'} | ${'activity'} | ${'activity-content'}
|
|
138
|
+
${'sidebar'} | ${'activity'} | ${'sidebar_activity'} | ${'sidebar_activity-content'}
|
|
139
|
+
${'main'} | ${'skills'} | ${'main_skills'} | ${'main_skills-content'}
|
|
140
|
+
`(
|
|
141
|
+
'should generate correct id and aria-controls with elementId=$elementId and sidebarView=$sidebarView',
|
|
142
|
+
({ elementId, sidebarView, expectedId, expectedAriaControls }) => {
|
|
143
|
+
renderWrapper({
|
|
144
|
+
elementId,
|
|
145
|
+
sidebarView,
|
|
146
|
+
tooltip: 'test',
|
|
147
|
+
children: 'test button',
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const button = screen.getByRole('tab');
|
|
151
|
+
expect(button).toHaveAttribute('id', expectedId);
|
|
152
|
+
expect(button).toHaveAttribute('aria-controls', expectedAriaControls);
|
|
153
|
+
},
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
test('should forward ref to the Button', () => {
|
|
157
|
+
const ref = React.createRef();
|
|
158
|
+
|
|
159
|
+
renderWrapper({
|
|
160
|
+
ref,
|
|
161
|
+
sidebarView: 'activity',
|
|
162
|
+
tooltip: 'test',
|
|
163
|
+
children: 'test button',
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const button = screen.getByRole('tab');
|
|
167
|
+
expect(ref.current).toBe(button);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe('navigation on click', () => {
|
|
171
|
+
const mockHistoryPush = jest.fn();
|
|
172
|
+
const mockHistoryReplace = jest.fn();
|
|
173
|
+
const mockHistory = {
|
|
174
|
+
push: mockHistoryPush,
|
|
175
|
+
replace: mockHistoryReplace,
|
|
176
|
+
listen: jest.fn(),
|
|
177
|
+
location: { pathname: '/activity' },
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const renderWithRouter = (props, history = mockHistory) => {
|
|
181
|
+
return render(
|
|
182
|
+
<Router history={history}>
|
|
183
|
+
<SidebarNavButton sidebarView="activity" tooltip="test" {...props}>
|
|
184
|
+
Activity
|
|
185
|
+
</SidebarNavButton>
|
|
186
|
+
</Router>,
|
|
187
|
+
);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
test('calls onClick handler and history.push on left click when not exact match', () => {
|
|
191
|
+
const mockOnClick = jest.fn();
|
|
192
|
+
const mockHistoryWithDifferentPath = {
|
|
193
|
+
...mockHistory,
|
|
194
|
+
location: { pathname: '/activity/versions' },
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
renderWithRouter({ onClick: mockOnClick }, mockHistoryWithDifferentPath);
|
|
198
|
+
|
|
199
|
+
const button = screen.getByText('Activity');
|
|
200
|
+
fireEvent.click(button, { button: 0 });
|
|
201
|
+
|
|
202
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
203
|
+
expect(mockHistoryPush).toBeCalledWith({
|
|
204
|
+
pathname: '/activity',
|
|
205
|
+
state: { open: true },
|
|
206
|
+
});
|
|
207
|
+
expect(mockHistoryReplace).not.toBeCalled();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
test('calls history.replace on left click when exact match', () => {
|
|
211
|
+
const mockOnClick = jest.fn();
|
|
212
|
+
|
|
213
|
+
renderWithRouter({ onClick: mockOnClick });
|
|
214
|
+
|
|
215
|
+
const button = screen.getByText('Activity');
|
|
216
|
+
fireEvent.click(button, { button: 0 });
|
|
217
|
+
|
|
218
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
219
|
+
expect(mockHistoryReplace).toBeCalledWith({
|
|
220
|
+
pathname: '/activity',
|
|
221
|
+
state: { open: true },
|
|
222
|
+
});
|
|
223
|
+
expect(mockHistoryPush).not.toBeCalled();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test('does not call history.push on right click', () => {
|
|
227
|
+
const mockOnClick = jest.fn();
|
|
228
|
+
|
|
229
|
+
renderWithRouter({ onClick: mockOnClick });
|
|
230
|
+
|
|
231
|
+
const button = screen.getByText('Activity');
|
|
232
|
+
fireEvent.click(button, { button: 1 });
|
|
233
|
+
|
|
234
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
235
|
+
expect(mockHistoryPush).not.toBeCalled();
|
|
236
|
+
expect(mockHistoryReplace).not.toBeCalled();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('does not call history.push on prevented event', () => {
|
|
240
|
+
const mockOnClick = jest.fn();
|
|
241
|
+
|
|
242
|
+
renderWithRouter({ onClick: mockOnClick });
|
|
243
|
+
|
|
244
|
+
const button = screen.getByText('Activity');
|
|
245
|
+
|
|
246
|
+
// Prevent default on the button click
|
|
247
|
+
button.addEventListener('click', e => e.preventDefault());
|
|
248
|
+
fireEvent.click(button, { button: 0 });
|
|
249
|
+
|
|
250
|
+
expect(mockOnClick).toBeCalledWith('activity');
|
|
251
|
+
expect(mockHistoryPush).not.toBeCalled();
|
|
252
|
+
expect(mockHistoryReplace).not.toBeCalled();
|
|
253
|
+
});
|
|
254
|
+
});
|
|
73
255
|
});
|
|
@@ -10,7 +10,7 @@ import { Route } from 'react-router-dom';
|
|
|
10
10
|
|
|
11
11
|
import BoxDrive140 from '../../../illustration/BoxDrive140';
|
|
12
12
|
|
|
13
|
-
import
|
|
13
|
+
import BackButton from '../../common/back-button';
|
|
14
14
|
import PrimaryButton from '../../../components/primary-button';
|
|
15
15
|
import { LoadingIndicatorWrapper } from '../../../components/loading-indicator';
|
|
16
16
|
import VersionsMenu from './VersionsMenu';
|
|
@@ -7,11 +7,14 @@
|
|
|
7
7
|
import * as React from 'react';
|
|
8
8
|
import VersionsList from './VersionsList';
|
|
9
9
|
import type { BoxItemVersion } from '../../../common/types/core';
|
|
10
|
+
import type { InternalSidebarNavigation } from '../../common/types/SidebarNavigation';
|
|
10
11
|
import './VersionsGroup.scss';
|
|
11
12
|
|
|
12
13
|
type Props = {
|
|
13
14
|
fileId: string,
|
|
14
15
|
heading: string,
|
|
16
|
+
internalSidebarNavigation?: InternalSidebarNavigation,
|
|
17
|
+
routerDisabled?: boolean,
|
|
15
18
|
versionCount: number,
|
|
16
19
|
versionLimit: number,
|
|
17
20
|
versions: Array<BoxItemVersion>,
|
|
@@ -8,33 +8,51 @@ import * as React from 'react';
|
|
|
8
8
|
import { Route } from 'react-router-dom';
|
|
9
9
|
import VersionsItem from './VersionsItem';
|
|
10
10
|
import type { BoxItemVersion } from '../../../common/types/core';
|
|
11
|
+
import type { InternalSidebarNavigation } from '../../common/types/SidebarNavigation';
|
|
11
12
|
import './VersionsList.scss';
|
|
12
13
|
|
|
13
14
|
type Props = {
|
|
14
15
|
currentId?: string,
|
|
15
16
|
fileId: string,
|
|
17
|
+
internalSidebarNavigation?: InternalSidebarNavigation,
|
|
18
|
+
routerDisabled?: boolean,
|
|
16
19
|
versionCount: number,
|
|
17
20
|
versionLimit: number,
|
|
18
21
|
versions: Array<BoxItemVersion>,
|
|
19
22
|
};
|
|
20
23
|
|
|
21
|
-
const VersionsList = ({ currentId, versions, ...rest }: Props) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
const VersionsList = ({ currentId, internalSidebarNavigation, routerDisabled = false, versions, ...rest }: Props) => {
|
|
25
|
+
const renderVersionItemWithoutRouter = (version: BoxItemVersion) => (
|
|
26
|
+
<VersionsItem
|
|
27
|
+
isCurrent={currentId === version.id}
|
|
28
|
+
isSelected={internalSidebarNavigation?.versionId === version.id}
|
|
29
|
+
version={version}
|
|
30
|
+
{...rest}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const renderVersionItemWithRouter = (version: BoxItemVersion) => (
|
|
35
|
+
<Route
|
|
36
|
+
render={({ match }) => (
|
|
37
|
+
<VersionsItem
|
|
38
|
+
isCurrent={currentId === version.id}
|
|
39
|
+
isSelected={match.params.versionId === version.id}
|
|
40
|
+
version={version}
|
|
41
|
+
{...rest}
|
|
34
42
|
/>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
)}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<ul className="bcs-VersionsList">
|
|
49
|
+
{versions.map(version => (
|
|
50
|
+
<li className="bcs-VersionsList-item" key={version.id}>
|
|
51
|
+
{routerDisabled ? renderVersionItemWithoutRouter(version) : renderVersionItemWithRouter(version)}
|
|
52
|
+
</li>
|
|
53
|
+
))}
|
|
54
|
+
</ul>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
39
57
|
|
|
40
58
|
export default VersionsList;
|
|
@@ -11,11 +11,14 @@ import * as util from '../../../utils/datetime';
|
|
|
11
11
|
import messages from './messages';
|
|
12
12
|
import VersionsGroup from './VersionsGroup';
|
|
13
13
|
import type { BoxItemVersion } from '../../../common/types/core';
|
|
14
|
+
import type { InternalSidebarNavigation } from '../../common/types/SidebarNavigation';
|
|
14
15
|
import './VersionsMenu.scss';
|
|
15
16
|
|
|
16
17
|
type Props = {
|
|
17
18
|
fileId: string,
|
|
18
19
|
intl: any,
|
|
20
|
+
internalSidebarNavigation?: InternalSidebarNavigation,
|
|
21
|
+
routerDisabled?: boolean,
|
|
19
22
|
versionCount: number,
|
|
20
23
|
versionLimit: number,
|
|
21
24
|
versions: Array<BoxItemVersion>,
|
|
@@ -12,7 +12,7 @@ import InlineError from '../../../components/inline-error';
|
|
|
12
12
|
import messages from './messages';
|
|
13
13
|
import SidebarContent from '../SidebarContent';
|
|
14
14
|
import VersionsMenu from './VersionsMenu';
|
|
15
|
-
import
|
|
15
|
+
import BackButton from '../../common/back-button';
|
|
16
16
|
import { DEFAULT_FETCH_END } from '../../../constants';
|
|
17
17
|
import { LoadingIndicatorWrapper } from '../../../components/loading-indicator';
|
|
18
18
|
import type { BoxItemVersion } from '../../../common/types/core';
|
|
@@ -3,13 +3,11 @@ import { MemoryRouter, Route } from 'react-router-dom';
|
|
|
3
3
|
import { render, screen, userEvent } from '../../../../test-utils/testing-library';
|
|
4
4
|
import StaticVersionSidebar from '../StaticVersionSidebar';
|
|
5
5
|
|
|
6
|
-
jest.mock('../../../common/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
),
|
|
12
|
-
}));
|
|
6
|
+
jest.mock('../../../common/back-button', () => ({ onClick, 'data-resin-target': dataResinTarget }) => (
|
|
7
|
+
<button type="button" onClick={onClick} data-resin-target={dataResinTarget} data-testid="back-button">
|
|
8
|
+
Back
|
|
9
|
+
</button>
|
|
10
|
+
));
|
|
13
11
|
|
|
14
12
|
jest.mock('../VersionsMenu', () => ({ versions, fileId, versionCount, versionLimit }) => (
|
|
15
13
|
<div data-testid="versions-menu">
|