@openmrs/esm-styleguide 10.0.1-pre.5717 → 10.0.1-pre.5723

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.
@@ -1,3 +1,3 @@
1
- [0] Successfully compiled: 117 files, copied 171 files with swc (249.35ms)
1
+ [0] Successfully compiled: 117 files, copied 171 files with swc (176.65ms)
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 +1 @@
1
- {"version":3,"file":"active-workspace-window.component.d.ts","sourceRoot":"","sources":["../../src/workspaces2/active-workspace-window.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAM5E,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAGzE,UAAU,oBAAoB;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACvC,OAAO,EAAE,sBAAsB,CAAC;IAChC;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB;AAKD;;;GAGG;AACH,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA4DzD,CAAC;AAoRF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"active-workspace-window.component.d.ts","sourceRoot":"","sources":["../../src/workspaces2/active-workspace-window.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuD,MAAM,OAAO,CAAC;AAM5E,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAGzE,UAAU,oBAAoB;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACvC,OAAO,EAAE,sBAAsB,CAAC;IAChC;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;CACzB;AAKD;;;GAGG;AACH,QAAA,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA4DzD,CAAC;AAqRF,eAAe,qBAAqB,CAAC"}
@@ -9,7 +9,7 @@ import { isDesktop, useLayoutType, useStore } from "@openmrs/esm-react-utils";
9
9
  import { loadLifeCycles } from "@openmrs/esm-routes";
10
10
  import { getCoreTranslation } from "@openmrs/esm-translations";
11
11
  import { ArrowRightIcon, CloseIcon } from "../icons/index.js";
12
- import { closeWorkspaceGroup2, useWorkspace2Store } from "./workspace2.js";
12
+ import { closeWorkspaceGroup2, getOpenedWindowWidth, useWorkspace2Store } from "./workspace2.js";
13
13
  import styles from "./workspace2.module.scss";
14
14
  // module-level so the store subscription's snapshot getter stays stable across renders
15
15
  const selectRegisteredWorkspacesByName = (state)=>state.registeredWorkspacesByName;
@@ -171,12 +171,12 @@ const ActiveWorkspace = ({ lifeCycle, openedWorkspace, openedWindow, groupProps,
171
171
  * window system.
172
172
  */ const WorkspaceChrome = ({ openedWorkspace, openedWindow, isRootWorkspace, showActionMenu, closeWindow, children })=>{
173
173
  const layout = useLayoutType();
174
- const { openedGroup, openedWindows, registeredWindowsByName, registeredGroupsByName, isMostRecentlyOpenedWindowHidden, setWindowMaximized, hideWindow } = useWorkspace2Store();
174
+ const { openedGroup, openedWindows, registeredWindowsByName, registeredWorkspacesByName, registeredGroupsByName, isMostRecentlyOpenedWindowHidden, setWindowMaximized, hideWindow } = useWorkspace2Store();
175
175
  const windowName = openedWindow.windowName;
176
176
  const { maximized } = openedWindow;
177
177
  const title = openedWorkspace.title ?? '';
178
178
  const windowDef = registeredWindowsByName[windowName];
179
- const width = windowDef?.width ?? 'narrow';
179
+ const width = getOpenedWindowWidth(openedWindow, registeredWorkspacesByName, registeredWindowsByName);
180
180
  const icon = windowDef?.icon;
181
181
  const canMaximize = windowDef?.canMaximize;
182
182
  const canCloseGroup = openedGroup ? registeredGroupsByName[openedGroup.groupName]?.persistence === 'closable' : false;
@@ -36,15 +36,16 @@ export interface Workspace2DefinitionProps<WorkspaceProps extends object = objec
36
36
  windowName: string;
37
37
  isRootWorkspace: boolean;
38
38
  showActionMenu: boolean;
39
- /**
40
- * Records the title of this workspace, for display in the workspace window header.
41
- * @internal Called by `<Workspace2>`; use its `title` prop instead.
42
- */
39
+ }
40
+ /**
41
+ * The props the framework actually passes to a workspace: the public `Workspace2DefinitionProps` plus
42
+ * the setters `<Workspace2>` uses to report its `title` and `hasUnsavedChanges` to the workspace window.
43
+ * Not part of the public API.
44
+ */
45
+ export interface Workspace2InternalProps<WorkspaceProps extends object = object, WindowProps extends object = object, GroupProps extends object = object> extends Workspace2DefinitionProps<WorkspaceProps, WindowProps, GroupProps> {
46
+ /** Records the title of this workspace, for display in the workspace window header. */
43
47
  setWorkspaceTitle(title: string): void;
44
- /**
45
- * Records whether this workspace has unsaved changes.
46
- * @internal Called by `<Workspace2>`; use its `hasUnsavedChanges` prop instead.
47
- */
48
+ /** Records whether this workspace has unsaved changes. */
48
49
  setHasUnsavedChanges(hasUnsavedChanges: boolean): void;
49
50
  }
50
51
  export type Workspace2Definition<WorkspaceProps extends object, WindowProps extends object, GroupProps extends object> = React.FC<Workspace2DefinitionProps<WorkspaceProps, WindowProps, GroupProps>>;
@@ -1 +1 @@
1
- {"version":3,"file":"workspace2.component.d.ts","sourceRoot":"","sources":["../../src/workspaces2/workspace2.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGzD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB,CACxC,cAAc,SAAS,MAAM,GAAG,MAAM,EACtC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM;IAElC;;;;;;OAMG;IACH,oBAAoB,CAAC,KAAK,SAAS,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzG;;;;;;OAMG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvG,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IAExB;;;OAGG;IACH,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvC;;;OAGG;IACH,oBAAoB,CAAC,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,MAAM,oBAAoB,CAC9B,cAAc,SAAS,MAAM,EAC7B,WAAW,SAAS,MAAM,EAC1B,UAAU,SAAS,MAAM,IACvB,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAAC,cAAc,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;AAEjF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAiBhD,CAAC"}
1
+ {"version":3,"file":"workspace2.component.d.ts","sourceRoot":"","sources":["../../src/workspaces2/workspace2.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAa,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGzD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,yBAAyB,CACxC,cAAc,SAAS,MAAM,GAAG,MAAM,EACtC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM;IAElC;;;;;;OAMG;IACH,oBAAoB,CAAC,KAAK,SAAS,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzG;;;;;;OAMG;IACH,cAAc,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEvG,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,uBAAuB,CACtC,cAAc,SAAS,MAAM,GAAG,MAAM,EACtC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM,CAClC,SAAQ,yBAAyB,CAAC,cAAc,EAAE,WAAW,EAAE,UAAU,CAAC;IAC1E,uFAAuF;IACvF,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvC,0DAA0D;IAC1D,oBAAoB,CAAC,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,MAAM,oBAAoB,CAC9B,cAAc,SAAS,MAAM,EAC7B,WAAW,SAAS,MAAM,EAC1B,UAAU,SAAS,MAAM,IACvB,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAAC,cAAc,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;AAEjF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAiBhD,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { type OpenedWindow, type OpenedWorkspace, type WorkspaceStoreState2 } from '@openmrs/esm-extensions';
2
+ import { type WorkspaceDefinition2 } from '@openmrs/esm-globals';
2
3
  import { type Workspace2DefinitionProps } from './workspace2.component';
3
4
  /**
4
5
  * Attempts to launch the specified workspace group with the given group props. Note that only one workspace group
@@ -127,7 +128,7 @@ export declare const workspace2StoreActions: {
127
128
  registeredWindowsByName: Record<string, import("@openmrs/esm-globals").WorkspaceWindowDefinition2 & {
128
129
  moduleName: string;
129
130
  }>;
130
- registeredWorkspacesByName: Record<string, import("@openmrs/esm-globals").WorkspaceDefinition2 & {
131
+ registeredWorkspacesByName: Record<string, WorkspaceDefinition2 & {
131
132
  moduleName: string;
132
133
  }>;
133
134
  openedGroup: import("@openmrs/esm-extensions").OpenedGroup | null;
@@ -141,7 +142,7 @@ export declare const workspace2StoreActions: {
141
142
  registeredWindowsByName: Record<string, import("@openmrs/esm-globals").WorkspaceWindowDefinition2 & {
142
143
  moduleName: string;
143
144
  }>;
144
- registeredWorkspacesByName: Record<string, import("@openmrs/esm-globals").WorkspaceDefinition2 & {
145
+ registeredWorkspacesByName: Record<string, WorkspaceDefinition2 & {
145
146
  moduleName: string;
146
147
  }>;
147
148
  openedGroup: import("@openmrs/esm-extensions").OpenedGroup | null;
@@ -156,7 +157,7 @@ export declare const workspace2StoreActions: {
156
157
  registeredWindowsByName: Record<string, import("@openmrs/esm-globals").WorkspaceWindowDefinition2 & {
157
158
  moduleName: string;
158
159
  }>;
159
- registeredWorkspacesByName: Record<string, import("@openmrs/esm-globals").WorkspaceDefinition2 & {
160
+ registeredWorkspacesByName: Record<string, WorkspaceDefinition2 & {
160
161
  moduleName: string;
161
162
  }>;
162
163
  openedGroup: import("@openmrs/esm-extensions").OpenedGroup | null;
@@ -170,7 +171,7 @@ export declare const workspace2StoreActions: {
170
171
  registeredWindowsByName: Record<string, import("@openmrs/esm-globals").WorkspaceWindowDefinition2 & {
171
172
  moduleName: string;
172
173
  }>;
173
- registeredWorkspacesByName: Record<string, import("@openmrs/esm-globals").WorkspaceDefinition2 & {
174
+ registeredWorkspacesByName: Record<string, WorkspaceDefinition2 & {
174
175
  moduleName: string;
175
176
  }>;
176
177
  openedGroup: import("@openmrs/esm-extensions").OpenedGroup | null;
@@ -197,6 +198,12 @@ export declare const useWorkspace2Context: () => Workspace2DefinitionProps<objec
197
198
  * @returns a list of registered workspaces.
198
199
  */
199
200
  export declare const getRegisteredWorkspace2Names: () => string[];
201
+ /**
202
+ * Returns the width an opened window renders at: its leaf workspace's `width`, falling back to the
203
+ * window's `width`, then `'narrow'`. Every workspace in the window uses this width so that a wider
204
+ * workspace lower in the stack doesn't show behind a narrower one.
205
+ */
206
+ export declare function getOpenedWindowWidth(openedWindow: OpenedWindow, registeredWorkspacesByName: WorkspaceStoreState2['registeredWorkspacesByName'], registeredWindowsByName: WorkspaceStoreState2['registeredWindowsByName']): NonNullable<WorkspaceDefinition2['width']>;
200
207
  /**
201
208
  * Builds the window an `<ExportedWorkspace>` starts with: the workspace's real registered window
202
209
  * (so `launchChildWorkspace` keeps working), containing just the requested workspace.
@@ -1 +1 @@
1
- {"version":3,"file":"workspace2.d.ts","sourceRoot":"","sources":["../../src/workspaces2/workspace2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace2.d.ts","sourceRoot":"","sources":["../../src/workspaces2/workspace2.ts"],"names":[],"mappings":"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"}
@@ -606,6 +606,15 @@ export function useWorkspace2Store() {
606
606
  */ export const getRegisteredWorkspace2Names = ()=>{
607
607
  return Object.keys(workspace2Store.getState().registeredWorkspacesByName);
608
608
  };
609
+ /**
610
+ * Returns the width an opened window renders at: its leaf workspace's `width`, falling back to the
611
+ * window's `width`, then `'narrow'`. Every workspace in the window uses this width so that a wider
612
+ * workspace lower in the stack doesn't show behind a narrower one.
613
+ */ export function getOpenedWindowWidth(openedWindow, registeredWorkspacesByName, registeredWindowsByName) {
614
+ const leaf = openedWindow.openedWorkspaces[openedWindow.openedWorkspaces.length - 1];
615
+ const leafWidth = leaf ? registeredWorkspacesByName[leaf.workspaceName]?.width : undefined;
616
+ return leafWidth ?? registeredWindowsByName[openedWindow.windowName]?.width ?? 'narrow';
617
+ }
609
618
  function newOpenedWorkspace(workspaceName, workspaceProps) {
610
619
  return {
611
620
  workspaceName,
@@ -61,12 +61,9 @@ $extraWideWorkspaceWidth: 48.25rem;
61
61
  width: var(--workspaceWidth);
62
62
  border-inline-start: 1px solid $text-03;
63
63
  background-color: #fff;
64
- will-change: width;
65
- transition: width 0.5s ease-in-out;
66
64
 
67
65
  &.maximized {
68
66
  width: 100%;
69
- transition: none !important;
70
67
  }
71
68
  }
72
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-styleguide",
3
- "version": "10.0.1-pre.5717",
3
+ "version": "10.0.1-pre.5723",
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": "^10.0.1-pre.5717",
83
- "@openmrs/esm-config": "^10.0.1-pre.5717",
84
- "@openmrs/esm-emr-api": "^10.0.1-pre.5717",
85
- "@openmrs/esm-error-handling": "^10.0.1-pre.5717",
86
- "@openmrs/esm-extensions": "^10.0.1-pre.5717",
87
- "@openmrs/esm-globals": "^10.0.1-pre.5717",
88
- "@openmrs/esm-navigation": "^10.0.1-pre.5717",
89
- "@openmrs/esm-react-utils": "^10.0.1-pre.5717",
90
- "@openmrs/esm-routes": "^10.0.1-pre.5717",
91
- "@openmrs/esm-state": "^10.0.1-pre.5717",
92
- "@openmrs/esm-translations": "^10.0.1-pre.5717",
93
- "@openmrs/esm-utils": "^10.0.1-pre.5717",
82
+ "@openmrs/esm-api": "^10.0.1-pre.5723",
83
+ "@openmrs/esm-config": "^10.0.1-pre.5723",
84
+ "@openmrs/esm-emr-api": "^10.0.1-pre.5723",
85
+ "@openmrs/esm-error-handling": "^10.0.1-pre.5723",
86
+ "@openmrs/esm-extensions": "^10.0.1-pre.5723",
87
+ "@openmrs/esm-globals": "^10.0.1-pre.5723",
88
+ "@openmrs/esm-navigation": "^10.0.1-pre.5723",
89
+ "@openmrs/esm-react-utils": "^10.0.1-pre.5723",
90
+ "@openmrs/esm-routes": "^10.0.1-pre.5723",
91
+ "@openmrs/esm-state": "^10.0.1-pre.5723",
92
+ "@openmrs/esm-translations": "^10.0.1-pre.5723",
93
+ "@openmrs/esm-utils": "^10.0.1-pre.5723",
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": "10.0.1-pre.5717",
103
- "@openmrs/esm-config": "10.0.1-pre.5717",
104
- "@openmrs/esm-emr-api": "10.0.1-pre.5717",
105
- "@openmrs/esm-error-handling": "10.0.1-pre.5717",
106
- "@openmrs/esm-extensions": "10.0.1-pre.5717",
107
- "@openmrs/esm-globals": "10.0.1-pre.5717",
108
- "@openmrs/esm-navigation": "10.0.1-pre.5717",
109
- "@openmrs/esm-react-utils": "10.0.1-pre.5717",
110
- "@openmrs/esm-routes": "10.0.1-pre.5717",
111
- "@openmrs/esm-state": "10.0.1-pre.5717",
112
- "@openmrs/esm-translations": "10.0.1-pre.5717",
113
- "@openmrs/esm-utils": "10.0.1-pre.5717",
102
+ "@openmrs/esm-api": "10.0.1-pre.5723",
103
+ "@openmrs/esm-config": "10.0.1-pre.5723",
104
+ "@openmrs/esm-emr-api": "10.0.1-pre.5723",
105
+ "@openmrs/esm-error-handling": "10.0.1-pre.5723",
106
+ "@openmrs/esm-extensions": "10.0.1-pre.5723",
107
+ "@openmrs/esm-globals": "10.0.1-pre.5723",
108
+ "@openmrs/esm-navigation": "10.0.1-pre.5723",
109
+ "@openmrs/esm-react-utils": "10.0.1-pre.5723",
110
+ "@openmrs/esm-routes": "10.0.1-pre.5723",
111
+ "@openmrs/esm-state": "10.0.1-pre.5723",
112
+ "@openmrs/esm-translations": "10.0.1-pre.5723",
113
+ "@openmrs/esm-utils": "10.0.1-pre.5723",
114
114
  "@swc/cli": "0.8.1",
115
115
  "@swc/core": "1.15.21",
116
116
  "@types/geopattern": "^1.2.9",
@@ -15,8 +15,8 @@ import { isDesktop, useLayoutType, useStore } from '@openmrs/esm-react-utils';
15
15
  import { loadLifeCycles } from '@openmrs/esm-routes';
16
16
  import { getCoreTranslation } from '@openmrs/esm-translations';
17
17
  import { ArrowRightIcon, CloseIcon } from '../icons';
18
- import { closeWorkspaceGroup2, useWorkspace2Store } from './workspace2';
19
- import { type Workspace2DefinitionProps } from './workspace2.component';
18
+ import { closeWorkspaceGroup2, getOpenedWindowWidth, useWorkspace2Store } from './workspace2';
19
+ import { type Workspace2InternalProps } from './workspace2.component';
20
20
  import { type WorkspaceWindowActions } from './workspace-window-actions';
21
21
  import styles from './workspace2.module.scss';
22
22
 
@@ -127,7 +127,7 @@ const ActiveWorkspace: React.FC<ActiveWorkspaceProps> = ({
127
127
  isLeafWorkspace,
128
128
  showActionMenu,
129
129
  }) => {
130
- const props: Workspace2DefinitionProps = useMemo(
130
+ const props: Workspace2InternalProps = useMemo(
131
131
  () =>
132
132
  openedWorkspace && {
133
133
  closeWorkspace: async (options = {}) => {
@@ -262,6 +262,7 @@ const WorkspaceChrome: React.FC<WorkspaceChromeProps> = ({
262
262
  openedGroup,
263
263
  openedWindows,
264
264
  registeredWindowsByName,
265
+ registeredWorkspacesByName,
265
266
  registeredGroupsByName,
266
267
  isMostRecentlyOpenedWindowHidden,
267
268
  setWindowMaximized,
@@ -273,7 +274,7 @@ const WorkspaceChrome: React.FC<WorkspaceChromeProps> = ({
273
274
  const title = openedWorkspace.title ?? '';
274
275
 
275
276
  const windowDef = registeredWindowsByName[windowName];
276
- const width = windowDef?.width ?? 'narrow';
277
+ const width = getOpenedWindowWidth(openedWindow, registeredWorkspacesByName, registeredWindowsByName);
277
278
  const icon = windowDef?.icon;
278
279
  const canMaximize = windowDef?.canMaximize;
279
280
  const canCloseGroup = openedGroup ? registeredGroupsByName[openedGroup.groupName]?.persistence === 'closable' : false;
@@ -4,7 +4,8 @@ import { act, render, screen } from '@testing-library/react';
4
4
  import { workspace2Store, type OpenedWindow, type OpenedWorkspace } from '@openmrs/esm-extensions';
5
5
  import { loadLifeCycles } from '@openmrs/esm-routes';
6
6
  import ActiveWorkspaceWindow from './active-workspace-window.component';
7
- import { type Workspace2DefinitionProps } from './workspace2.component';
7
+ import styles from './workspace2.module.scss';
8
+ import { type Workspace2InternalProps } from './workspace2.component';
8
9
  import { type WorkspaceWindowActions } from './workspace-window-actions';
9
10
 
10
11
  vi.mock('@openmrs/esm-routes', () => ({
@@ -13,13 +14,13 @@ vi.mock('@openmrs/esm-routes', () => ({
13
14
 
14
15
  // Records the props each parcel was handed, keyed by workspace name, so tests can call them the way
15
16
  // the workspace component would.
16
- const { parcelProps } = vi.hoisted(() => ({ parcelProps: {} as Record<string, Workspace2DefinitionProps> }));
17
+ const { parcelProps } = vi.hoisted(() => ({ parcelProps: {} as Record<string, Workspace2InternalProps> }));
17
18
  vi.mock('single-spa-react/parcel', () => ({
18
19
  default: ({
19
20
  config,
20
21
  wrapClassName,
21
22
  ...props
22
- }: { config: { name: string }; wrapClassName?: string } & Workspace2DefinitionProps) => {
23
+ }: { config: { name: string }; wrapClassName?: string } & Workspace2InternalProps) => {
23
24
  parcelProps[props.workspaceName] = props;
24
25
  // Surface the wrapper class the real Parcel would apply, so tests can assert stacking/visibility.
25
26
  return (
@@ -106,6 +107,48 @@ describe('ActiveWorkspaceWindow', () => {
106
107
  }
107
108
  });
108
109
 
110
+ it('applies the leaf width to loading and mounted chrome, and restores it when the child closes', async () => {
111
+ const state = workspace2Store.getState();
112
+ workspace2Store.setState({
113
+ registeredWorkspacesByName: {
114
+ ...state.registeredWorkspacesByName,
115
+ 'form-workspace': { ...state.registeredWorkspacesByName['form-workspace'], width: 'extra-wide' },
116
+ 'admit-workspace': { ...state.registeredWorkspacesByName['admit-workspace'], width: 'narrow' },
117
+ },
118
+ });
119
+ const parent = makeOpenedWorkspace('form-workspace', 'parent');
120
+ const child = makeOpenedWorkspace('admit-workspace', 'child');
121
+ const actions = makeActions();
122
+ let resolveChild: (config: { name: string }) => void;
123
+ mockLoadLifeCycles.mockImplementation((_, component) =>
124
+ component === 'form'
125
+ ? Promise.resolve({ name: 'form' } as never)
126
+ : (new Promise((resolve) => {
127
+ resolveChild = resolve as never;
128
+ }) as never),
129
+ );
130
+ const { container, rerender } = render(renderWindow(makeOpenedWindow([parent]), actions, true));
131
+ await flushLifeCycles();
132
+ // Width classes live on the chrome containers, including the loading state with no title bar.
133
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
134
+ expect(container.querySelectorAll(`.${styles.extraWideWorkspace}`)).toHaveLength(1);
135
+ rerender(renderWindow(makeOpenedWindow([parent, child]), actions, true));
136
+ // Width classes live on the chrome containers, including the loading state with no title bar.
137
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
138
+ expect(container.querySelectorAll(`.${styles.narrowWorkspace}`)).toHaveLength(2);
139
+ await act(async () => {
140
+ resolveChild({ name: 'admit' });
141
+ });
142
+ expect(screen.getAllByTestId('parcel')).toHaveLength(2);
143
+ // Width classes live on the chrome containers, including the loading state with no title bar.
144
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
145
+ expect(container.querySelectorAll(`.${styles.narrowWorkspace}`)).toHaveLength(2);
146
+ rerender(renderWindow(makeOpenedWindow([parent]), actions, true));
147
+ // Width classes live on the chrome containers, including the loading state with no title bar.
148
+ // eslint-disable-next-line testing-library/no-container, testing-library/no-node-access
149
+ expect(container.querySelectorAll(`.${styles.extraWideWorkspace}`)).toHaveLength(1);
150
+ });
151
+
109
152
  it('does not render a replaced workspace with the previous workspace lifecycle at the same stack position', async () => {
110
153
  // The form lifecycle resolves immediately. The admit lifecycle resolves only
111
154
  // when we release it, keeping the reload from the stack change pending, which
@@ -5,7 +5,7 @@ import { workspace2Store } from '@openmrs/esm-extensions';
5
5
  import { loadLifeCycles } from '@openmrs/esm-routes';
6
6
  import { showModal } from '../modals';
7
7
  import { ExportedWorkspace, type ExportedWorkspaceWindowInfo } from './exported-workspace.component';
8
- import { type Workspace2DefinitionProps } from './workspace2.component';
8
+ import { type Workspace2InternalProps } from './workspace2.component';
9
9
 
10
10
  vi.mock('@openmrs/esm-routes', () => ({
11
11
  loadLifeCycles: vi.fn(),
@@ -18,9 +18,9 @@ vi.mock('../modals', () => ({
18
18
  // The parcel is where the workspace component (and its <Workspace2>) would mount. We stub it out,
19
19
  // surface the workspace name it was handed, and record its props (keyed by workspace name) so tests
20
20
  // can call them the way the workspace component would.
21
- const { parcelProps } = vi.hoisted(() => ({ parcelProps: {} as Record<string, Workspace2DefinitionProps> }));
21
+ const { parcelProps } = vi.hoisted(() => ({ parcelProps: {} as Record<string, Workspace2InternalProps> }));
22
22
  vi.mock('single-spa-react/parcel', () => ({
23
- default: (props: Workspace2DefinitionProps) => {
23
+ default: (props: Workspace2InternalProps) => {
24
24
  parcelProps[props.workspaceName] = props;
25
25
  return <div data-testid="parcel">{props.workspaceName}</div>;
26
26
  },
@@ -42,17 +42,22 @@ export interface Workspace2DefinitionProps<
42
42
  windowName: string;
43
43
  isRootWorkspace: boolean;
44
44
  showActionMenu: boolean;
45
+ }
45
46
 
46
- /**
47
- * Records the title of this workspace, for display in the workspace window header.
48
- * @internal Called by `<Workspace2>`; use its `title` prop instead.
49
- */
47
+ /**
48
+ * The props the framework actually passes to a workspace: the public `Workspace2DefinitionProps` plus
49
+ * the setters `<Workspace2>` uses to report its `title` and `hasUnsavedChanges` to the workspace window.
50
+ * Not part of the public API.
51
+ */
52
+ export interface Workspace2InternalProps<
53
+ WorkspaceProps extends object = object,
54
+ WindowProps extends object = object,
55
+ GroupProps extends object = object,
56
+ > extends Workspace2DefinitionProps<WorkspaceProps, WindowProps, GroupProps> {
57
+ /** Records the title of this workspace, for display in the workspace window header. */
50
58
  setWorkspaceTitle(title: string): void;
51
59
 
52
- /**
53
- * Records whether this workspace has unsaved changes.
54
- * @internal Called by `<Workspace2>`; use its `hasUnsavedChanges` prop instead.
55
- */
60
+ /** Records whether this workspace has unsaved changes. */
56
61
  setHasUnsavedChanges(hasUnsavedChanges: boolean): void;
57
62
  }
58
63
 
@@ -71,7 +76,7 @@ export type Workspace2Definition<
71
76
  export const Workspace2: React.FC<Workspace2Props> = ({ title, children, hasUnsavedChanges = false }) => {
72
77
  // These are bound to this workspace instance, in whichever store holds it (the global store, or an
73
78
  // `<ExportedWorkspace>`'s local store). They skip writes that change nothing.
74
- const { setHasUnsavedChanges, setWorkspaceTitle } = useWorkspace2Context();
79
+ const { setHasUnsavedChanges, setWorkspaceTitle } = useWorkspace2Context() as Workspace2InternalProps;
75
80
 
76
81
  useEffect(() => {
77
82
  setHasUnsavedChanges(hasUnsavedChanges ?? false);
@@ -61,12 +61,9 @@ $extraWideWorkspaceWidth: 48.25rem;
61
61
  width: var(--workspaceWidth);
62
62
  border-inline-start: 1px solid $text-03;
63
63
  background-color: #fff;
64
- will-change: width;
65
- transition: width 0.5s ease-in-out;
66
64
 
67
65
  &.maximized {
68
66
  width: 100%;
69
- transition: none !important;
70
67
  }
71
68
  }
72
69
 
@@ -9,6 +9,7 @@ import {
9
9
  closeWorkspaceInWindow,
10
10
  openChildWorkspaceInWindow,
11
11
  updateOpenedWorkspaceInWindow,
12
+ getOpenedWindowWidth,
12
13
  workspace2StoreActions,
13
14
  } from './workspace2';
14
15
 
@@ -268,3 +269,70 @@ describe('updateOpenedWorkspaceInWindow', () => {
268
269
  expect(updateOpenedWorkspaceInWindow(window, 'uuid-parent-workspace', { hasUnsavedChanges: false })).toBe(window);
269
270
  });
270
271
  });
272
+
273
+ describe('getOpenedWindowWidth', () => {
274
+ const registeredWindowsByName = {
275
+ 'test-window': { name: 'test-window', group: 'test-group', width: 'wider' as const, moduleName: 'test' },
276
+ 'plain-window': { name: 'plain-window', group: 'test-group', moduleName: 'test' },
277
+ };
278
+ const registeredWorkspacesByName = {
279
+ 'inherits-width': { name: 'inherits-width', component: 'a', window: 'test-window', moduleName: 'test' },
280
+ 'extra-wide': {
281
+ name: 'extra-wide',
282
+ component: 'b',
283
+ window: 'test-window',
284
+ width: 'extra-wide' as const,
285
+ moduleName: 'test',
286
+ },
287
+ 'narrow-on-plain': { name: 'narrow-on-plain', component: 'c', window: 'plain-window', moduleName: 'test' },
288
+ };
289
+
290
+ function makeWindow(windowName: string, workspaceNames: Array<string>) {
291
+ return {
292
+ windowName,
293
+ openedWorkspaces: workspaceNames.map((n) => makeOpenedWorkspace(n)),
294
+ props: null,
295
+ maximized: false,
296
+ };
297
+ }
298
+
299
+ it("uses the window's width when the leaf workspace declares none", () => {
300
+ expect(
301
+ getOpenedWindowWidth(
302
+ makeWindow('test-window', ['inherits-width']),
303
+ registeredWorkspacesByName,
304
+ registeredWindowsByName,
305
+ ),
306
+ ).toBe('wider');
307
+ });
308
+
309
+ it("uses the leaf workspace's width over the window's width", () => {
310
+ expect(
311
+ getOpenedWindowWidth(
312
+ makeWindow('test-window', ['inherits-width', 'extra-wide']),
313
+ registeredWorkspacesByName,
314
+ registeredWindowsByName,
315
+ ),
316
+ ).toBe('extra-wide');
317
+ });
318
+
319
+ it('ignores the width of non-leaf workspaces', () => {
320
+ expect(
321
+ getOpenedWindowWidth(
322
+ makeWindow('test-window', ['extra-wide', 'inherits-width']),
323
+ registeredWorkspacesByName,
324
+ registeredWindowsByName,
325
+ ),
326
+ ).toBe('wider');
327
+ });
328
+
329
+ it("defaults to 'narrow' when neither the workspace nor the window declares a width", () => {
330
+ expect(
331
+ getOpenedWindowWidth(
332
+ makeWindow('plain-window', ['narrow-on-plain']),
333
+ registeredWorkspacesByName,
334
+ registeredWindowsByName,
335
+ ),
336
+ ).toBe('narrow');
337
+ });
338
+ });
@@ -10,6 +10,7 @@ import {
10
10
  workspace2Store,
11
11
  type WorkspaceStoreState2,
12
12
  } from '@openmrs/esm-extensions';
13
+ import { type WorkspaceDefinition2 } from '@openmrs/esm-globals';
13
14
  import { useStoreWithActions, type Actions } from '@openmrs/esm-react-utils';
14
15
  import { shallowEqual } from '@openmrs/esm-utils';
15
16
  import { showModal } from '../modals';
@@ -683,6 +684,21 @@ export const getRegisteredWorkspace2Names = () => {
683
684
  return Object.keys(workspace2Store.getState().registeredWorkspacesByName);
684
685
  };
685
686
 
687
+ /**
688
+ * Returns the width an opened window renders at: its leaf workspace's `width`, falling back to the
689
+ * window's `width`, then `'narrow'`. Every workspace in the window uses this width so that a wider
690
+ * workspace lower in the stack doesn't show behind a narrower one.
691
+ */
692
+ export function getOpenedWindowWidth(
693
+ openedWindow: OpenedWindow,
694
+ registeredWorkspacesByName: WorkspaceStoreState2['registeredWorkspacesByName'],
695
+ registeredWindowsByName: WorkspaceStoreState2['registeredWindowsByName'],
696
+ ): NonNullable<WorkspaceDefinition2['width']> {
697
+ const leaf = openedWindow.openedWorkspaces[openedWindow.openedWorkspaces.length - 1];
698
+ const leafWidth = leaf ? registeredWorkspacesByName[leaf.workspaceName]?.width : undefined;
699
+ return leafWidth ?? registeredWindowsByName[openedWindow.windowName]?.width ?? 'narrow';
700
+ }
701
+
686
702
  function newOpenedWorkspace(workspaceName: string, workspaceProps: Record<string, any> | null): OpenedWorkspace {
687
703
  return {
688
704
  workspaceName,