@adaptabletools/adaptable 22.0.0-canary.7 → 22.0.0-canary.8

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.
Files changed (62) hide show
  1. package/index.css +63 -71
  2. package/index.css.map +1 -1
  3. package/package.json +1 -1
  4. package/src/AdaptableInterfaces/IAdaptable.d.ts +6 -6
  5. package/src/AdaptableOptions/ContainerOptions.d.ts +55 -15
  6. package/src/AdaptableState/AdaptableState.d.ts +2 -0
  7. package/src/AdaptableState/Common/AdaptableColumnContext.d.ts +9 -0
  8. package/src/AdaptableState/Common/AdaptableRowContext.d.ts +11 -0
  9. package/src/AdaptableState/Common/AdaptableRowContext.js +1 -0
  10. package/src/AdaptableState/Common/DataUpdateConfig.d.ts +7 -0
  11. package/src/AdaptableState/Common/TransposeConfig.d.ts +11 -9
  12. package/src/AdaptableState/InitialState.d.ts +9 -0
  13. package/src/AdaptableState/LayoutState.d.ts +1 -2
  14. package/src/AdaptableState/UserInterfaceState.d.ts +14 -0
  15. package/src/AdaptableState/UserInterfaceState.js +1 -0
  16. package/src/Api/GridApi.d.ts +5 -9
  17. package/src/Api/Implementation/AlertApiImpl.js +2 -6
  18. package/src/Api/Implementation/GridApiImpl.d.ts +2 -6
  19. package/src/Api/Implementation/GridApiImpl.js +9 -9
  20. package/src/Api/Implementation/LayoutApiImpl.d.ts +1 -0
  21. package/src/Api/Implementation/LayoutApiImpl.js +3 -0
  22. package/src/Api/Implementation/SystemStatusApiImpl.js +2 -5
  23. package/src/Api/Implementation/UserInterfaceApiImpl.d.ts +5 -0
  24. package/src/Api/Implementation/UserInterfaceApiImpl.js +13 -0
  25. package/src/Api/LayoutApi.d.ts +6 -0
  26. package/src/Api/UserInterfaceApi.d.ts +17 -0
  27. package/src/Redux/ActionsReducers/UserInterfaceRedux.d.ts +11 -0
  28. package/src/Redux/ActionsReducers/UserInterfaceRedux.js +21 -0
  29. package/src/Redux/Store/AdaptableStore.js +27 -0
  30. package/src/Utilities/resolveContainerElement.d.ts +23 -0
  31. package/src/Utilities/resolveContainerElement.js +44 -0
  32. package/src/View/Components/ColumnFilter/components/ColumnFilterInput.js +1 -1
  33. package/src/View/Components/Popups/AdaptablePopup/AdaptablePopup.js +2 -1
  34. package/src/View/Components/Popups/AdaptablePopup/AdaptablePopupBody.js +1 -1
  35. package/src/View/Components/Popups/AdaptablePopup/AdaptablePopupDialog.d.ts +1 -1
  36. package/src/View/Components/Popups/AdaptablePopup/AdaptablePopupDialog.js +1 -8
  37. package/src/View/Components/Popups/WindowPopups/WindowPopups.js +36 -1
  38. package/src/View/Components/WizardSummaryPage.js +1 -1
  39. package/src/View/Dashboard/CustomToolbar.js +1 -1
  40. package/src/View/DataChangeHistory/DataChangeHistoryViewPanel.js +1 -1
  41. package/src/View/Layout/TransposedPopup.js +144 -138
  42. package/src/View/Schedule/Wizard/ScheduleSettingsWizard/ScheduleSettingsReminder.js +1 -1
  43. package/src/View/UIHelper.d.ts +2 -1
  44. package/src/View/UIHelper.js +8 -14
  45. package/src/agGrid/Adaptable.js +11 -11
  46. package/src/agGrid/AdaptableAgGrid.d.ts +12 -8
  47. package/src/agGrid/AdaptableAgGrid.js +112 -31
  48. package/src/agGrid/AgGridFloatingFilterAdapter.js +1 -1
  49. package/src/agGrid/AgGridMenuAdapter.js +9 -1
  50. package/src/components/CheckBox/index.js +1 -1
  51. package/src/components/Dropdown/Arrows.js +1 -1
  52. package/src/components/ExpressionEditor/DataTableEditor.js +3 -3
  53. package/src/components/FormLayout/index.js +1 -1
  54. package/src/components/Select/Select.js +1 -1
  55. package/src/components/Tree/TreeDropdown/index.js +1 -1
  56. package/src/env.js +2 -2
  57. package/src/metamodel/adaptable.metamodel.d.ts +62 -0
  58. package/src/metamodel/adaptable.metamodel.js +1 -1
  59. package/src/types.d.ts +5 -2
  60. package/themes/dark.css +30 -29
  61. package/themes/light.css +4 -2
  62. package/tsconfig.esm.tsbuildinfo +1 -1
