@openmrs/esm-styleguide 11.0.1-pre.5825 → 11.0.1-pre.5836
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/.turbo/turbo-build.log +1 -1
- package/dist/workspaces2/action-menu2/action-menu-button2.component.d.ts +15 -0
- package/dist/workspaces2/action-menu2/action-menu-button2.component.d.ts.map +1 -1
- package/dist/workspaces2/action-menu2/action-menu-button2.component.js +6 -1
- package/package.json +25 -25
- package/src/workspaces2/action-menu2/action-menu-button2.component.tsx +24 -0
- package/src/workspaces2/action-menu2/action-menu-button2.test.tsx +94 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
[0] Successfully compiled: 117 files, copied 171 files with swc (
|
|
1
|
+
[0] Successfully compiled: 117 files, copied 171 files with swc (326.49ms)
|
|
2
2
|
[0] swc --strip-leading-paths --copy-files src -d dist && svgo -rf dist --quiet exited with code 0
|
|
3
3
|
[1] tsc --project tsconfig.build.json exited with code 0
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** @module @category Workspace */
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { type OpenedWindow } from '@openmrs/esm-extensions';
|
|
3
4
|
export interface ActionMenuButtonProps2 {
|
|
4
5
|
icon: (props: object) => JSX.Element;
|
|
5
6
|
label: string;
|
|
@@ -18,6 +19,20 @@ export interface ActionMenuButtonProps2 {
|
|
|
18
19
|
*
|
|
19
20
|
*/
|
|
20
21
|
onBeforeWorkspaceLaunch?: () => Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* An optional callback function to determine whether the action menu button
|
|
24
|
+
* should be disabled based on the openedWindows state of the workspace group
|
|
25
|
+
* @param openedWindows
|
|
26
|
+
* @returns true if the action menu button should be disabled and false if it should be enabled
|
|
27
|
+
*/
|
|
28
|
+
disabled?: (openedWindows: Array<OpenedWindow>) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* An optional callback function to determine whether the action menu button
|
|
31
|
+
* should be hidden based on the openedWindows state of the workspace group
|
|
32
|
+
* @param openedWindows
|
|
33
|
+
* @returns true if the action menu button should be hidden and false if it should be shown
|
|
34
|
+
*/
|
|
35
|
+
hidden?: (openedWindows: Array<OpenedWindow>) => boolean;
|
|
21
36
|
}
|
|
22
37
|
/**
|
|
23
38
|
* The ActionMenuButton2 component is used to render a button in the action menu of a workspace group.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-menu-button2.component.d.ts","sourceRoot":"","sources":["../../../src/workspaces2/action-menu2/action-menu-button2.component.tsx"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,OAAO,KAAqB,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"action-menu-button2.component.d.ts","sourceRoot":"","sources":["../../../src/workspaces2/action-menu2/action-menu-button2.component.tsx"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,OAAO,KAAqB,MAAM,OAAO,CAAC;AAK1C,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAwB5D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IACtC,iBAAiB,EAAE;QACjB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACrC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KACnC,CAAC;IAEF;;;;;;;OAOG;IACH,uBAAuB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC;IAE3D;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC;CAC1D;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CAqF9D,CAAC"}
|
|
@@ -34,7 +34,7 @@ function Tags({ getIcon, hasUnsavedChanges, tagContent }) {
|
|
|
34
34
|
* 2. restores the workspace window if it is opened and unfocused; or
|
|
35
35
|
* 3. launches a workspace from within that window, if the window is not opened.
|
|
36
36
|
*
|
|
37
|
-
*/ export const ActionMenuButton2 = ({ icon: getIcon, label, tagContent, workspaceToLaunch, onBeforeWorkspaceLaunch })=>{
|
|
37
|
+
*/ export const ActionMenuButton2 = ({ icon: getIcon, label, tagContent, workspaceToLaunch, onBeforeWorkspaceLaunch, hidden, disabled })=>{
|
|
38
38
|
const layout = useLayoutType();
|
|
39
39
|
const { openedWindows, restoreWindow, hideWindow, isMostRecentlyOpenedWindowHidden } = useWorkspace2Store();
|
|
40
40
|
const { extension } = useContext(ComponentContext);
|
|
@@ -60,6 +60,9 @@ function Tags({ getIcon, hasUnsavedChanges, tagContent }) {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
|
+
if (hidden?.(openedWindows)) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
63
66
|
if (layout === 'tablet' || layout === 'phone') {
|
|
64
67
|
return /*#__PURE__*/ _jsxs(Button, {
|
|
65
68
|
className: classNames(styles.container, {
|
|
@@ -72,6 +75,7 @@ function Tags({ getIcon, hasUnsavedChanges, tagContent }) {
|
|
|
72
75
|
role: "button",
|
|
73
76
|
tabIndex: 0,
|
|
74
77
|
size: "md",
|
|
78
|
+
disabled: disabled?.(openedWindows),
|
|
75
79
|
children: [
|
|
76
80
|
/*#__PURE__*/ _jsx("span", {
|
|
77
81
|
className: styles.elementContainer,
|
|
@@ -99,6 +103,7 @@ function Tags({ getIcon, hasUnsavedChanges, tagContent }) {
|
|
|
99
103
|
label: label,
|
|
100
104
|
onClick: onClick,
|
|
101
105
|
size: "md",
|
|
106
|
+
disabled: disabled?.(openedWindows),
|
|
102
107
|
children: /*#__PURE__*/ _jsx("div", {
|
|
103
108
|
className: styles.elementContainer,
|
|
104
109
|
children: /*#__PURE__*/ _jsx(Tags, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmrs/esm-styleguide",
|
|
3
|
-
"version": "11.0.1-pre.
|
|
3
|
+
"version": "11.0.1-pre.5836",
|
|
4
4
|
"license": "MPL-2.0",
|
|
5
5
|
"description": "The styleguide for OpenMRS SPA",
|
|
6
6
|
"module": "dist/internal.js",
|
|
@@ -79,18 +79,18 @@
|
|
|
79
79
|
"uuid": "^11.1.1"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
|
-
"@openmrs/esm-api": "^11.0.1-pre.
|
|
83
|
-
"@openmrs/esm-config": "^11.0.1-pre.
|
|
84
|
-
"@openmrs/esm-emr-api": "^11.0.1-pre.
|
|
85
|
-
"@openmrs/esm-error-handling": "^11.0.1-pre.
|
|
86
|
-
"@openmrs/esm-extensions": "^11.0.1-pre.
|
|
87
|
-
"@openmrs/esm-globals": "^11.0.1-pre.
|
|
88
|
-
"@openmrs/esm-navigation": "^11.0.1-pre.
|
|
89
|
-
"@openmrs/esm-react-utils": "^11.0.1-pre.
|
|
90
|
-
"@openmrs/esm-routes": "^11.0.1-pre.
|
|
91
|
-
"@openmrs/esm-state": "^11.0.1-pre.
|
|
92
|
-
"@openmrs/esm-translations": "^11.0.1-pre.
|
|
93
|
-
"@openmrs/esm-utils": "^11.0.1-pre.
|
|
82
|
+
"@openmrs/esm-api": "^11.0.1-pre.5836",
|
|
83
|
+
"@openmrs/esm-config": "^11.0.1-pre.5836",
|
|
84
|
+
"@openmrs/esm-emr-api": "^11.0.1-pre.5836",
|
|
85
|
+
"@openmrs/esm-error-handling": "^11.0.1-pre.5836",
|
|
86
|
+
"@openmrs/esm-extensions": "^11.0.1-pre.5836",
|
|
87
|
+
"@openmrs/esm-globals": "^11.0.1-pre.5836",
|
|
88
|
+
"@openmrs/esm-navigation": "^11.0.1-pre.5836",
|
|
89
|
+
"@openmrs/esm-react-utils": "^11.0.1-pre.5836",
|
|
90
|
+
"@openmrs/esm-routes": "^11.0.1-pre.5836",
|
|
91
|
+
"@openmrs/esm-state": "^11.0.1-pre.5836",
|
|
92
|
+
"@openmrs/esm-translations": "^11.0.1-pre.5836",
|
|
93
|
+
"@openmrs/esm-utils": "^11.0.1-pre.5836",
|
|
94
94
|
"dayjs": "1.x",
|
|
95
95
|
"i18next": "25.x",
|
|
96
96
|
"react": "18.x",
|
|
@@ -99,18 +99,18 @@
|
|
|
99
99
|
"swr": "2.x"
|
|
100
100
|
},
|
|
101
101
|
"devDependencies": {
|
|
102
|
-
"@openmrs/esm-api": "11.0.1-pre.
|
|
103
|
-
"@openmrs/esm-config": "11.0.1-pre.
|
|
104
|
-
"@openmrs/esm-emr-api": "11.0.1-pre.
|
|
105
|
-
"@openmrs/esm-error-handling": "11.0.1-pre.
|
|
106
|
-
"@openmrs/esm-extensions": "11.0.1-pre.
|
|
107
|
-
"@openmrs/esm-globals": "11.0.1-pre.
|
|
108
|
-
"@openmrs/esm-navigation": "11.0.1-pre.
|
|
109
|
-
"@openmrs/esm-react-utils": "11.0.1-pre.
|
|
110
|
-
"@openmrs/esm-routes": "11.0.1-pre.
|
|
111
|
-
"@openmrs/esm-state": "11.0.1-pre.
|
|
112
|
-
"@openmrs/esm-translations": "11.0.1-pre.
|
|
113
|
-
"@openmrs/esm-utils": "11.0.1-pre.
|
|
102
|
+
"@openmrs/esm-api": "11.0.1-pre.5836",
|
|
103
|
+
"@openmrs/esm-config": "11.0.1-pre.5836",
|
|
104
|
+
"@openmrs/esm-emr-api": "11.0.1-pre.5836",
|
|
105
|
+
"@openmrs/esm-error-handling": "11.0.1-pre.5836",
|
|
106
|
+
"@openmrs/esm-extensions": "11.0.1-pre.5836",
|
|
107
|
+
"@openmrs/esm-globals": "11.0.1-pre.5836",
|
|
108
|
+
"@openmrs/esm-navigation": "11.0.1-pre.5836",
|
|
109
|
+
"@openmrs/esm-react-utils": "11.0.1-pre.5836",
|
|
110
|
+
"@openmrs/esm-routes": "11.0.1-pre.5836",
|
|
111
|
+
"@openmrs/esm-state": "11.0.1-pre.5836",
|
|
112
|
+
"@openmrs/esm-translations": "11.0.1-pre.5836",
|
|
113
|
+
"@openmrs/esm-utils": "11.0.1-pre.5836",
|
|
114
114
|
"@swc/cli": "0.8.1",
|
|
115
115
|
"@swc/core": "1.15.21",
|
|
116
116
|
"@types/geopattern": "^1.2.9",
|
|
@@ -47,6 +47,22 @@ export interface ActionMenuButtonProps2 {
|
|
|
47
47
|
*
|
|
48
48
|
*/
|
|
49
49
|
onBeforeWorkspaceLaunch?: () => Promise<boolean>;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* An optional callback function to determine whether the action menu button
|
|
53
|
+
* should be disabled based on the openedWindows state of the workspace group
|
|
54
|
+
* @param openedWindows
|
|
55
|
+
* @returns true if the action menu button should be disabled and false if it should be enabled
|
|
56
|
+
*/
|
|
57
|
+
disabled?: (openedWindows: Array<OpenedWindow>) => boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* An optional callback function to determine whether the action menu button
|
|
61
|
+
* should be hidden based on the openedWindows state of the workspace group
|
|
62
|
+
* @param openedWindows
|
|
63
|
+
* @returns true if the action menu button should be hidden and false if it should be shown
|
|
64
|
+
*/
|
|
65
|
+
hidden?: (openedWindows: Array<OpenedWindow>) => boolean;
|
|
50
66
|
}
|
|
51
67
|
|
|
52
68
|
/**
|
|
@@ -69,6 +85,8 @@ export const ActionMenuButton2: React.FC<ActionMenuButtonProps2> = ({
|
|
|
69
85
|
tagContent,
|
|
70
86
|
workspaceToLaunch,
|
|
71
87
|
onBeforeWorkspaceLaunch,
|
|
88
|
+
hidden,
|
|
89
|
+
disabled,
|
|
72
90
|
}) => {
|
|
73
91
|
const layout = useLayoutType();
|
|
74
92
|
const { openedWindows, restoreWindow, hideWindow, isMostRecentlyOpenedWindowHidden } = useWorkspace2Store();
|
|
@@ -99,6 +117,10 @@ export const ActionMenuButton2: React.FC<ActionMenuButtonProps2> = ({
|
|
|
99
117
|
}
|
|
100
118
|
};
|
|
101
119
|
|
|
120
|
+
if (hidden?.(openedWindows)) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
|
|
102
124
|
if (layout === 'tablet' || layout === 'phone') {
|
|
103
125
|
return (
|
|
104
126
|
<Button
|
|
@@ -112,6 +134,7 @@ export const ActionMenuButton2: React.FC<ActionMenuButtonProps2> = ({
|
|
|
112
134
|
role="button"
|
|
113
135
|
tabIndex={0}
|
|
114
136
|
size="md"
|
|
137
|
+
disabled={disabled?.(openedWindows)}
|
|
115
138
|
>
|
|
116
139
|
<span className={styles.elementContainer}>
|
|
117
140
|
<Tags hasUnsavedChanges={hasUnsavedChanges} getIcon={getIcon} tagContent={tagContent} />
|
|
@@ -134,6 +157,7 @@ export const ActionMenuButton2: React.FC<ActionMenuButtonProps2> = ({
|
|
|
134
157
|
label={label}
|
|
135
158
|
onClick={onClick}
|
|
136
159
|
size="md"
|
|
160
|
+
disabled={disabled?.(openedWindows)}
|
|
137
161
|
>
|
|
138
162
|
<div className={styles.elementContainer}>
|
|
139
163
|
<Tags hasUnsavedChanges={hasUnsavedChanges} getIcon={getIcon} tagContent={tagContent} />
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import { ComponentContext, useLayoutType } from '@openmrs/esm-react-utils';
|
|
6
|
+
import { type OpenedWindow } from '@openmrs/esm-extensions';
|
|
7
|
+
import { launchWorkspace2, useWorkspace2Store } from '../workspace2';
|
|
8
|
+
import { ActionMenuButton2 } from './action-menu-button2.component';
|
|
9
|
+
|
|
10
|
+
vi.mock('../workspace2', () => ({
|
|
11
|
+
launchWorkspace2: vi.fn(),
|
|
12
|
+
useWorkspace2Store: vi.fn(),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
vi.mock('@openmrs/esm-react-utils', async () => ({
|
|
16
|
+
...(await vi.importActual<object>('@openmrs/esm-react-utils')),
|
|
17
|
+
useLayoutType: vi.fn(),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
const mockUseLayoutType = vi.mocked(useLayoutType);
|
|
21
|
+
const mockUseWorkspace2Store = vi.mocked(useWorkspace2Store);
|
|
22
|
+
const mockLaunchWorkspace2 = vi.mocked(launchWorkspace2);
|
|
23
|
+
|
|
24
|
+
const mockHideWindow = vi.fn();
|
|
25
|
+
|
|
26
|
+
const openedWindows = [{ windowName: 'test-window', openedWorkspaces: [] }] as unknown as Array<OpenedWindow>;
|
|
27
|
+
|
|
28
|
+
function renderButton(props: Partial<React.ComponentProps<typeof ActionMenuButton2>> = {}) {
|
|
29
|
+
return render(
|
|
30
|
+
<ComponentContext.Provider value={{ extension: { extensionId: 'test-window' } } as any}>
|
|
31
|
+
<ActionMenuButton2
|
|
32
|
+
icon={() => <svg data-testid="icon" />}
|
|
33
|
+
label="Test button"
|
|
34
|
+
workspaceToLaunch={{ workspaceName: 'test-workspace' }}
|
|
35
|
+
{...props}
|
|
36
|
+
/>
|
|
37
|
+
</ComponentContext.Provider>,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('ActionMenuButton2 hidden and disabled', () => {
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
mockUseLayoutType.mockReturnValue('small-desktop');
|
|
44
|
+
mockUseWorkspace2Store.mockReturnValue({
|
|
45
|
+
openedWindows,
|
|
46
|
+
restoreWindow: vi.fn(),
|
|
47
|
+
hideWindow: mockHideWindow,
|
|
48
|
+
isMostRecentlyOpenedWindowHidden: false,
|
|
49
|
+
} as any);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('renders an enabled button by default', () => {
|
|
53
|
+
renderButton();
|
|
54
|
+
expect(screen.getByRole('button')).toBeEnabled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('renders nothing when hidden returns true, passing openedWindows', () => {
|
|
58
|
+
const hidden = vi.fn().mockReturnValue(true);
|
|
59
|
+
renderButton({ hidden });
|
|
60
|
+
expect(hidden).toHaveBeenCalledWith(openedWindows);
|
|
61
|
+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('renders the button when hidden returns false', () => {
|
|
65
|
+
renderButton({ hidden: () => false });
|
|
66
|
+
expect(screen.getByRole('button')).toBeInTheDocument();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('disables the button when disabled returns true, passing openedWindows', async () => {
|
|
70
|
+
const disabled = vi.fn().mockReturnValue(true);
|
|
71
|
+
renderButton({ disabled });
|
|
72
|
+
expect(disabled).toHaveBeenCalledWith(openedWindows);
|
|
73
|
+
const button = screen.getByRole('button');
|
|
74
|
+
expect(button).toBeDisabled();
|
|
75
|
+
await userEvent.click(button);
|
|
76
|
+
expect(mockLaunchWorkspace2).not.toHaveBeenCalled();
|
|
77
|
+
expect(mockHideWindow).not.toHaveBeenCalled();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('keeps the button enabled when disabled returns false', () => {
|
|
81
|
+
renderButton({ disabled: () => false });
|
|
82
|
+
expect(screen.getByRole('button')).toBeEnabled();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('supports hidden and disabled on tablet layout', () => {
|
|
86
|
+
mockUseLayoutType.mockReturnValue('tablet');
|
|
87
|
+
const { unmount } = renderButton({ disabled: () => true });
|
|
88
|
+
expect(screen.getByRole('button')).toBeDisabled();
|
|
89
|
+
unmount();
|
|
90
|
+
|
|
91
|
+
renderButton({ hidden: () => true });
|
|
92
|
+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
93
|
+
});
|
|
94
|
+
});
|