@axinom/mosaic-ui 0.49.0-rc.1 → 0.49.0-rc.11
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/components/DynamicDataList/DynamicDataList.d.ts +3 -1
- package/dist/components/DynamicDataList/DynamicDataList.d.ts.map +1 -1
- package/dist/components/DynamicDataList/DynamicListRow/DynamicListRow.d.ts +3 -1
- package/dist/components/DynamicDataList/DynamicListRow/DynamicListRow.d.ts.map +1 -1
- package/dist/components/Explorer/Explorer.d.ts +2 -0
- package/dist/components/Explorer/Explorer.d.ts.map +1 -1
- package/dist/components/Filters/Filter/Filter.d.ts +2 -1
- package/dist/components/Filters/Filter/Filter.d.ts.map +1 -1
- package/dist/components/Filters/SelectionTypes/FreeTextFilter/FreeTextFilter.d.ts +2 -0
- package/dist/components/Filters/SelectionTypes/FreeTextFilter/FreeTextFilter.d.ts.map +1 -1
- package/dist/components/FormStation/FormStationHeader/FormStationHeader.d.ts.map +1 -1
- package/dist/components/List/List.d.ts +2 -0
- package/dist/components/List/List.d.ts.map +1 -1
- package/dist/components/List/ListRow/ListRow.d.ts +4 -2
- package/dist/components/List/ListRow/ListRow.d.ts.map +1 -1
- package/dist/components/List/ListRow/ListRowLoader.d.ts +1 -1
- package/dist/components/List/ListRow/ListRowLoader.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeader.d.ts +9 -2
- package/dist/components/PageHeader/PageHeader.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeader.model.d.ts +11 -12
- package/dist/components/PageHeader/PageHeader.model.d.ts.map +1 -1
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.d.ts +35 -0
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.d.ts.map +1 -0
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroupsContext.d.ts +7 -0
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroupsContext.d.ts.map +1 -0
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroupsContextProvider.d.ts +3 -0
- package/dist/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroupsContextProvider.d.ts.map +1 -0
- package/dist/components/PageHeader/index.d.ts +1 -1
- package/dist/components/PageHeader/index.d.ts.map +1 -1
- package/dist/index.es.js +5 -4
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/{components/DynamicDataList/helpers/generateId.d.ts → utils/GenerateId.d.ts} +1 -1
- package/dist/utils/GenerateId.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/components/DynamicDataList/DynamicDataList.spec.tsx +2 -1
- package/src/components/DynamicDataList/DynamicDataList.stories.tsx +2 -1
- package/src/components/DynamicDataList/DynamicDataList.tsx +5 -1
- package/src/components/DynamicDataList/DynamicListRow/DynamicListRow.scss +11 -5
- package/src/components/DynamicDataList/DynamicListRow/DynamicListRow.spec.tsx +37 -0
- package/src/components/DynamicDataList/DynamicListRow/DynamicListRow.tsx +23 -14
- package/src/components/Explorer/Explorer.spec.tsx +26 -16
- package/src/components/Explorer/Explorer.stories.tsx +1 -0
- package/src/components/Explorer/Explorer.tsx +52 -28
- package/src/components/Explorer/NavigationExplorer/NavigationExplorer.spec.tsx +2 -2
- package/src/components/Explorer/SelectionExplorer/SelectionExplorer.spec.tsx +8 -32
- package/src/components/Filters/Filter/Filter.tsx +3 -0
- package/src/components/Filters/SelectionTypes/FreeTextFilter/FreeTextFilter.spec.tsx +16 -1
- package/src/components/Filters/SelectionTypes/FreeTextFilter/FreeTextFilter.tsx +13 -1
- package/src/components/FormStation/FormStationHeader/FormStationHeader.tsx +34 -30
- package/src/components/List/List.stories.tsx +2 -1
- package/src/components/List/List.tsx +5 -1
- package/src/components/List/ListRow/ListRow.scss +11 -4
- package/src/components/List/ListRow/ListRow.spec.tsx +35 -0
- package/src/components/List/ListRow/ListRow.tsx +44 -17
- package/src/components/List/ListRow/ListRowLoader.tsx +2 -2
- package/src/components/PageHeader/PageHeader.model.ts +10 -12
- package/src/components/PageHeader/PageHeader.scss +7 -3
- package/src/components/PageHeader/PageHeader.spec.tsx +28 -86
- package/src/components/PageHeader/PageHeader.stories.tsx +32 -7
- package/src/components/PageHeader/PageHeader.tsx +50 -77
- package/src/components/PageHeader/{PageHeaderBulkActions/PageHeaderBulkActions.scss → PageHeaderActionsGroup/PageHeaderActionsGroup.scss} +21 -21
- package/src/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.spec.tsx +105 -0
- package/src/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroup.tsx +224 -0
- package/src/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroupsContext.ts +13 -0
- package/src/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroupsContextProvider.tsx +30 -0
- package/src/components/PageHeader/index.ts +1 -1
- package/dist/components/DynamicDataList/helpers/generateId.d.ts.map +0 -1
- package/dist/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.d.ts +0 -22
- package/dist/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.d.ts.map +0 -1
- package/src/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.spec.tsx +0 -369
- package/src/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.tsx +0 -188
- /package/src/{components/DynamicDataList/helpers/generateId.ts → utils/GenerateId.ts} +0 -0
|
@@ -1,90 +1,57 @@
|
|
|
1
1
|
import clsx from 'clsx';
|
|
2
|
-
import React
|
|
3
|
-
import { noop } from '../../helpers/utils';
|
|
2
|
+
import React from 'react';
|
|
4
3
|
import { useTabTitle } from '../../hooks/useTabTitle/useTabTitle';
|
|
5
4
|
import { useWindowSize } from '../../hooks/useWindowSize/useWindowSize';
|
|
6
5
|
import { PageHeaderProps } from './PageHeader.model';
|
|
7
6
|
import classes from './PageHeader.scss';
|
|
7
|
+
import { PageHeaderActionProps } from './PageHeaderAction';
|
|
8
8
|
import { PageHeaderAction } from './PageHeaderAction/PageHeaderAction';
|
|
9
|
-
import {
|
|
9
|
+
import { PageHeaderActionsGroup } from './PageHeaderActionsGroup/PageHeaderActionsGroup';
|
|
10
|
+
import { PageHeaderActionsGroupContextProvider } from './PageHeaderActionsGroup/PageHeaderActionsGroupsContextProvider';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
|
-
* Primary header for stations. Accepts a title, subtitle, actions, and
|
|
13
|
+
* Primary header for stations. Accepts a title, subtitle, actions, and actions groups.
|
|
13
14
|
* @example
|
|
14
|
-
* <PageHeader title="title" subtitle="subtitle"
|
|
15
|
+
* <PageHeader title="title" subtitle="subtitle" actions={[
|
|
16
|
+
* { label: 'Undo', icon: IconName.Undo, kind: 'action', onClick: onActionSelected },
|
|
17
|
+
* { label: 'Cancel', icon: IconName.X, kind: 'action' onClick: onActionSelected },
|
|
18
|
+
* { kind: 'spacer' },
|
|
19
|
+
* { label: 'Actions Group', kind: 'group', actions: [
|
|
20
|
+
* { label: 'Action 1', actionType: PageHeaderActionType.Context, icon: IconName.Delete, confirmationMode: 'Advanced', onClick: onActionSelected },
|
|
21
|
+
* ]}
|
|
22
|
+
* ]} />
|
|
15
23
|
*/
|
|
16
24
|
export const PageHeader: React.FC<PageHeaderProps> = ({
|
|
17
25
|
title = '',
|
|
18
26
|
subtitle = '',
|
|
19
27
|
actions = [],
|
|
20
|
-
bulkActions = [],
|
|
21
|
-
bulkActionsDisabled = false,
|
|
22
|
-
openBulkActionsOnStart = false,
|
|
23
|
-
onBulkActionsToggled = noop,
|
|
24
28
|
className = '',
|
|
25
29
|
setTabTitle = true,
|
|
26
30
|
}) => {
|
|
27
|
-
const [containerScrollWidth, setContainerScrollWidth] = useState<number>(0);
|
|
28
|
-
const [childrenScrollWidth, setChildrenScrollWidth] = useState<number>(0);
|
|
29
|
-
const [availableActionSpace, setAvailableActionSpace] = useState<number>(0);
|
|
30
|
-
const ActionsWidth = 120;
|
|
31
|
-
const { width } = useWindowSize();
|
|
32
|
-
|
|
33
|
-
// Order of this useEffect hook is important
|
|
34
|
-
useEffect(() => {
|
|
35
|
-
setContainerScrollWidth(width);
|
|
36
|
-
}, [width]);
|
|
37
|
-
|
|
38
|
-
const actionsRef = (node: HTMLDivElement): void => {
|
|
39
|
-
if (node !== null) {
|
|
40
|
-
setChildrenScrollWidth(node.scrollWidth);
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
31
|
useTabTitle(title, setTabTitle);
|
|
32
|
+
const { width } = useWindowSize();
|
|
33
|
+
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
45
34
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (bulkActions.length > 0) {
|
|
49
|
-
const minimumTitleWidth = width >= 1920 ? 510 : 120;
|
|
50
|
-
const availableWidth: number =
|
|
51
|
-
containerScrollWidth - (minimumTitleWidth + childrenScrollWidth);
|
|
35
|
+
const [availableActionSpace, setAvailableActionSpace] =
|
|
36
|
+
React.useState<number>(0);
|
|
52
37
|
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
if (containerRef.current) {
|
|
40
|
+
// Use up to 75% of the container width for actions
|
|
41
|
+
const maxActionsWidth = containerRef.current.clientWidth * 0.75;
|
|
55
42
|
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
43
|
+
// Each action is 120px wide
|
|
44
|
+
setAvailableActionSpace(
|
|
45
|
+
Math.floor(maxActionsWidth / 120 - actions.length),
|
|
59
46
|
);
|
|
60
|
-
|
|
61
|
-
// determines if the 'more' action will take up an action slot
|
|
62
|
-
if (bulkActions.length > currentAvailableActionSpace) {
|
|
63
|
-
currentAvailableActionSpace -= moreActionSpace;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// prevents current available space from going negative
|
|
67
|
-
if (currentAvailableActionSpace < 0) {
|
|
68
|
-
currentAvailableActionSpace = 0;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// update available action space if the currentAvailableActionSpace has changed
|
|
72
|
-
if (currentAvailableActionSpace !== availableActionSpace) {
|
|
73
|
-
setAvailableActionSpace(currentAvailableActionSpace);
|
|
74
|
-
}
|
|
75
47
|
}
|
|
76
|
-
}, [
|
|
77
|
-
bulkActions,
|
|
78
|
-
availableActionSpace,
|
|
79
|
-
childrenScrollWidth,
|
|
80
|
-
containerScrollWidth,
|
|
81
|
-
width,
|
|
82
|
-
]);
|
|
48
|
+
}, [width, actions.length]);
|
|
83
49
|
|
|
84
50
|
return (
|
|
85
51
|
<div
|
|
86
52
|
className={clsx(classes.container, 'page-header-container', className)}
|
|
87
53
|
data-test-id="page-header"
|
|
54
|
+
ref={containerRef}
|
|
88
55
|
>
|
|
89
56
|
<div className={clsx(classes.titles)}>
|
|
90
57
|
<div className={clsx(classes.title)} data-test-id="page-header-title">
|
|
@@ -98,24 +65,30 @@ export const PageHeader: React.FC<PageHeaderProps> = ({
|
|
|
98
65
|
{subtitle}
|
|
99
66
|
</div>
|
|
100
67
|
</div>
|
|
101
|
-
{
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
68
|
+
<div className={classes.actions} data-test-id="page-header-actions">
|
|
69
|
+
<PageHeaderActionsGroupContextProvider>
|
|
70
|
+
{actions.map((action, index) => {
|
|
71
|
+
switch (action.kind) {
|
|
72
|
+
case 'group':
|
|
73
|
+
return (
|
|
74
|
+
<PageHeaderActionsGroup
|
|
75
|
+
key={index}
|
|
76
|
+
{...action}
|
|
77
|
+
availableActionSpace={availableActionSpace}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
case 'spacer':
|
|
81
|
+
return <div key={index} className={classes.spacer} />;
|
|
82
|
+
case 'action':
|
|
83
|
+
return (
|
|
84
|
+
<PageHeaderAction
|
|
85
|
+
key={index}
|
|
86
|
+
{...(action as PageHeaderActionProps)}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
})}
|
|
91
|
+
</PageHeaderActionsGroupContextProvider>
|
|
119
92
|
</div>
|
|
120
93
|
</div>
|
|
121
94
|
);
|
|
@@ -2,36 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
.container {
|
|
4
4
|
display: grid;
|
|
5
|
-
grid-template-rows: 1fr;
|
|
6
|
-
grid-
|
|
5
|
+
grid-template-rows: $page-header-height 1fr;
|
|
6
|
+
grid-template-columns: max-content 1fr;
|
|
7
7
|
grid-gap: 1px;
|
|
8
8
|
justify-content: end;
|
|
9
|
+
width: max-content;
|
|
9
10
|
|
|
10
|
-
.
|
|
11
|
-
width: 120px;
|
|
11
|
+
.actions {
|
|
12
12
|
display: grid;
|
|
13
|
-
grid-
|
|
14
|
-
grid-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
grid-auto-flow: column;
|
|
14
|
+
grid-gap: 1px;
|
|
15
|
+
transition: max-width 200ms linear, opacity 150ms linear;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
}
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
.dropDownList {
|
|
20
|
+
width: 100%;
|
|
21
|
+
max-width: 360px;
|
|
22
|
+
display: grid;
|
|
23
|
+
grid-template-columns: 1fr;
|
|
24
|
+
grid-auto-rows: 60px;
|
|
25
|
+
grid-gap: 1px;
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
border-top: 2px solid white;
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
right: 0px;
|
|
29
|
+
grid-column: 1 / span 2;
|
|
30
|
+
place-self: end;
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
background-color: white;
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
}
|
|
34
|
+
z-index: 2;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { mount, shallow } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { noop } from '../../../helpers/utils';
|
|
4
|
+
import { PageHeaderAction } from '../PageHeaderAction/PageHeaderAction';
|
|
5
|
+
import {
|
|
6
|
+
PageHeaderActionProps,
|
|
7
|
+
PageHeaderActionType,
|
|
8
|
+
} from '../PageHeaderAction/PageHeaderAction.model';
|
|
9
|
+
import {
|
|
10
|
+
PageHeaderActionsGroup,
|
|
11
|
+
PageHeaderActionsGroupProps,
|
|
12
|
+
} from './PageHeaderActionsGroup';
|
|
13
|
+
|
|
14
|
+
jest.mock('../../../utils/GenerateId', () => ({
|
|
15
|
+
uuid: jest.fn().mockReturnValue('test-uuid'),
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
const defaultActions: PageHeaderActionProps[] = [
|
|
19
|
+
{
|
|
20
|
+
label: 'Group Action 1',
|
|
21
|
+
onClick: noop,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: 'Group Action 2',
|
|
25
|
+
onClick: noop,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: 'Group Action 3',
|
|
29
|
+
onClick: noop,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: 'Group Action 4',
|
|
33
|
+
onClick: noop,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const defaultProps: PageHeaderActionsGroupProps = {
|
|
38
|
+
label: 'Group Actions',
|
|
39
|
+
actions: defaultActions,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
describe('PageHeaderActionsGroup', () => {
|
|
43
|
+
it('renders the component without crashing', () => {
|
|
44
|
+
const wrapper = shallow(<PageHeaderActionsGroup {...defaultProps} />);
|
|
45
|
+
expect(wrapper).toBeTruthy();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it(`'Group Actions' has the 'Context' actionType when closed and 'Active' actionType when open`, () => {
|
|
49
|
+
const wrapper = mount(<PageHeaderActionsGroup {...defaultProps} />);
|
|
50
|
+
let groupActionsToggle = wrapper.find(PageHeaderAction).first();
|
|
51
|
+
// let action = wrapper.find(PageHeaderAction);
|
|
52
|
+
|
|
53
|
+
expect(groupActionsToggle.prop('actionType')).toBe(
|
|
54
|
+
PageHeaderActionType.Context,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
groupActionsToggle.simulate('click');
|
|
58
|
+
|
|
59
|
+
groupActionsToggle = wrapper.find(PageHeaderAction).first();
|
|
60
|
+
|
|
61
|
+
expect(groupActionsToggle.prop('actionType')).toBe(
|
|
62
|
+
PageHeaderActionType.Active,
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it(`renders all actions when 'Group Actions' is selected and there is enough available action slots`, () => {
|
|
67
|
+
const wrapper = mount(
|
|
68
|
+
<PageHeaderActionsGroup {...defaultProps} availableActionSpace={5} />,
|
|
69
|
+
);
|
|
70
|
+
const groupActionsToggle = wrapper.find(PageHeaderAction).first();
|
|
71
|
+
let actions = wrapper.find(PageHeaderAction);
|
|
72
|
+
|
|
73
|
+
groupActionsToggle.simulate('click');
|
|
74
|
+
actions = wrapper.find(PageHeaderAction);
|
|
75
|
+
expect(actions).toHaveLength(5);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it(`raises onActionsGroupToggled`, () => {
|
|
79
|
+
const groupActionSpy = jest.fn();
|
|
80
|
+
const wrapper = mount(
|
|
81
|
+
<PageHeaderActionsGroup
|
|
82
|
+
{...defaultProps}
|
|
83
|
+
onActionsGroupToggled={groupActionSpy}
|
|
84
|
+
/>,
|
|
85
|
+
);
|
|
86
|
+
const groupActionsToggle = wrapper.find(PageHeaderAction).first();
|
|
87
|
+
groupActionsToggle.simulate('click');
|
|
88
|
+
expect(groupActionSpy).toHaveBeenCalledTimes(1);
|
|
89
|
+
expect(groupActionSpy).toHaveBeenCalledWith(true);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it(`renders 'Group Actions' and 'More Actions' if openActionsGroupOnStart is set to true and there isn't enough available space`, () => {
|
|
93
|
+
const wrapper = mount(
|
|
94
|
+
<PageHeaderActionsGroup
|
|
95
|
+
{...defaultProps}
|
|
96
|
+
openActionsGroupOnStart={true}
|
|
97
|
+
availableActionSpace={3}
|
|
98
|
+
/>,
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const actions = wrapper.find(PageHeaderAction);
|
|
102
|
+
|
|
103
|
+
expect(actions).toHaveLength(4);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import clsx from 'clsx';
|
|
2
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { noop } from '../../../helpers/utils';
|
|
4
|
+
import { useExpand } from '../../../hooks/useExpand/useExpand';
|
|
5
|
+
import { uuid } from '../../../utils/GenerateId';
|
|
6
|
+
import { ConfirmationMode } from '../../ConfirmDialog';
|
|
7
|
+
import { IconName } from '../../Icons';
|
|
8
|
+
import {
|
|
9
|
+
PageHeaderAction,
|
|
10
|
+
isPageHeaderJsAction,
|
|
11
|
+
} from '../PageHeaderAction/PageHeaderAction';
|
|
12
|
+
import {
|
|
13
|
+
PageHeaderActionProps,
|
|
14
|
+
PageHeaderActionType,
|
|
15
|
+
} from '../PageHeaderAction/PageHeaderAction.model';
|
|
16
|
+
import classes from './PageHeaderActionsGroup.scss';
|
|
17
|
+
import { PageHeaderActionsGroupContext } from './PageHeaderActionsGroupsContext';
|
|
18
|
+
|
|
19
|
+
export interface PageHeaderActionsGroupProps {
|
|
20
|
+
/** Array of Actions to be rendered (default: []) */
|
|
21
|
+
actions: PageHeaderActionProps[];
|
|
22
|
+
/** Whether group is disabled (default: false) */
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/** Whether actions in the group are disabled or not (default: false)*/
|
|
25
|
+
groupActionsDisabled?: boolean;
|
|
26
|
+
/** CSS Class name for additional styles */
|
|
27
|
+
className?: string;
|
|
28
|
+
/** The label of the action. */
|
|
29
|
+
label: string;
|
|
30
|
+
/** Optional built in icon. This prop also accepts an img src. */
|
|
31
|
+
icon?: IconName | string;
|
|
32
|
+
/** Whether group actions are shown by default. (default: false) */
|
|
33
|
+
openActionsGroupOnStart?: boolean;
|
|
34
|
+
/** The number of actions that can be displayed in the group. (default: actions.length) */
|
|
35
|
+
availableActionSpace?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Callback to emit when Group Actions is toggled
|
|
38
|
+
* The expanded state is supplied as an argument
|
|
39
|
+
*/
|
|
40
|
+
onActionsGroupToggled?: (expanded: boolean) => void;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Used to perform group operations from the PageHeader component.
|
|
45
|
+
* @example
|
|
46
|
+
* <PageHeaderActionsGroup>
|
|
47
|
+
* <PageHeaderAction action={action} onActionsGroupToggled={onActionsGroupToggledHandler} />
|
|
48
|
+
* </PageHeaderActionsGroup>
|
|
49
|
+
*/
|
|
50
|
+
export const PageHeaderActionsGroup: React.FC<PageHeaderActionsGroupProps> = ({
|
|
51
|
+
actions = [],
|
|
52
|
+
openActionsGroupOnStart = false,
|
|
53
|
+
label,
|
|
54
|
+
icon,
|
|
55
|
+
onActionsGroupToggled = noop,
|
|
56
|
+
groupActionsDisabled = false,
|
|
57
|
+
disabled = false,
|
|
58
|
+
availableActionSpace = actions.length,
|
|
59
|
+
className = '',
|
|
60
|
+
}) => {
|
|
61
|
+
const [uniqueId] = useState<string>(uuid());
|
|
62
|
+
const { isExpanded, toggleExpanded, collapse } = useExpand(
|
|
63
|
+
openActionsGroupOnStart,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const { registerCollapse, collapseAll } = React.useContext(
|
|
67
|
+
PageHeaderActionsGroupContext,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const customCollapse = useCallback(() => {
|
|
71
|
+
collapse();
|
|
72
|
+
onActionsGroupToggled(false);
|
|
73
|
+
}, [collapse, onActionsGroupToggled]);
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
registerCollapse(customCollapse, uniqueId);
|
|
77
|
+
}, [customCollapse, registerCollapse, uniqueId]);
|
|
78
|
+
|
|
79
|
+
const {
|
|
80
|
+
isExpanded: isMoreExpanded,
|
|
81
|
+
expand: moreExpanded,
|
|
82
|
+
collapse: moreCollapse,
|
|
83
|
+
toggleExpanded: toggleMoreExpanded,
|
|
84
|
+
} = useExpand();
|
|
85
|
+
|
|
86
|
+
const [isMouseOverMore, setIsMouseOverMore] = useState<boolean>(false);
|
|
87
|
+
const [isConfirmOpen, setIsConfirmOpen] = useState<Record<string, boolean>>(
|
|
88
|
+
{},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const onConfirmToggled = (
|
|
92
|
+
isOpen: boolean,
|
|
93
|
+
data: { id: string; mode: ConfirmationMode },
|
|
94
|
+
): void => {
|
|
95
|
+
setIsConfirmOpen((prevState) => {
|
|
96
|
+
return { ...prevState, [data.id]: isOpen };
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
useEffect(() => {
|
|
101
|
+
const hasConfirm: boolean = Object.values(isConfirmOpen).includes(true);
|
|
102
|
+
|
|
103
|
+
// open drop down
|
|
104
|
+
if (isMouseOverMore) {
|
|
105
|
+
moreExpanded();
|
|
106
|
+
// close drop down if no confirmation is active
|
|
107
|
+
} else if (!isMouseOverMore && !hasConfirm) {
|
|
108
|
+
moreCollapse();
|
|
109
|
+
// keep the drop down open if confirmation is active
|
|
110
|
+
} else if (!isMouseOverMore && hasConfirm) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
}, [isConfirmOpen, isMouseOverMore, moreCollapse, moreExpanded]);
|
|
114
|
+
|
|
115
|
+
const actionsSlice =
|
|
116
|
+
availableActionSpace < actions.length
|
|
117
|
+
? availableActionSpace - 1
|
|
118
|
+
: availableActionSpace;
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div
|
|
122
|
+
className={clsx(
|
|
123
|
+
classes.container,
|
|
124
|
+
'page-header-group-action-container',
|
|
125
|
+
className,
|
|
126
|
+
)}
|
|
127
|
+
onMouseLeave={() => setIsMouseOverMore(false)}
|
|
128
|
+
>
|
|
129
|
+
<PageHeaderAction
|
|
130
|
+
label={label}
|
|
131
|
+
actionType={
|
|
132
|
+
isExpanded
|
|
133
|
+
? PageHeaderActionType.Active
|
|
134
|
+
: PageHeaderActionType.Context
|
|
135
|
+
}
|
|
136
|
+
icon={icon}
|
|
137
|
+
onClick={() => {
|
|
138
|
+
if (!isExpanded) {
|
|
139
|
+
collapseAll();
|
|
140
|
+
}
|
|
141
|
+
toggleExpanded();
|
|
142
|
+
onActionsGroupToggled(!isExpanded);
|
|
143
|
+
}}
|
|
144
|
+
disabled={disabled}
|
|
145
|
+
/>
|
|
146
|
+
<div
|
|
147
|
+
style={{
|
|
148
|
+
maxWidth: isExpanded
|
|
149
|
+
? `${Math.min(availableActionSpace, actions.length) * 121}px`
|
|
150
|
+
: `0px`,
|
|
151
|
+
opacity: isExpanded ? 1 : 0,
|
|
152
|
+
}}
|
|
153
|
+
className={classes.actions}
|
|
154
|
+
>
|
|
155
|
+
{actions.slice(0, actionsSlice).map((action, idx) =>
|
|
156
|
+
isPageHeaderJsAction(action) ? (
|
|
157
|
+
<PageHeaderAction
|
|
158
|
+
key={idx}
|
|
159
|
+
{...action}
|
|
160
|
+
disabled={groupActionsDisabled}
|
|
161
|
+
confirmationConfig={{
|
|
162
|
+
...action.confirmationConfig,
|
|
163
|
+
onConfirmOpen: (isOpen: boolean, args: unknown) => {
|
|
164
|
+
onConfirmToggled(
|
|
165
|
+
isOpen,
|
|
166
|
+
args as { id: string; mode: ConfirmationMode },
|
|
167
|
+
);
|
|
168
|
+
action.confirmationConfig?.onConfirmOpen?.(isOpen, args);
|
|
169
|
+
},
|
|
170
|
+
}}
|
|
171
|
+
/>
|
|
172
|
+
) : (
|
|
173
|
+
<PageHeaderAction key={idx} {...action} />
|
|
174
|
+
),
|
|
175
|
+
)}
|
|
176
|
+
{actions.length > availableActionSpace && (
|
|
177
|
+
<div onMouseEnter={() => setIsMouseOverMore(true)}>
|
|
178
|
+
<PageHeaderAction
|
|
179
|
+
label="More"
|
|
180
|
+
icon={IconName.Ellipsis}
|
|
181
|
+
actionType={
|
|
182
|
+
isMoreExpanded
|
|
183
|
+
? PageHeaderActionType.Active
|
|
184
|
+
: PageHeaderActionType.Context
|
|
185
|
+
}
|
|
186
|
+
onClick={() => toggleMoreExpanded()}
|
|
187
|
+
/>
|
|
188
|
+
</div>
|
|
189
|
+
)}
|
|
190
|
+
</div>
|
|
191
|
+
{isMoreExpanded && (
|
|
192
|
+
<div className={clsx(classes.dropDownList)}>
|
|
193
|
+
{actions.slice(actionsSlice).map((action, idx) =>
|
|
194
|
+
isPageHeaderJsAction(action) ? (
|
|
195
|
+
<PageHeaderAction
|
|
196
|
+
key={idx}
|
|
197
|
+
{...action}
|
|
198
|
+
disabled={groupActionsDisabled}
|
|
199
|
+
onClick={() => {
|
|
200
|
+
action.onClick();
|
|
201
|
+
moreCollapse();
|
|
202
|
+
setIsMouseOverMore(false);
|
|
203
|
+
}}
|
|
204
|
+
className={clsx(classes.dropDown)}
|
|
205
|
+
confirmationConfig={{
|
|
206
|
+
...action.confirmationConfig,
|
|
207
|
+
onConfirmOpen: (isOpen, args) => {
|
|
208
|
+
onConfirmToggled(
|
|
209
|
+
isOpen,
|
|
210
|
+
args as { id: string; mode: ConfirmationMode },
|
|
211
|
+
);
|
|
212
|
+
action.confirmationConfig?.onConfirmOpen?.(isOpen, args);
|
|
213
|
+
},
|
|
214
|
+
}}
|
|
215
|
+
/>
|
|
216
|
+
) : (
|
|
217
|
+
<PageHeaderAction key={idx} {...action} />
|
|
218
|
+
),
|
|
219
|
+
)}
|
|
220
|
+
</div>
|
|
221
|
+
)}
|
|
222
|
+
</div>
|
|
223
|
+
);
|
|
224
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
import { noop } from '../../../helpers/utils';
|
|
3
|
+
|
|
4
|
+
export interface PageHeaderActionsGroupContextType {
|
|
5
|
+
registerCollapse: (readonly: () => void, uuid: string) => void;
|
|
6
|
+
collapseAll: () => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const PageHeaderActionsGroupContext =
|
|
10
|
+
createContext<PageHeaderActionsGroupContextType>({
|
|
11
|
+
registerCollapse: noop,
|
|
12
|
+
collapseAll: noop,
|
|
13
|
+
});
|
package/src/components/PageHeader/PageHeaderActionsGroup/PageHeaderActionsGroupsContextProvider.tsx
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import { PageHeaderActionsGroupContext } from './PageHeaderActionsGroupsContext';
|
|
3
|
+
|
|
4
|
+
type CollapseAction = Record<string, () => void>;
|
|
5
|
+
|
|
6
|
+
export const PageHeaderActionsGroupContextProvider: React.FC = ({
|
|
7
|
+
children,
|
|
8
|
+
}) => {
|
|
9
|
+
const [registeredCollapses, setRegisteredCollapses] =
|
|
10
|
+
useState<CollapseAction>({});
|
|
11
|
+
|
|
12
|
+
const registerCollapse = useCallback(
|
|
13
|
+
(collapse: () => void, uuid: string): void => {
|
|
14
|
+
setRegisteredCollapses((prev) => ({ ...prev, [uuid]: collapse }));
|
|
15
|
+
},
|
|
16
|
+
[],
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const collapseAll = useCallback(() => {
|
|
20
|
+
Object.values(registeredCollapses).forEach((collapse) => collapse());
|
|
21
|
+
}, [registeredCollapses]);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<PageHeaderActionsGroupContext.Provider
|
|
25
|
+
value={{ registerCollapse, collapseAll }}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</PageHeaderActionsGroupContext.Provider>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generateId.d.ts","sourceRoot":"","sources":["../../../../src/components/DynamicDataList/helpers/generateId.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,IAAI,QAAO,MAKvB,CAAC"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { PageHeaderProps } from '../PageHeader.model';
|
|
3
|
-
import { PageHeaderActionProps } from '../PageHeaderAction/PageHeaderAction.model';
|
|
4
|
-
export interface PageHeaderBulkActionsProps extends Pick<PageHeaderProps, 'openBulkActionsOnStart' | 'onBulkActionsToggled'> {
|
|
5
|
-
/** Array of Actions to be rendered (default: []) */
|
|
6
|
-
actions?: PageHeaderActionProps[];
|
|
7
|
-
/** Number of available slots actions can use in the PageHeader */
|
|
8
|
-
availableActionSpace: number;
|
|
9
|
-
/** Whether or not bulk actions are disabled (default: false)*/
|
|
10
|
-
bulkActionsDisabled?: boolean;
|
|
11
|
-
/** CSS Class name for additional styles */
|
|
12
|
-
className?: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Used to perform bulk operations from the PageHeader component.
|
|
16
|
-
* @example
|
|
17
|
-
* <PageHeaderBulkActions>
|
|
18
|
-
* <PageHeaderAction action={action} onBulkActionsToggled={onBulkActionsToggledHandler} />
|
|
19
|
-
* </PageHeaderBulkActions>
|
|
20
|
-
*/
|
|
21
|
-
export declare const PageHeaderBulkActions: React.FC<PageHeaderBulkActionsProps>;
|
|
22
|
-
//# sourceMappingURL=PageHeaderBulkActions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PageHeaderBulkActions.d.ts","sourceRoot":"","sources":["../../../../src/components/PageHeader/PageHeaderBulkActions/PageHeaderBulkActions.tsx"],"names":[],"mappings":"AACA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAKnD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAKtD,OAAO,EACL,qBAAqB,EAEtB,MAAM,4CAA4C,CAAC;AAGpD,MAAM,WAAW,0BACf,SAAQ,IAAI,CACV,eAAe,EACf,wBAAwB,GAAG,sBAAsB,CAClD;IACD,oDAAoD;IACpD,OAAO,CAAC,EAAE,qBAAqB,EAAE,CAAC;IAClC,kEAAkE;IAClE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,+DAA+D;IAC/D,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAoJtE,CAAC"}
|