@@ -0,0 +1,14 @@
1
+ import { BaseState } from './BaseState';
2
+ /**
3
+ * Adaptable State Section for the User Interface
4
+ *
5
+ * Controls the visibility and behaviour of AdapTable UI elements
6
+ */
7
+ export interface UserInterfaceState extends BaseState {
8
+ /**
9
+ * Whether to hide all AdapTable UI elements (Dashboard, Tool Panel, Status Bar, Column and Context Menus etc.)
10
+ *
11
+ * @defaultValue false
12
+ */
13
+ HideAdaptableUI?: boolean;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -2,7 +2,7 @@ import { SelectedCellInfo } from '../AdaptableState/Selection/SelectedCellInfo';
2
2
  import { SelectedRowInfo } from '../AdaptableState/Selection/SelectedRowInfo';
3
3
  import { ColumnSort } from '../AdaptableState/Common/ColumnSort';
4
4
  import { CellUpdateRequest, GridCell } from '../AdaptableState/Selection/GridCell';
5
- import { DataUpdateConfig } from '../AdaptableState/Common/DataUpdateConfig';
5
+ import { DataRowConfig, DataUpdateConfig } from '../AdaptableState/Common/DataUpdateConfig';
6
6
  import { CellDataChangedInfo } from '../AdaptableState/Common/CellDataChangedInfo';
7
7
  import { CellHighlightInfo } from '../AdaptableState/Common/CellHighlightInfo';
8
8
  import { RowHighlightInfo } from '../AdaptableState/Common/RowHighlightInfo';
@@ -71,15 +71,11 @@ export interface GridApi {
71
71
  */
72
72
  deleteGridData(dataRows: any[], config?: DataUpdateConfig): Promise<IRowNode[]>;
73
73
  /**
74
- * Applies a data transaction (add, update, remove) to AdapTable (and AG Grid)
75
- * @param dataRows - Rows to add, update or remove (via transaction)
76
- * @param config - batch option and callback function to run post transaction
74
+ * Adds, Updates or Deletes rows in AdapTable (and AG Grid) in single transaction
75
+ * @param dataRowConfig - Rows to add, update or remove
76
+ * @param dataUpdateConfig - batch option and callback function to run post transaction
77
77
  */
78
- manageGridData(dataRows: {
79
- add?: any[];
80
- update?: any[];
81
- delete?: any[];
82
- }, config?: DataUpdateConfig): Promise<{
78
+ manageGridData(dataRowConfig: DataRowConfig, dataUpdateConfig?: DataUpdateConfig): Promise<{
83
79
  addedRows: IRowNode[];
84
80
  updatedRows: IRowNode[];
85
81
  removedRows: IRowNode[];
@@ -7,6 +7,7 @@ import ObjectFactory from '../../Utilities/ObjectFactory';
7
7
  import { isAdaptableCellChangedAlert, isAdaptableRowChangedAlert, } from '../../AdaptableState/Common/AdaptableAlert';
8
8
  import StringExtensions from '../../Utilities/Extensions/StringExtensions';
9
9
  import { AlertInternalApi } from '../Internal/AlertInternalApi';
10
+ import { resolveContainerElement } from '../../Utilities/resolveContainerElement';
10
11
  export class AlertApiImpl extends ApiBase {
11
12
  internalApi;
12
13
  constructor(_adaptable) {
@@ -62,12 +63,7 @@ export class AlertApiImpl extends ApiBase {
62
63
  }
63
64
  // Show Alert in a Div (if one has been set)
64
65
  if (alertProperties.ShowInDiv) {
65
- let alertDiv;
66
- let optionsDiv = this.getContainerOptions().alertContainer;
67
- if (optionsDiv) {
68
- alertDiv =
69
- typeof optionsDiv === 'string' ? document.getElementById(optionsDiv) : optionsDiv;
70
- }
66
+ const alertDiv = resolveContainerElement(this.getContainerOptions().alertContainer, this.getAdaptableInternalApi().buildBaseContext());
71
67
  if (alertDiv) {
72
68
  let alertString = alertToShow.header + ': ' + alertToShow.message;
73
69
  alertDiv.innerHTML = alertString;
@@ -4,7 +4,7 @@ import { SelectedCellInfo } from '../../AdaptableState/Selection/SelectedCellInf
4
4
  import { SelectedRowInfo } from '../../AdaptableState/Selection/SelectedRowInfo';
5
5
  import { CellUpdateRequest, GridCell } from '../../AdaptableState/Selection/GridCell';
6
6
  import { ColumnSort } from '../../AdaptableState/Common/ColumnSort';
7
- import { DataUpdateConfig } from '../../AdaptableState/Common/DataUpdateConfig';
7
+ import { DataRowConfig, DataUpdateConfig } from '../../AdaptableState/Common/DataUpdateConfig';
8
8
  import { CellHighlightInfo } from '../../AdaptableState/Common/CellHighlightInfo';
9
9
  import { RowHighlightInfo } from '../../AdaptableState/Common/RowHighlightInfo';
10
10
  import { ColDef, ColGroupDef, Column, ColumnState, IRowNode, RowModelType } from 'ag-grid-enterprise';
@@ -35,11 +35,7 @@ export declare class GridApiImpl extends ApiBase implements GridApi {
35
35
  addGridData(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<IRowNode[]>;
36
36
  undoCellEdit(cellDataChangedInfo: CellDataChangedInfo): boolean;
37
37
  deleteGridData(dataRows: any[], dataUpdateConfig?: DataUpdateConfig): Promise<IRowNode[]>;
38
- manageGridData(dataRows: {
39
- add?: any[];
40
- update?: any[];
41
- delete?: any[];
42
- }, config?: DataUpdateConfig): Promise<{
38
+ manageGridData(dataRowConfig: DataRowConfig, dataUpdateConfig?: DataUpdateConfig): Promise<{
43
39
  addedRows: IRowNode[];
44
40
  updatedRows: IRowNode[];
45
41
  removedRows: IRowNode[];
@@ -95,18 +95,18 @@ export class GridApiImpl extends ApiBase {
95
95
  }
96
96
  return [];
97
97
  }
98
- async manageGridData(dataRows, config) {
99
- const transactionResult = await this._adaptable.manageGridRows(dataRows, config);
98
+ async manageGridData(dataRowConfig, dataUpdateConfig) {
99
+ const transactionResult = await this._adaptable.manageGridRows(dataRowConfig, dataUpdateConfig);
100
100
  if (Array.isArray(transactionResult.removedRows) && transactionResult.removedRows.length) {
101
- const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows.delete, transactionResult.removedRows, 'Delete');
101
+ const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRowConfig.dataRows.delete, transactionResult.removedRows, 'Delete');
102
102
  this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
103
103
  }
104
104
  if (Array.isArray(transactionResult.updatedRows) && transactionResult.updatedRows.length) {
105
- const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows.update, transactionResult.updatedRows, 'Update');
105
+ const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRowConfig.dataRows.update, transactionResult.updatedRows, 'Update');
106
106
  this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
107
107
  }
108
108
  if (Array.isArray(transactionResult.addedRows) && transactionResult.addedRows.length) {
109
- const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRows.add, transactionResult.addedRows, 'Add');
109
+ const rowDataChangedInfo = this.getAdaptableInternalApi().buildRowDataChangedInfo(dataRowConfig.dataRows.add, transactionResult.addedRows, 'Add');
110
110
  this.getAdaptableInternalApi().getDataService().CreateRowDataChangedEvent(rowDataChangedInfo);
111
111
  }
112
112
  return transactionResult;
@@ -607,9 +607,9 @@ export class GridApiImpl extends ApiBase {
607
607
  showTransposedView(transposeConfig = {}) {
608
608
  const transposedColumnId = transposeConfig.transposedColumnId ?? this.getOptionsApi().getPrimaryKey();
609
609
  const hideTransposedColumn = transposeConfig.hideTransposedColumn ?? true;
610
- const visibleColumns = transposeConfig.visibleColumns ?? false;
611
- const visibleRows = transposeConfig.visibleRows ?? false;
612
610
  const autosize = transposeConfig.autosize ?? true;
611
+ const columnsToTranspose = transposeConfig.columnsToTranspose;
612
+ const rowsToTranspose = transposeConfig.rowsToTranspose;
613
613
  this.getAdaptableInternalApi().showPopupWindow({
614
614
  id: WINDOW_SHOW_TRANSPOSED_VIEW,
615
615
  factoryId: WINDOW_SHOW_TRANSPOSED_VIEW,
@@ -618,9 +618,9 @@ export class GridApiImpl extends ApiBase {
618
618
  popupProps: {
619
619
  transposedColumnId,
620
620
  hideTransposedColumn,
621
- visibleColumns,
622
- visibleRows,
623
621
  autosize,
622
+ columnsToTranspose,
623
+ rowsToTranspose,
624
624
  },
625
625
  });
626
626
  }
@@ -24,6 +24,7 @@ export declare class LayoutApiImpl extends ApiBase implements LayoutApi {
24
24
  getCurrentLayoutColumnSort(columnId: string): ColumnSort['SortOrder'] | null;
25
25
  getCurrentLayoutName(): string;
26
26
  getLayoutByName(layoutName: string): Layout | null;
27
+ setExtendedLayout(extendedLayout: ExtendedLayout): void;
27
28
  createOrUpdateExtendedLayout(extendedLayoutInfo: ExtendedLayout): void;
28
29
  getExtendedLayoutByName(layoutName: string): ExtendedLayout | undefined;
29
30
  cloneExtendedLayout(extendedLayoutToClone: ExtendedLayout, layoutName: string): ExtendedLayout | false;
@@ -90,6 +90,9 @@ export class LayoutApiImpl extends ApiBase {
90
90
  }
91
91
  }
92
92
  }
93
+ setExtendedLayout(extendedLayout) {
94
+ this.setLayout(extendedLayout.Layout.Name);
95
+ }
93
96
  createOrUpdateExtendedLayout(extendedLayoutInfo) {
94
97
  const config = {
95
98
  includeLayoutNotExtendedObjects: true,
@@ -7,6 +7,7 @@ import { createElement } from 'react';
7
7
  import UIHelper from '../../View/UIHelper';
8
8
  import StringExtensions from '../../Utilities/Extensions/StringExtensions';
9
9
  import { SystemStatusInternalApi } from '../Internal/SystemStatusInternalApi';
10
+ import { resolveContainerElement } from '../../Utilities/resolveContainerElement';
10
11
  export class SystemStatusApiImpl extends ApiBase {
11
12
  systemStatusDiv;
12
13
  internalApi;
@@ -48,11 +49,7 @@ export class SystemStatusApiImpl extends ApiBase {
48
49
  }
49
50
  displayMessageInDiv(statusMessage, statusFurtherInformation, messageType) {
50
51
  if (!this.systemStatusDiv) {
51
- let optionsDiv = this.getContainerOptions().systemStatusContainer;
52
- if (optionsDiv) {
53
- this.systemStatusDiv =
54
- typeof optionsDiv === 'string' ? document.getElementById(optionsDiv) : optionsDiv;
55
- }
52
+ this.systemStatusDiv = resolveContainerElement(this.getContainerOptions().systemStatusContainer, this.getAdaptableInternalApi().buildBaseContext());
56
53
  }
57
54
  if (this.systemStatusDiv) {
58
55
  if (StringExtensions.IsNotNullOrEmpty(statusFurtherInformation)) {
@@ -6,6 +6,7 @@ import { UserInterfaceInternalApi } from '../Internal/UserInterfaceInternalApi';
6
6
  import { UserInterfaceApi } from '../UserInterfaceApi';
7
7
  import { ProgressIndicatorConfig } from '../../AdaptableState/Common/ProgressIndicatorConfig';
8
8
  import { ApiBase } from './ApiBase';
9
+ import { UserInterfaceState } from '../../AdaptableState/UserInterfaceState';
9
10
  export declare class UserInterfaceApiImpl extends ApiBase implements UserInterfaceApi {
10
11
  internalApi: UserInterfaceInternalApi;
11
12
  private showProgressIndicatorTimeout;
@@ -26,4 +27,8 @@ export declare class UserInterfaceApiImpl extends ApiBase implements UserInterfa
26
27
  close: () => void;
27
28
  };
28
29
  closeCustomWindowPopup(windowId: string): void;
30
+ getUserInterfaceState(): UserInterfaceState;
31
+ isAdaptableUIVisible(): boolean;
32
+ hideAdaptableUI(): void;
33
+ showAdaptableUI(): void;
29
34
  }
@@ -4,6 +4,7 @@ import { CUSTOM_WINDOW_FACTORY_ID } from '../../View/Components/Popups/WindowPop
4
4
  import { UserInterfaceInternalApi } from '../Internal/UserInterfaceInternalApi';
5
5
  import { ApiBase } from './ApiBase';
6
6
  import { ProgressIndicatorHide, ProgressIndicatorShow, } from '../../Redux/ActionsReducers/PopupRedux';
7
+ import * as UserInterfaceRedux from '../../Redux/ActionsReducers/UserInterfaceRedux';
7
8
  export class UserInterfaceApiImpl extends ApiBase {
8
9
  internalApi;
9
10
  showProgressIndicatorTimeout = null;
@@ -128,4 +129,16 @@ export class UserInterfaceApiImpl extends ApiBase {
128
129
  closeCustomWindowPopup(windowId) {
129
130
  this.dispatchAction(PopupRedux.PopupHideWindow(windowId));
130
131
  }
132
+ getUserInterfaceState() {
133
+ return this.getAdaptableState().UserInterface;
134
+ }
135
+ isAdaptableUIVisible() {
136
+ return !(this.getUserInterfaceState().HideAdaptableUI ?? false);
137
+ }
138
+ hideAdaptableUI() {
139
+ this.dispatchAction(UserInterfaceRedux.UserInterfaceSetHideAdaptableUI(true));
140
+ }
141
+ showAdaptableUI() {
142
+ this.dispatchAction(UserInterfaceRedux.UserInterfaceSetHideAdaptableUI(false));
143
+ }
131
144
  }
@@ -57,6 +57,12 @@ export interface LayoutApi {
57
57
  */
58
58
  getLayoutByName(layoutName: string): Layout | null;
59
59
  /**
60
+ * Sets (i.e. selects) the Extended Layout
61
+ * @param extendedLayout Extended Layout to set
62
+ */
63
+ setExtendedLayout(extendedLayout: ExtendedLayout): void;
64
+ /**
65
+ *
60
66
  * Retrieves Layout with the given name
61
67
  * @param layoutName Layout to retrieve
62
68
  * @returns layout
@@ -3,6 +3,7 @@ import { AdaptableObject, AdaptableObjectTag } from '../AdaptableState/Common/Ad
3
3
  import { AdaptableModule, CustomIcon } from '../types';
4
4
  import { CustomWindowConfig } from '../AdaptableState/Common/CustomWindowConfig';
5
5
  import { ProgressIndicatorConfig } from '../AdaptableState/Common/ProgressIndicatorConfig';
6
+ import { UserInterfaceState } from '../AdaptableState/UserInterfaceState';
6
7
  /**
7
8
  * Functions relating to User Interface section of Adaptable State
8
9
  */
@@ -78,4 +79,20 @@ export interface UserInterfaceApi {
78
79
  * @param windowId window popup id
79
80
  */
80
81
  closeCustomWindowPopup(windowId: string): void;
82
+ /**
83
+ * Retrieves the current User Interface State
84
+ */
85
+ getUserInterfaceState(): UserInterfaceState;
86
+ /**
87
+ * Returns whether the AdapTable UI is currently visible
88
+ */
89
+ isAdaptableUIVisible(): boolean;
90
+ /**
91
+ * Hides all AdapTable UI elements (Dashboard, Tool Panel, Status Bar, Column and Context Menus etc.)
92
+ */
93
+ hideAdaptableUI(): void;
94
+ /**
95
+ * Shows all AdapTable UI elements (Dashboard, Tool Panel, Status Bar, Column and Context Menus etc.)
96
+ */
97
+ showAdaptableUI(): void;
81
98
  }
@@ -0,0 +1,11 @@
1
+ import * as Redux from 'redux';
2
+ import { UserInterfaceState } from '../../AdaptableState/UserInterfaceState';
3
+ /**
4
+ * @ReduxAction Sets whether all AdapTable UI elements are hidden
5
+ */
6
+ export declare const USER_INTERFACE_SET_HIDE_ADAPTABLE_UI = "USER_INTERFACE_SET_HIDE_ADAPTABLE_UI";
7
+ export interface UserInterfaceSetHideAdaptableUIAction extends Redux.Action {
8
+ hideAdaptableUI: boolean;
9
+ }
10
+ export declare const UserInterfaceSetHideAdaptableUI: (hideAdaptableUI: boolean) => UserInterfaceSetHideAdaptableUIAction;
11
+ export declare const UserInterfaceReducer: Redux.Reducer<UserInterfaceState>;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @ReduxAction Sets whether all AdapTable UI elements are hidden
3
+ */
4
+ export const USER_INTERFACE_SET_HIDE_ADAPTABLE_UI = 'USER_INTERFACE_SET_HIDE_ADAPTABLE_UI';
5
+ export const UserInterfaceSetHideAdaptableUI = (hideAdaptableUI) => ({
6
+ type: USER_INTERFACE_SET_HIDE_ADAPTABLE_UI,
7
+ hideAdaptableUI,
8
+ });
9
+ const initialState = {
10
+ HideAdaptableUI: false,
11
+ };
12
+ export const UserInterfaceReducer = (state = initialState, action) => {
13
+ switch (action.type) {
14
+ case USER_INTERFACE_SET_HIDE_ADAPTABLE_UI:
15
+ return Object.assign({}, state, {
16
+ HideAdaptableUI: action.hideAdaptableUI,
17
+ });
18
+ default:
19
+ return state;
20
+ }
21
+ };
@@ -38,6 +38,7 @@ import * as InternalRedux from '../ActionsReducers/InternalRedux';
38
38
  import * as TeamSharingRedux from '../ActionsReducers/TeamSharingRedux';
39
39
  import * as ThemeRedux from '../ActionsReducers/ThemeRedux';
40
40
  import * as ToolPanelRedux from '../ActionsReducers/ToolPanelRedux';
41
+ import * as UserInterfaceRedux from '../ActionsReducers/UserInterfaceRedux';
41
42
  import { areAdaptableProfileTracksEnabled, getMarker } from '../../devTools';
42
43
  import { isAdaptableSharedEntity, isCustomSharedEntity, } from '../../AdaptableState/TeamSharingState';
43
44
  import { buildAdaptableStateFunctionConfig } from './buildAdaptableStateFunctionConfig';
@@ -121,6 +122,7 @@ export class AdaptableStore {
121
122
  TeamSharing: TeamSharingRedux.TeamSharingReducer,
122
123
  Theme: ThemeRedux.ThemeReducer,
123
124
  ToolPanel: ToolPanelRedux.ToolPanelReducer,
125
+ UserInterface: UserInterfaceRedux.UserInterfaceReducer,
124
126
  };
125
127
  // allow plugins to participate in the root reducer
126
128
  adaptable.forPlugins((plugin) => {
@@ -992,6 +994,31 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
992
994
  module.setUpScheduleJobs();
993
995
  return returnAction;
994
996
  }
997
+ /*******************
998
+ * USER INTERFACE ACTIONS
999
+ *******************/
1000
+ case UserInterfaceRedux.USER_INTERFACE_SET_HIDE_ADAPTABLE_UI: {
1001
+ const returnAction = next(action);
1002
+ const { hideAdaptableUI } = action;
1003
+ // Hide or show Dashboard
1004
+ middlewareAPI.dispatch(DashboardRedux.DashboardSetIsHidden(hideAdaptableUI));
1005
+ // Hide or show Adaptable ToolPanel in the AG Grid sidebar
1006
+ if (hideAdaptableUI) {
1007
+ adaptable.hideAdaptableToolPanel();
1008
+ }
1009
+ else {
1010
+ adaptable.showAdaptableToolPanel();
1011
+ }
1012
+ // Hide or show Adaptable StatusBar panels
1013
+ if (hideAdaptableUI) {
1014
+ adaptable.hideAdaptableStatusBar();
1015
+ }
1016
+ else {
1017
+ adaptable.showAdaptableStatusBar();
1018
+ }
1019
+ // Column and Context Menus are handled in the AgGridMenuAdapter
1020
+ return returnAction;
1021
+ }
995
1022
  /*******************
996
1023
  * DASHBOARD ACTIONS
997
1024
  *******************/
@@ -0,0 +1,23 @@
1
+ import type { AdaptableContainerValue, ContainerContext, InitContainerContext } from '../AdaptableOptions/ContainerOptions';
2
+ /**
3
+ * The union type representing any container option value (static or function).
4
+ */
5
+ type AnyContainerOption = AdaptableContainerValue | ((context: any) => AdaptableContainerValue);
6
+ /**
7
+ * Resolves a container option value to an `HTMLElement`.
8
+ *
9
+ * Resolution order:
10
+ * 1. If `container` is `null`/`undefined`, returns `null`.
11
+ * 2. If `container` is a function, it is called with the provided `context` and the result is resolved.
12
+ * 3. If the value is an `HTMLElement`, it is returned directly.
13
+ * 4. If the value is an `AdaptableCSSSelector` (`{ selector: string }`), `document.querySelectorAll` is used.
14
+ * If multiple elements match, the first is returned and a console warning is logged.
15
+ * 5. If the value is a `string`, it is treated as an element ID and `document.getElementById` is used.
16
+ *
17
+ * @param container - The container reference to resolve.
18
+ * @param context - Optional context passed to the function form of the container.
19
+ * @param doc - The document to query against (defaults to `globalThis.document`).
20
+ * @returns The resolved `HTMLElement`, or `null` if not found.
21
+ */
22
+ export declare function resolveContainerElement(container: AnyContainerOption | undefined | null, context?: ContainerContext | InitContainerContext, doc?: Document): HTMLElement | null;
23
+ export {};
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Resolves a container option value to an `HTMLElement`.
3
+ *
4
+ * Resolution order:
5
+ * 1. If `container` is `null`/`undefined`, returns `null`.
6
+ * 2. If `container` is a function, it is called with the provided `context` and the result is resolved.
7
+ * 3. If the value is an `HTMLElement`, it is returned directly.
8
+ * 4. If the value is an `AdaptableCSSSelector` (`{ selector: string }`), `document.querySelectorAll` is used.
9
+ * If multiple elements match, the first is returned and a console warning is logged.
10
+ * 5. If the value is a `string`, it is treated as an element ID and `document.getElementById` is used.
11
+ *
12
+ * @param container - The container reference to resolve.
13
+ * @param context - Optional context passed to the function form of the container.
14
+ * @param doc - The document to query against (defaults to `globalThis.document`).
15
+ * @returns The resolved `HTMLElement`, or `null` if not found.
16
+ */
17
+ export function resolveContainerElement(container, context, doc = globalThis.document) {
18
+ if (container == null) {
19
+ return null;
20
+ }
21
+ // Unwrap function form — pass context if the container is a function
22
+ const value = typeof container === 'function' ? container(context) : container;
23
+ // Guard against null/undefined returned by a callback (e.g. document.getElementById(...))
24
+ if (value == null) {
25
+ return null;
26
+ }
27
+ // Direct HTMLElement reference
28
+ if (value instanceof HTMLElement) {
29
+ return value;
30
+ }
31
+ // CSS Selector object
32
+ if (typeof value === 'object' && 'selector' in value) {
33
+ const matches = doc.querySelectorAll(value.selector);
34
+ if (matches.length > 1) {
35
+ console.warn(`[AdapTable] CSS selector "${value.selector}" matched ${matches.length} elements. Using the first match. Consider using a more specific selector.`);
36
+ }
37
+ return matches[0] ?? null;
38
+ }
39
+ // String element ID
40
+ if (typeof value === 'string') {
41
+ return doc.getElementById(value);
42
+ }
43
+ return null;
44
+ }
@@ -93,7 +93,7 @@ export const ColumnFilterInput = (props) => {
93
93
  return (React.createElement(AdaptableInput, { style: filterType === 'floating'
94
94
  ? {
95
95
  width: '100%',
96
- padding: 'var(--ab-space-1)',
96
+ padding: 'var(--ab-base-space)',
97
97
  borderRadius: 0,
98
98
  border: 'none',
99
99
  }
@@ -9,6 +9,7 @@ import { AdaptablePopupBody } from './AdaptablePopupBody';
9
9
  import { useAdaptable } from '../../../AdaptableContext';
10
10
  import { CustomSettingsPanelView } from './CustomSettingsPanelView';
11
11
  import { useMenuItems } from './useMenuItems';
12
+ import { resolveContainerElement } from '../../../../Utilities/resolveContainerElement';
12
13
  import { AdaptablePopupDialog } from './AdaptablePopupDialog';
13
14
  import { Box } from '../../../../components/Flex';
14
15
  export const AdaptablePopup = (props) => {
@@ -17,7 +18,7 @@ export const AdaptablePopup = (props) => {
17
18
  const settingsPanelTitle = adaptable.ModuleService.getModuleFriendlyName('SettingsPanel');
18
19
  const menuItems = useMenuItems();
19
20
  const isWindowModal = settingsPanelOptions.popupType === 'window';
20
- const modalContainer = adaptable.adaptableOptions?.containerOptions?.modalContainer;
21
+ const modalContainer = resolveContainerElement(adaptable.adaptableOptions?.containerOptions?.modalContainer, props.api.internalApi.buildBaseContext());
21
22
  let friendlyName = null;
22
23
  /**
23
24
  * This means that it is not rendered in the context of Settings Panel
@@ -3,7 +3,7 @@ import { UIHelper } from '../../../UIHelper';
3
3
  import { AdaptableViewFactory } from '../../../AdaptableViewFactory';
4
4
  import { AdaptablePopupModuleView } from './AdaptablePopupModuleView';
5
5
  export const AdaptablePopupBody = (props) => {
6
- const modalContainer = UIHelper.getModalContainer(props.api.optionsApi.getAdaptableOptions(), document);
6
+ const modalContainer = UIHelper.getModalContainer(props.api.optionsApi.getAdaptableOptions(), document, props.api.internalApi.buildBaseContext());
7
7
  const moduleName = props.module.moduleInfo.ModuleName;
8
8
  const accessLevel = props.api.entitlementApi.getEntitlementAccessLevelForModule(moduleName);
9
9
  const moduleInfo = props.api.internalApi.getModuleService().getModuleInfoByModule(moduleName);
@@ -7,6 +7,6 @@ export declare const AdaptablePopupDialog: React.FunctionComponent<React.PropsWi
7
7
  isWindowModal: boolean;
8
8
  onHide: () => void;
9
9
  style?: React.CSSProperties;
10
- modalContainer?: string | HTMLElement;
10
+ modalContainer?: HTMLElement;
11
11
  dataName?: string;
12
12
  }>>;
@@ -43,14 +43,7 @@ const PopupDialog = (props) => {
43
43
  export const AdaptablePopupDialog = (props) => {
44
44
  const { isActionModule, style, friendlyName, baseClassName, className, children, onHide, isWindowModal, modalContainer, } = props;
45
45
  if (modalContainer) {
46
- let ref = null;
47
- if (typeof modalContainer === 'string') {
48
- ref = globalThis.document.querySelector(modalContainer);
49
- }
50
- else {
51
- ref = modalContainer;
52
- }
53
- return createPortal(React.createElement(Dialog, { "data-name": props.dataName, modal: false, fixed: false, onDismiss: onHide, className: className }, children), ref);
46
+ return createPortal(React.createElement(Dialog, { "data-name": props.dataName, modal: false, fixed: false, onDismiss: onHide, className: className }, children), modalContainer);
54
47
  }
55
48
  if (isWindowModal) {
56
49
  const settingsPanelOptionsKey = isActionModule ? `action-${friendlyName}` : 'settings';
@@ -1,16 +1,44 @@
1
1
  import * as React from 'react';
2
+ import { createPortal } from 'react-dom';
2
3
  import { useDispatch, useSelector } from 'react-redux';
3
4
  import Dialog from '../../../../components/Dialog';
4
5
  import { PopupHideWindow } from '../../../../Redux/ActionsReducers/PopupRedux';
6
+ import { resolveContainerElement } from '../../../../Utilities/resolveContainerElement';
5
7
  import { useAdaptable } from '../../../AdaptableContext';
6
8
  import { ExternalRenderer } from '../../ExternalRenderer';
7
9
  import { PanelWithImage } from '../../Panels/PanelWithImage';
8
10
  import { getMiddlePosition, getWindowPopupSize } from '../Utilities';
9
- import { windowFactory } from './windowFactory';
11
+ import { WINDOW_SHOW_TRANSPOSED_VIEW, windowFactory } from './windowFactory';
10
12
  const NoopComponent = () => {
11
13
  return React.createElement(React.Fragment, null);
12
14
  };
13
15
  export const CUSTOM_WINDOW_FACTORY_ID = 'CUSTOM_WINDOW_FACTORY_ID';
16
+ /**
17
+ * Portals children into a target container element.
18
+ * Monitors the container with a MutationObserver — if the container is removed
19
+ * from the DOM, `onContainerRemoved` is called so callers can clean up React/Redux state.
20
+ */
21
+ const ContainerPortal = ({ container, onContainerRemoved, children }) => {
22
+ React.useEffect(() => {
23
+ // If the container is already detached, clean up immediately
24
+ if (!document.contains(container)) {
25
+ onContainerRemoved();
26
+ return;
27
+ }
28
+ const observer = new MutationObserver(() => {
29
+ if (!document.contains(container)) {
30
+ onContainerRemoved();
31
+ observer.disconnect();
32
+ }
33
+ });
34
+ // Observe the entire document body for subtree removals
35
+ observer.observe(document.body, { childList: true, subtree: true });
36
+ return () => {
37
+ observer.disconnect();
38
+ };
39
+ }, [container, onContainerRemoved]);
40
+ return createPortal(children, container);
41
+ };
14
42
  export const WindowPopups = () => {
15
43
  const [windowModalSettings, setWindowModalSettings] = React.useState({});
16
44
  const adaptable = useAdaptable();
@@ -37,6 +65,13 @@ export const WindowPopups = () => {
37
65
  Component = Component ?? NoopComponent;
38
66
  componentNode = (React.createElement(Component, { api: adaptable.api, onDismiss: handleDismiss, popupProps: restPopupProps }));
39
67
  }
68
+ // Transposed View: portal into custom container if configured
69
+ if (windowItem.FactoryId === WINDOW_SHOW_TRANSPOSED_VIEW) {
70
+ const transposedContainer = resolveContainerElement(adaptable.adaptableOptions?.containerOptions?.transposedViewContainer, adaptable.api.internalApi.buildBaseContext());
71
+ if (transposedContainer) {
72
+ return (React.createElement(ContainerPortal, { key: windowItem.Id, container: transposedContainer, onContainerRemoved: handleDismiss }, componentNode));
73
+ }
74
+ }
40
75
  return (React.createElement(Dialog, { "data-name": windowItem.Id, className: "ab-Window-Modal twa:h-full twa:p-0", key: windowItem.Id, windowModal: true, windowModalProps: {
41
76
  ...windowModalProps,
42
77
  onChange: (settings) => {
@@ -9,7 +9,7 @@ const tableDOMProps = {
9
9
  className: 'ab-WizardSummary__list',
10
10
  style: {
11
11
  height: '100%',
12
- margin: 'var(--ab-space-2)',
12
+ margin: 'calc(var(--ab-base-space) * 2)',
13
13
  },
14
14
  };
15
15
  export const WizardSummaryPage = (props) => {
@@ -75,7 +75,7 @@ export const CustomToolbarCmp = (props) => {
75
75
  const disabled = button.disabled && button.disabled(button, dashboardContext);
76
76
  let buttonVariant = buttonStyle && buttonStyle.variant ? buttonStyle.variant : 'outlined';
77
77
  let buttonTone = buttonStyle && buttonStyle.tone ? buttonStyle.tone : 'neutral';
78
- return (React.createElement(AdaptableButtonComponent, { style: { marginLeft: index ? 'var(--ab-space-1)' : 0 }, key: index, disabled: disabled, tooltip: buttonTooltip, icon: buttonIcon, variant: buttonVariant, tone: buttonTone, className: buttonStyle?.className || '', onClick: () => {
78
+ return (React.createElement(AdaptableButtonComponent, { style: { marginLeft: index ? 'var(--ab-base-space)' : 0 }, key: index, disabled: disabled, tooltip: buttonTooltip, icon: buttonIcon, variant: buttonVariant, tone: buttonTone, className: buttonStyle?.className || '', onClick: () => {
79
79
  button.onClick ? button.onClick(button, dashboardContext) : null;
80
80
  setTimeout(() => {
81
81
  // mutate state to force a re-rendering
@@ -27,7 +27,7 @@ export const DataChangeHistoryViewPanelControl = (props) => {
27
27
  const enabled = changeHistoryMode === 'ACTIVE';
28
28
  const disabled = changeHistoryMode === 'INACTIVE';
29
29
  const suspended = changeHistoryMode === 'SUSPENDED';
30
- const gap = props.gap ?? 'var(--ab-space-1)';
30
+ const gap = props.gap ?? 'var(--ab-base-space)';
31
31
  const buttonsPaddingY = props.buttonsPaddingY ?? 2;
32
32
  const buttonPanel = (React.createElement(Flex, { className: "ab-DataChangeHistoryPanel--button-panel", style: { gap: gap, paddingBlock: buttonsPaddingY } },
33
33
  disabled && (React.createElement(ButtonPlay, { "aria-label": "Enable Data Change History", className: "ab-DataChangeHistoryPanel--button-activate", "data-name": 'data-change-history--button-activate', tooltip: '', onClick: () => onChangeHistoryEnable() })),