@adaptabletools/adaptable 24.0.0-canary.5 → 24.0.0-canary.6

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 (93) hide show
  1. package/devtools.d.ts +182 -1
  2. package/index.css +271 -102
  3. package/package.json +2 -1
  4. package/src/AdaptableInterfaces/IAdaptable.d.ts +4 -4
  5. package/src/AdaptableOptions/DefaultAdaptableOptions.js +5 -5
  6. package/src/AdaptableOptions/FlashingCellOptions.d.ts +3 -3
  7. package/src/AdaptableOptions/SettingsPanelOptions.d.ts +6 -4
  8. package/src/AdaptableOptions/StateOptions.d.ts +37 -13
  9. package/src/AdaptableState/AdaptableState.d.ts +2 -0
  10. package/src/AdaptableState/QuickSearchState.d.ts +4 -0
  11. package/src/Api/Implementation/ColumnScopeApiImpl.js +3 -3
  12. package/src/Api/Implementation/StateApiImpl.d.ts +1 -1
  13. package/src/Api/Implementation/StateApiImpl.js +4 -3
  14. package/src/Api/Internal/CalculatedColumnInternalApi.js +1 -1
  15. package/src/Api/Internal/StateInternalApi.d.ts +1 -1
  16. package/src/Api/Internal/StateInternalApi.js +2 -2
  17. package/src/Api/StateApi.d.ts +2 -2
  18. package/src/Redux/ActionsReducers/QuickSearchRedux.d.ts +0 -4
  19. package/src/Redux/ActionsReducers/QuickSearchRedux.js +3 -7
  20. package/src/Redux/Store/AdaptableReduxLocalStorageEngine.d.ts +8 -0
  21. package/src/Redux/Store/AdaptableReduxLocalStorageEngine.js +12 -12
  22. package/src/Redux/Store/AdaptableStore.d.ts +8 -5
  23. package/src/Redux/Store/AdaptableStore.js +47 -19
  24. package/src/Redux/Store/Interface/IAdaptableStore.d.ts +5 -5
  25. package/src/Redux/Store/Interface/IStorageEngine.d.ts +4 -4
  26. package/src/Redux/Store/StateOptionsGuards.d.ts +58 -0
  27. package/src/Redux/Store/StateOptionsGuards.js +112 -0
  28. package/src/Redux/Store/isTransientReduxAction.d.ts +5 -0
  29. package/src/Redux/Store/isTransientReduxAction.js +19 -0
  30. package/src/Utilities/Constants/DocumentationLinkConstants.d.ts +1 -0
  31. package/src/Utilities/Constants/DocumentationLinkConstants.js +1 -0
  32. package/src/Utilities/Constants/ReduxConstants.d.ts +2 -2
  33. package/src/Utilities/Constants/ReduxConstants.js +5 -5
  34. package/src/Utilities/Helpers/AlertTypeHelper.d.ts +1 -1
  35. package/src/Utilities/Helpers/SettingsPanelHelper.d.ts +14 -0
  36. package/src/Utilities/Helpers/SettingsPanelHelper.js +37 -1
  37. package/src/Utilities/Helpers/UIHelper.d.ts +6 -3
  38. package/src/Utilities/Helpers/UIHelper.js +8 -4
  39. package/src/Utilities/ObjectFactory.js +3 -3
  40. package/src/View/Dashboard/DashboardPopupSections.js +1 -1
  41. package/src/View/GridInfo/GridInfoPopup.js +62 -25
  42. package/src/View/StyledColumn/RangesComponent.js +6 -6
  43. package/src/View/StyledColumn/Wizard/StyledColumnWizardBulletSection.js +2 -2
  44. package/src/View/StyledColumn/Wizard/StyledColumnWizardRangeBarSection.js +4 -4
  45. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/StyledColumnWizardRangesSection.js +2 -2
  46. package/src/View/StyledColumn/Wizard/StyledColumnWizardStyleSection/StyledColumnWizardStyleSection.js +2 -2
  47. package/src/View/Wizard/CollapsibleWizardCard.d.ts +3 -1
  48. package/src/View/Wizard/CollapsibleWizardCard.js +17 -9
  49. package/src/agGrid/AdaptableAgGrid.d.ts +4 -4
  50. package/src/agGrid/AdaptableAgGrid.js +2 -0
  51. package/src/agGrid/AgGridColumnAdapter.d.ts +1 -1
  52. package/src/agGrid/AgGridColumnAdapter.js +4 -4
  53. package/src/components/aql/QueryBuilder/QueryBuilderInputs.js +1 -1
  54. package/src/env.js +2 -2
  55. package/src/layout-manager/src/normalizeLayoutModel.d.ts +1 -1
  56. package/src/layout-manager/src/simplifyLayoutModel.d.ts +1 -1
  57. package/src/migration/AdaptableUpgradeHelper.d.ts +7 -2
  58. package/src/migration/VersionUpgrade17.js +13 -8
  59. package/src/setupDevTools.js +442 -103
  60. package/src/types.d.ts +1 -1
  61. package/tsconfig.esm.tsbuildinfo +1 -1
  62. package/vendor/components/Button/index.d.ts +1 -1
  63. package/vendor/components/Button/index.d.ts.map +1 -1
  64. package/vendor/components/Button/index.js.map +1 -1
  65. package/vendor/components/CheckBox/index.d.ts +1 -1
  66. package/vendor/components/CheckBox/index.d.ts.map +1 -1
  67. package/vendor/components/CheckBox/index.js.map +1 -1
  68. package/vendor/components/ColorPicker/colorPickerTab.d.ts +4 -0
  69. package/vendor/components/ColorPicker/colorPickerTab.d.ts.map +1 -0
  70. package/vendor/components/ColorPicker/colorPickerTab.js +50 -0
  71. package/vendor/components/ColorPicker/colorPickerTab.js.map +1 -0
  72. package/vendor/components/ColorPicker/index.d.ts +31 -0
  73. package/vendor/components/ColorPicker/index.d.ts.map +1 -0
  74. package/vendor/components/ColorPicker/index.js +132 -0
  75. package/vendor/components/ColorPicker/index.js.map +1 -0
  76. package/vendor/components/ColorPicker/themeColors.d.ts +24 -0
  77. package/vendor/components/ColorPicker/themeColors.d.ts.map +1 -0
  78. package/vendor/components/ColorPicker/themeColors.js +52 -0
  79. package/vendor/components/ColorPicker/themeColors.js.map +1 -0
  80. package/vendor/components/Combobox/VirtualizedList.d.ts +1 -1
  81. package/vendor/components/Combobox/VirtualizedList.d.ts.map +1 -1
  82. package/vendor/components/Combobox/VirtualizedList.js.map +1 -1
  83. package/vendor/components/Combobox/index.d.ts +1 -1
  84. package/vendor/components/Combobox/index.d.ts.map +1 -1
  85. package/vendor/components/Combobox/index.js.map +1 -1
  86. package/vendor/components/index.css +213 -0
  87. package/vendor/components/index.d.ts +2 -0
  88. package/vendor/components/index.d.ts.map +1 -1
  89. package/vendor/components/index.js +1 -0
  90. package/vendor/components/index.js.map +1 -1
  91. package/vendor/components/ui/combobox.d.ts.map +1 -1
  92. package/vendor/components/ui/combobox.js +1 -1
  93. package/vendor/components/ui/combobox.js.map +1 -1
@@ -4,6 +4,7 @@ import * as PopupRedux from '../ActionsReducers/PopupRedux';
4
4
  import { PROGRESS_INDICATOR_HIDE, PROGRESS_INDICATOR_SHOW } from '../ActionsReducers/PopupRedux';
5
5
  import { createEngine as createEngineLocal } from './AdaptableReduxLocalStorageEngine';
6
6
  import { mergeReducer } from './AdaptableReduxMerger';
7
+ import { runSyncStateFunction } from './StateOptionsGuards';
7
8
  import { isRowChangeAlertDefinition } from '../../AdaptableState/AlertState';
8
9
  import { getAlertCellDataChangedInfos, isAdaptableRowChangedAlert, } from '../../AdaptableState/Common/AdaptableAlert';
9
10
  import { closeAgChartDefinitionIfOpen, closeExternalChartDefinitionIfOpen, } from '../../Utilities/Helpers/ChartHelper';
@@ -185,13 +186,9 @@ export class AdaptableStore {
185
186
  !init &&
186
187
  !this.loadStorageInProgress;
187
188
  if (shouldPersist) {
188
- let storageState = { ...finalState };
189
- storageState = getPersistableState(storageState);
189
+ const storageState = getPersistableState({ ...finalState });
190
190
  this.currentStorageState = storageState;
191
- this.previousStorageState = { ...state };
192
- NON_PERSISTENT_STORE_KEYS.forEach((key) => {
193
- delete this.previousStorageState[key];
194
- });
191
+ this.previousStorageState = getPersistableState({ ...state });
195
192
  storageEngine.save(adaptable, storageState, action.type);
196
193
  }
197
194
  return finalState;
@@ -245,7 +242,9 @@ export class AdaptableStore {
245
242
  return this.previousStorageState;
246
243
  }
247
244
  saveStateNow(adaptable, state) {
248
- const newState = state ?? this.getCurrentStorageState();
245
+ const newState = state
246
+ ? getPersistableState({ ...state })
247
+ : this.getCurrentStorageState();
249
248
  if (newState) {
250
249
  return this.storageEngine.saveNow(adaptable, newState, 'API_CALL_SAVE_STATE');
251
250
  }
@@ -260,7 +259,8 @@ export class AdaptableStore {
260
259
  .load(adaptable, initialState ?? adaptable.adaptableOptions.initialState)
261
260
  .then((storedState) => {
262
261
  if (storedState && this.loadStateOnStartup) {
263
- this.TheStore.dispatch(LoadState(postProcessState(adaptable.adaptableOptions.stateOptions.applyState(storedState, adaptable.api.stateApi.internalApi.buildAdaptableStateFunctionConfig()))));
262
+ const appliedState = runSyncStateFunction('applyState', adaptable.adaptableOptions.stateOptions.applyState, storedState, adaptable.api.stateApi.internalApi.buildAdaptableStateFunctionConfig(), adaptable.logger);
263
+ this.TheStore.dispatch(LoadState(postProcessState(appliedState)));
264
264
  }
265
265
  })
266
266
  .then(() => {
@@ -402,10 +402,26 @@ function refreshFormulaTraceCells(adaptable, formulaTraceInfo) {
402
402
  });
403
403
  }
404
404
  const LAYOUT_EXTENSION_OBJECT_ACTIONS = {
405
- [AlertRedux.ALERT_DEFINITION_EDIT]: { module: 'Alert', payloadKey: 'alertDefinition', kind: 'edit' },
406
- [AlertRedux.ALERT_DEFINITION_DELETE]: { module: 'Alert', payloadKey: 'alertDefinition', kind: 'delete' },
407
- [CustomSortRedux.CUSTOM_SORT_EDIT]: { module: 'CustomSort', payloadKey: 'customSort', kind: 'edit' },
408
- [CustomSortRedux.CUSTOM_SORT_DELETE]: { module: 'CustomSort', payloadKey: 'customSort', kind: 'delete' },
405
+ [AlertRedux.ALERT_DEFINITION_EDIT]: {
406
+ module: 'Alert',
407
+ payloadKey: 'alertDefinition',
408
+ kind: 'edit',
409
+ },
410
+ [AlertRedux.ALERT_DEFINITION_DELETE]: {
411
+ module: 'Alert',
412
+ payloadKey: 'alertDefinition',
413
+ kind: 'delete',
414
+ },
415
+ [CustomSortRedux.CUSTOM_SORT_EDIT]: {
416
+ module: 'CustomSort',
417
+ payloadKey: 'customSort',
418
+ kind: 'edit',
419
+ },
420
+ [CustomSortRedux.CUSTOM_SORT_DELETE]: {
421
+ module: 'CustomSort',
422
+ payloadKey: 'customSort',
423
+ kind: 'delete',
424
+ },
409
425
  [FlashingCellRedux.FLASHING_CELL_DEFINITION_EDIT]: {
410
426
  module: 'FlashingCell',
411
427
  payloadKey: 'flashingCellDefinition',
@@ -416,13 +432,21 @@ const LAYOUT_EXTENSION_OBJECT_ACTIONS = {
416
432
  payloadKey: 'flashingCellDefinition',
417
433
  kind: 'delete',
418
434
  },
419
- [FormatColumnRedux.FORMAT_COLUMN_EDIT]: { module: 'FormatColumn', payloadKey: 'formatColumn', kind: 'edit' },
435
+ [FormatColumnRedux.FORMAT_COLUMN_EDIT]: {
436
+ module: 'FormatColumn',
437
+ payloadKey: 'formatColumn',
438
+ kind: 'edit',
439
+ },
420
440
  [FormatColumnRedux.FORMAT_COLUMN_DELETE]: {
421
441
  module: 'FormatColumn',
422
442
  payloadKey: 'formatColumn',
423
443
  kind: 'delete',
424
444
  },
425
- [PlusMinusRedux.PLUS_MINUS_RULE_EDIT]: { module: 'PlusMinus', payloadKey: 'plusMinusNudge', kind: 'edit' },
445
+ [PlusMinusRedux.PLUS_MINUS_RULE_EDIT]: {
446
+ module: 'PlusMinus',
447
+ payloadKey: 'plusMinusNudge',
448
+ kind: 'edit',
449
+ },
426
450
  [PlusMinusRedux.PLUS_MINUS_RULE_DELETE]: {
427
451
  module: 'PlusMinus',
428
452
  payloadKey: 'plusMinusNudge',
@@ -430,7 +454,11 @@ const LAYOUT_EXTENSION_OBJECT_ACTIONS = {
430
454
  },
431
455
  [ShortcutRedux.SHORTCUT_EDIT]: { module: 'Shortcut', payloadKey: 'shortcut', kind: 'edit' },
432
456
  [ShortcutRedux.SHORTCUT_DELETE]: { module: 'Shortcut', payloadKey: 'shortcut', kind: 'delete' },
433
- [StyledColumnRedux.STYLED_COLUMN_EDIT]: { module: 'StyledColumn', payloadKey: 'StyledColumn', kind: 'edit' },
457
+ [StyledColumnRedux.STYLED_COLUMN_EDIT]: {
458
+ module: 'StyledColumn',
459
+ payloadKey: 'StyledColumn',
460
+ kind: 'edit',
461
+ },
434
462
  [StyledColumnRedux.STYLED_COLUMN_DELETE]: {
435
463
  module: 'StyledColumn',
436
464
  payloadKey: 'StyledColumn',
@@ -585,8 +613,8 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
585
613
  if (!adaptable.api.freeTextColumnApi.internalApi.validateDeletedFreeTextColumn(actionTyped.freeTextColumn)) {
586
614
  return;
587
615
  }
588
- if (adaptable.api.optionsApi.getLayoutOptions()
589
- ?.autoRemoveDeletedColumnsFromLayouts !== false) {
616
+ if (adaptable.api.optionsApi.getLayoutOptions()?.autoRemoveDeletedColumnsFromLayouts !==
617
+ false) {
590
618
  adaptable.api.layoutApi.internalApi.removeColumnIdFromAllLayouts(actionTyped.freeTextColumn.ColumnId);
591
619
  }
592
620
  }
@@ -607,8 +635,8 @@ const adaptableMiddleware = (adaptable) => (function(middlewareAPI) {
607
635
  if (!adaptable.api.calculatedColumnApi.internalApi.validateDeletedCalculatedColumn(calculatedColumn)) {
608
636
  return;
609
637
  }
610
- if (adaptable.api.optionsApi.getLayoutOptions()
611
- ?.autoRemoveDeletedColumnsFromLayouts !== false) {
638
+ if (adaptable.api.optionsApi.getLayoutOptions()?.autoRemoveDeletedColumnsFromLayouts !==
639
+ false) {
612
640
  adaptable.api.layoutApi.internalApi.removeColumnIdFromAllLayouts(calculatedColumn.ColumnId);
613
641
  }
614
642
  }
@@ -1,20 +1,20 @@
1
1
  import * as Redux from 'redux';
2
- import { AdaptableState } from '../../../AdaptableState/AdaptableState';
2
+ import { AdaptablePersistentState, AdaptableState } from '../../../AdaptableState/AdaptableState';
3
3
  import { InitialState } from '../../../types';
4
4
  import { IAdaptable } from '../../../AdaptableInterfaces/IAdaptable';
5
5
  export interface LoadStoreConfig {
6
6
  adaptable: IAdaptable;
7
7
  adaptableStateKey: string;
8
8
  initialState?: InitialState;
9
- postLoadHook?: (state: AdaptableState) => AdaptableState;
9
+ postLoadHook?: (state: Partial<AdaptablePersistentState>) => Partial<AdaptablePersistentState>;
10
10
  }
11
11
  export interface IAdaptableStore {
12
12
  TheStore: Redux.Store<AdaptableState>;
13
13
  Load: Promise<any>;
14
14
  loadStore: (config: LoadStoreConfig) => Promise<any>;
15
- getCurrentStorageState: () => AdaptableState | void;
16
- getPreviousStorageState: () => AdaptableState | void;
17
- saveStateNow: (adaptable: IAdaptable, state?: AdaptableState) => Promise<any>;
15
+ getCurrentStorageState: () => AdaptablePersistentState | void;
16
+ getPreviousStorageState: () => AdaptablePersistentState | void;
17
+ saveStateNow: (adaptable: IAdaptable, state?: AdaptablePersistentState) => Promise<any>;
18
18
  on: (eventName: string, callback: (data?: any) => any) => () => void;
19
19
  onAny: (callback: (eventName: string, data?: any) => any) => () => void;
20
20
  onBeforeAny: (callback: (eventName: string, data?: any) => any) => () => void;
@@ -1,9 +1,9 @@
1
- import { AdaptableState } from '../../../AdaptableState/AdaptableState';
1
+ import { AdaptablePersistentState } from '../../../AdaptableState/AdaptableState';
2
2
  import { InitialState } from '../../../AdaptableState/InitialState';
3
3
  import { IAdaptable } from '../../../AdaptableInterfaces/IAdaptable';
4
4
  export default interface IStorageEngine {
5
- load(adaptable: IAdaptable, initialState?: string | InitialState): Promise<any>;
6
- save(adaptable: IAdaptable, state: AdaptableState, actionName: string): Promise<any>;
7
- saveNow(adaptable: IAdaptable, state: AdaptableState, actionName: string): Promise<any>;
5
+ load(adaptable: IAdaptable, initialState?: string | InitialState): Promise<Partial<AdaptablePersistentState> | void>;
6
+ save(adaptable: IAdaptable, state: AdaptablePersistentState, actionName: string): Promise<any>;
7
+ saveNow(adaptable: IAdaptable, state: AdaptablePersistentState, actionName: string): Promise<any>;
8
8
  setStateKey(stateKey: string): void;
9
9
  }
@@ -0,0 +1,58 @@
1
+ import { AdaptablePersistentState } from '../../AdaptableState/AdaptableState';
2
+ import { AdaptableStateFunctionConfig, StateOptions } from '../../AdaptableOptions/StateOptions';
3
+ /**
4
+ * Runtime guards for the `StateOptions` functions.
5
+ *
6
+ * The most frequent mistakes when implementing these functions are:
7
+ * - providing an `async` function (or otherwise returning a Promise) for `saveState` / `applyState`, which are synchronous
8
+ * - mutating the state in `saveState` / `applyState` but forgetting to return it
9
+ * - returning a plain value (not a Promise) from `loadState` / `persistState`
10
+ *
11
+ * The helpers below detect these cases - as early as possible - and either recover (when there is only one sensible
12
+ * interpretation) or fail with an actionable error message instead of an obscure one further down the line.
13
+ */
14
+ export type StateOptionsLogger = {
15
+ consoleError(message: string, ...optionalParams: any[]): void;
16
+ consoleWarn(message: string, ...optionalParams: any[]): void;
17
+ };
18
+ export type SyncStateFunctionName = 'saveState' | 'applyState';
19
+ export type AsyncStateFunctionName = 'loadState' | 'persistState' | 'clearState';
20
+ export type StateFunctionName = SyncStateFunctionName | AsyncStateFunctionName;
21
+ /**
22
+ * Error thrown when a `StateOptions` function breaks its contract
23
+ */
24
+ export declare class AdaptableStateOptionsError extends Error {
25
+ constructor(message: string);
26
+ }
27
+ export declare const isThenable: (value: unknown) => value is PromiseLike<unknown>;
28
+ /**
29
+ * Detects functions declared with the `async` keyword (not transpiled to generators / promises)
30
+ */
31
+ export declare const isAsyncFunction: (fn: unknown) => boolean;
32
+ /**
33
+ * Validates the shape of `stateOptions` once, at initialisation - before any state is loaded or persisted.
34
+ *
35
+ * Reports (does not throw):
36
+ * - non-function values for any state function
37
+ * - `async` functions for `saveState` / `applyState`
38
+ * - `loadState` without `persistState` (or vice versa) - the localStorage fallback is used for the missing one,
39
+ * which makes the remote and local copies of the state diverge
40
+ */
41
+ export declare function validateStateOptions(stateOptions: StateOptions | undefined, logger: StateOptionsLogger): void;
42
+ /**
43
+ * Invokes a synchronous state transform (`saveState` / `applyState`) and validates its result.
44
+ *
45
+ * - returns the result when it is a state object
46
+ * - **recovers** when the function returned nothing: the input state is used (the function most likely mutated it in place
47
+ * and forgot to `return` it) and an error is logged
48
+ * - **throws** `AdaptableStateOptionsError` when the result is a Promise (async function) or any other non-object value;
49
+ * there is no safe way to continue in these cases
50
+ */
51
+ export declare function runSyncStateFunction<T extends Partial<AdaptablePersistentState>>(functionName: SyncStateFunctionName, fn: ((state: T, config: AdaptableStateFunctionConfig) => T) | undefined, state: T, config: AdaptableStateFunctionConfig, logger: StateOptionsLogger): T;
52
+ /**
53
+ * Invokes an asynchronous state function (`loadState` / `persistState` / `clearState`) and normalises its result to a Promise.
54
+ *
55
+ * A non-Promise result is logged (these functions are expected to be async) and wrapped in a resolved Promise, so a
56
+ * synchronous implementation degrades gracefully instead of failing with `.then is not a function`.
57
+ */
58
+ export declare function runAsyncStateFunction<TResult, TArgs extends unknown[]>(functionName: AsyncStateFunctionName, fn: (...args: TArgs) => Promise<TResult>, args: TArgs, logger: StateOptionsLogger): Promise<TResult>;
@@ -0,0 +1,112 @@
1
+ import { StatePersistenceDocsLink } from '../../Utilities/Constants/DocumentationLinkConstants';
2
+ const STATE_FUNCTION_NAMES = [
3
+ 'loadState',
4
+ 'persistState',
5
+ 'applyState',
6
+ 'saveState',
7
+ 'clearState',
8
+ ];
9
+ export class AdaptableStateOptionsError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = 'AdaptableStateOptionsError';
13
+ }
14
+ }
15
+ export const isThenable = (value) => {
16
+ return value != null && typeof value.then === 'function';
17
+ };
18
+ export const isAsyncFunction = (fn) => {
19
+ return typeof fn === 'function' && fn.constructor?.name === 'AsyncFunction';
20
+ };
21
+ const isStateObject = (value) => {
22
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
23
+ };
24
+ const docs = `See ${StatePersistenceDocsLink}`;
25
+ const syncFunctionMustReturnMessage = (functionName) => `stateOptions.${functionName} must be synchronous and return the (modified) state object.`;
26
+ const asyncFunctionMessage = (functionName, reason) => `${syncFunctionMustReturnMessage(functionName)} ${reason} ` +
27
+ `Asynchronous work belongs in stateOptions.${functionName === 'saveState' ? 'persistState' : 'loadState'}. ${docs}`;
28
+ export function validateStateOptions(stateOptions, logger) {
29
+ if (!stateOptions) {
30
+ return;
31
+ }
32
+ for (const functionName of STATE_FUNCTION_NAMES) {
33
+ const fn = stateOptions[functionName];
34
+ if (fn != null && typeof fn !== 'function') {
35
+ logger.consoleError(`stateOptions.${functionName} must be a function, but received ${describe(fn)}. ${docs}`);
36
+ }
37
+ }
38
+ for (const functionName of ['saveState', 'applyState']) {
39
+ if (isAsyncFunction(stateOptions[functionName])) {
40
+ logger.consoleError(asyncFunctionMessage(functionName, 'It is declared as an async function.'));
41
+ }
42
+ }
43
+ const hasLoadState = typeof stateOptions.loadState === 'function';
44
+ const hasPersistState = typeof stateOptions.persistState === 'function';
45
+ if (hasLoadState !== hasPersistState) {
46
+ const provided = hasLoadState ? 'loadState' : 'persistState';
47
+ const missing = hasLoadState ? 'persistState' : 'loadState';
48
+ logger.consoleWarn(`stateOptions.${provided} is provided without stateOptions.${missing}; ` +
49
+ `the default localStorage implementation is used for ${missing}, so the loaded and the persisted state may diverge. ` +
50
+ `Provide both functions (or neither). ${docs}`);
51
+ }
52
+ }
53
+ export function runSyncStateFunction(functionName, fn, state, config, logger) {
54
+ if (fn == null) {
55
+ return state;
56
+ }
57
+ if (typeof fn !== 'function') {
58
+ throw new AdaptableStateOptionsError(`stateOptions.${functionName} must be a function, but received ${describe(fn)}. ${docs}`);
59
+ }
60
+ const result = fn(state, config);
61
+ if (result === undefined) {
62
+ logger.consoleError(`${syncFunctionMustReturnMessage(functionName)} It returned nothing - ` +
63
+ `the state object passed to it is used instead (add 'return state;' to fix this). ${docs}`);
64
+ return state;
65
+ }
66
+ if (isThenable(result)) {
67
+ throw new AdaptableStateOptionsError(asyncFunctionMessage(functionName, 'It returned a Promise (is it an async function?).'));
68
+ }
69
+ if (!isStateObject(result)) {
70
+ throw new AdaptableStateOptionsError(`${syncFunctionMustReturnMessage(functionName)} It returned ${describe(result)}. ${docs}`);
71
+ }
72
+ return result;
73
+ }
74
+ export function runAsyncStateFunction(functionName, fn, args, logger) {
75
+ if (typeof fn !== 'function') {
76
+ return Promise.reject(new AdaptableStateOptionsError(`stateOptions.${functionName} must be a function, but received ${describe(fn)}. ${docs}`));
77
+ }
78
+ let result;
79
+ try {
80
+ result = fn(...args);
81
+ }
82
+ catch (error) {
83
+ return Promise.reject(error);
84
+ }
85
+ if (!isThenable(result)) {
86
+ logger.consoleWarn(`stateOptions.${functionName} should be asynchronous and return a Promise, but it returned ${describe(result)}. The value is used as if it had been resolved. ${docs}`);
87
+ return Promise.resolve(result);
88
+ }
89
+ return Promise.resolve(result);
90
+ }
91
+ function describe(value) {
92
+ if (value === null) {
93
+ return 'null';
94
+ }
95
+ if (value === undefined) {
96
+ return 'undefined';
97
+ }
98
+ if (Array.isArray(value)) {
99
+ return 'an array';
100
+ }
101
+ if (isThenable(value)) {
102
+ return 'a Promise';
103
+ }
104
+ const type = typeof value;
105
+ if (type === 'object') {
106
+ return 'an object';
107
+ }
108
+ if (type === 'string') {
109
+ return `a string ('${String(value).slice(0, 40)}${String(value).length > 40 ? '…' : ''}')`;
110
+ }
111
+ return `${type} (${String(value)})`;
112
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Whether a Redux action only affects transient (non-persisted) Adaptable state,
3
+ * e.g. showing a popup, highlighting cells or setting the selected rows.
4
+ */
5
+ export declare function isTransientReduxAction(actionType: string | undefined): boolean;
@@ -0,0 +1,19 @@
1
+ import * as CommentsRedux from '../ActionsReducers/CommentsRedux';
2
+ import * as InternalRedux from '../ActionsReducers/InternalRedux';
3
+ import * as PluginsRedux from '../ActionsReducers/PluginsRedux';
4
+ import * as PopupRedux from '../ActionsReducers/PopupRedux';
5
+ const collectActionTypes = (reduxModule) => {
6
+ return Object.values(reduxModule).filter((value) => typeof value === 'string');
7
+ };
8
+ const TRANSIENT_REDUX_ACTION_TYPES = new Set([
9
+ ...collectActionTypes(InternalRedux),
10
+ ...collectActionTypes(PopupRedux),
11
+ ...collectActionTypes(PluginsRedux),
12
+ ...collectActionTypes(CommentsRedux),
13
+ ]);
14
+ export function isTransientReduxAction(actionType) {
15
+ if (!actionType) {
16
+ return false;
17
+ }
18
+ return TRANSIENT_REDUX_ACTION_TYPES.has(actionType);
19
+ }
@@ -16,3 +16,4 @@ export declare const AgGridModulesDocsLink = "https://www.adaptabletools.com/doc
16
16
  export declare const AlertMessageDocsLink = "https://www.adaptabletools.com/docs/handbook-alerting-message";
17
17
  export declare const FormatColumnPlaceholderDocsLink = "https://www.adaptabletools.com/docs/handbook-column-formatting-display-format-template";
18
18
  export declare const AgGridRequiredModulesDocsLink = "https://www.adaptabletools.com/docs/getting-started-aggrid-modules#mandatory-modules";
19
+ export declare const StatePersistenceDocsLink = "https://www.adaptabletools.com/docs/dev-guide-adaptable-state-persistence";
@@ -16,3 +16,4 @@ export const AgGridModulesDocsLink = `${HOST_URL_DOCS}/getting-started-aggrid-mo
16
16
  export const AlertMessageDocsLink = `${HOST_URL_DOCS}/handbook-alerting-message`;
17
17
  export const FormatColumnPlaceholderDocsLink = `${HOST_URL_DOCS}/handbook-column-formatting-display-format-template`;
18
18
  export const AgGridRequiredModulesDocsLink = `${HOST_URL_DOCS}/getting-started-aggrid-modules#mandatory-modules`;
19
+ export const StatePersistenceDocsLink = `${HOST_URL_DOCS}/dev-guide-adaptable-state-persistence`;
@@ -2,8 +2,8 @@ import { SummaryOperation } from '../../AdaptableState/Common/Enums';
2
2
  import { SystemThemeEntry } from '../../AdaptableState/ThemeState';
3
3
  export declare const CELL_SUMMARY_DEFAULT_OPERATION: SummaryOperation | string;
4
4
  export declare const QUICK_SEARCH_DEFAULT_TEXT_BACK_COLOR: string;
5
- export declare const QUICK_SEARCH_DEFAULT_CELL_BACK_COLOR: string;
6
- export declare const QUICK_SEARCH_DEFAULT_FORE_COLOR: string;
5
+ export declare const QUICK_SEARCH_DEFAULT_TEXT_FORE_COLOR: string;
7
6
  export declare const QUICK_SEARCH_DEFAULT_CURRENT_BACK_COLOR: string;
7
+ export declare const QUICK_SEARCH_DEFAULT_CURRENT_FORE_COLOR: string;
8
8
  export declare const SYSTEM_THEMES: SystemThemeEntry[];
9
9
  export declare const THEME_DEFAULT_CURRENT_THEME: string;
@@ -1,10 +1,10 @@
1
1
  import { SummaryOperation } from '../../AdaptableState/Common/Enums';
2
- import { getSwatchColorVar } from '../../Utilities/Helpers/UIHelper';
2
+ import { themeColorVar } from '../../Utilities/Helpers/UIHelper';
3
3
  import { LIGHT_THEME, DARK_THEME, OS_THEME } from './GeneralConstants';
4
4
  export const CELL_SUMMARY_DEFAULT_OPERATION = SummaryOperation.Sum;
5
- export const QUICK_SEARCH_DEFAULT_TEXT_BACK_COLOR = getSwatchColorVar(9);
6
- export const QUICK_SEARCH_DEFAULT_CELL_BACK_COLOR = getSwatchColorVar(10);
7
- export const QUICK_SEARCH_DEFAULT_FORE_COLOR = getSwatchColorVar(1);
8
- export const QUICK_SEARCH_DEFAULT_CURRENT_BACK_COLOR = getSwatchColorVar(20);
5
+ export const QUICK_SEARCH_DEFAULT_TEXT_BACK_COLOR = themeColorVar('quick-search-match');
6
+ export const QUICK_SEARCH_DEFAULT_TEXT_FORE_COLOR = themeColorVar('quick-search-match-foreground');
7
+ export const QUICK_SEARCH_DEFAULT_CURRENT_BACK_COLOR = themeColorVar('quick-search-current-match');
8
+ export const QUICK_SEARCH_DEFAULT_CURRENT_FORE_COLOR = themeColorVar('quick-search-current-match-foreground');
9
9
  export const SYSTEM_THEMES = [LIGHT_THEME, DARK_THEME, OS_THEME];
10
10
  export const THEME_DEFAULT_CURRENT_THEME = LIGHT_THEME;
@@ -31,4 +31,4 @@ export declare const inferAlertTypeFromDefinition: (alert: AlertDefinition, kind
31
31
  * otherwise inferred from Rule / Schedule shape.
32
32
  */
33
33
  export declare const getAlertType: (alert: AlertDefinition, kind?: ExpressionKind) => AlertType | null;
34
- export declare const getAlertTypeText: (alertType: AlertType) => "" | "Aggregation" | "Observable" | "Scheduled" | "Data Change" | "Relative Change" | "Data Validation" | "Row Change";
34
+ export declare const getAlertTypeText: (alertType: AlertType) => "" | "Observable" | "Aggregation" | "Scheduled" | "Data Change" | "Relative Change" | "Data Validation" | "Row Change";
@@ -1,6 +1,15 @@
1
1
  import { AdaptableApi } from '../../Api/AdaptableApi';
2
2
  import { SettingsPanelDisplayOptions, SettingsPanelNavigation, SettingsPanelNavigationGroup, SettingsPanelOptions } from '../../AdaptableOptions/SettingsPanelOptions';
3
3
  import { AdaptableIcon } from '../../types';
4
+ /** One Settings Panel sidebar module (visible for the current grid / entitlements). */
5
+ export type VisibleSettingsPanelNavigationItem = {
6
+ moduleName: string;
7
+ label: string;
8
+ };
9
+ export type VisibleSettingsPanelNavigationGroup = {
10
+ label: string;
11
+ items: VisibleSettingsPanelNavigationItem[];
12
+ };
4
13
  /**
5
14
  * True when `adaptableId` is the framework placeholder (`adaptable_id` or `adaptable_id_<n>`),
6
15
  * not a developer-supplied human name.
@@ -41,3 +50,8 @@ export declare const getSettingsPanelOpenIcon: (resolvedIcon: SettingsPanelOptio
41
50
  export declare const DEFAULT_SETTINGS_PANEL_NAVIGATION_GROUPS: SettingsPanelNavigationGroup[];
42
51
  export declare const buildDefaultSettingsPanelNavigation: (customPanelNames?: string[]) => SettingsPanelNavigation;
43
52
  export declare const resolveSettingsPanelNavigation: (api: AdaptableApi, settingsPanelOptions: SettingsPanelOptions) => SettingsPanelNavigation;
53
+ /**
54
+ * Settings Panel navigation groups containing only modules that appear in the
55
+ * panel sidebar (same rules as {@link useMenuItems} in AdaptablePopup).
56
+ */
57
+ export declare function resolveVisibleSettingsPanelNavigationGroups(api: AdaptableApi): VisibleSettingsPanelNavigationGroup[];
@@ -1,4 +1,4 @@
1
- import { ADAPTABLE_ID } from '../Constants/GeneralConstants';
1
+ import { ADAPTABLE_ID, STANDALONE_MODULE_POPUPS } from '../Constants/GeneralConstants';
2
2
  import { SettingsPanelFriendlyName } from '../Constants/ModuleConstants';
3
3
  import StringExtensions from '../Extensions/StringExtensions';
4
4
  export const isGenericAdaptableId = (adaptableId) => {
@@ -143,3 +143,39 @@ export const resolveSettingsPanelNavigation = (api, settingsPanelOptions) => {
143
143
  warnLegacyNavigationOnce(api);
144
144
  return convertLegacyFlatNavigationToGrouped(navigation);
145
145
  };
146
+ export function resolveVisibleSettingsPanelNavigationGroups(api) {
147
+ const settingsPanelOptions = api.optionsApi.getAdaptableOptions().settingsPanelOptions;
148
+ const navigation = resolveSettingsPanelNavigation(api, settingsPanelOptions ?? {});
149
+ const allMenuItems = api.internalApi.getInternalState().SettingsPanelModuleEntries ?? [];
150
+ const visibleItems = allMenuItems.filter((item) => item.category !== 'General' &&
151
+ item.category !== 'CustomSettingsPanel' &&
152
+ item.category !== 'Group' &&
153
+ !STANDALONE_MODULE_POPUPS.includes(item.category) &&
154
+ item.isVisible);
155
+ const moduleService = api.internalApi.getModuleService();
156
+ const groups = [];
157
+ for (const group of navigation.groups) {
158
+ const items = [];
159
+ for (const moduleName of group.items) {
160
+ const moduleId = String(moduleName);
161
+ const customSettingsPanel = settingsPanelOptions?.customSettingsPanels?.find((panel) => panel.name === moduleId);
162
+ if (customSettingsPanel) {
163
+ items.push({ moduleName: moduleId, label: customSettingsPanel.name });
164
+ continue;
165
+ }
166
+ const menuItem = visibleItems.find((item) => item.category === moduleId);
167
+ if (!menuItem) {
168
+ continue;
169
+ }
170
+ items.push({
171
+ moduleName: moduleId,
172
+ label: menuItem.label ??
173
+ moduleService.getModuleFriendlyName(moduleId),
174
+ });
175
+ }
176
+ if (items.length) {
177
+ groups.push({ label: group.label ?? '', items });
178
+ }
179
+ }
180
+ return groups;
181
+ }
@@ -6,10 +6,12 @@ import { Schedule, Weekday } from '../../AdaptableState/Common/Schedule';
6
6
  import { AdaptableColumnDataType, AdaptableSystemIconName } from '../../types';
7
7
  import { AdaptableAlert } from '../../AdaptableState/Common/AdaptableAlert';
8
8
  import { AdaptableMessageType } from '../../AdaptableState/Common/AdaptableMessageType';
9
+ /** A theme colour token as a CSS value: `themeColorVar('badge')` → `var(--ab-color-badge)`. */
10
+ export declare function themeColorVar(token: string): string;
9
11
  /** Generic swatch entries for the Colour Picker (resolved at runtime per active theme). */
10
12
  export declare function getSwatchColorVar(index: number): string;
11
- /** Default mid-gray from the theme swatch palette (`--ab-color-swatch-4`). */
12
- export declare function getGraySwatchColor(): string;
13
+ /** Default colour of a new range in Range Bar, Bullet and Ranges styled columns. */
14
+ export declare function getDefaultRangeColor(): string;
13
15
  export declare function getSwatchColorPaletteEntries(): string[];
14
16
  /** Theme semantic colours for the Colour Picker (resolved at runtime per active theme). */
15
17
  export declare function getThemeSemanticColorPaletteEntries(): string[];
@@ -41,8 +43,9 @@ export declare function getCSSVariableValue(cssVariable: string): string | undef
41
43
  export declare function setCSSVariableValue(cssVariable: string, value: string): void;
42
44
  export declare function isBrowserDocumentAvailable(): boolean;
43
45
  export declare const UIHelper: {
46
+ themeColorVar: typeof themeColorVar;
44
47
  getSwatchColorVar: typeof getSwatchColorVar;
45
- getGraySwatchColor: typeof getGraySwatchColor;
48
+ getDefaultRangeColor: typeof getDefaultRangeColor;
46
49
  getSwatchColorPaletteEntries: typeof getSwatchColorPaletteEntries;
47
50
  getThemeSemanticColorPaletteEntries: typeof getThemeSemanticColorPaletteEntries;
48
51
  getDefaultColorPalette: typeof getDefaultColorPalette;
@@ -3,11 +3,14 @@ import { FontWeight, FontStyle, StatusColour } from '../../AdaptableState/Common
3
3
  import { StringExtensions } from '../Extensions/StringExtensions';
4
4
  import { getScheduleDescription as getScheduleDescriptionFromHelper } from './Scheduling/ScheduleHelper';
5
5
  import ArrayExtensions from '../Extensions/ArrayExtensions';
6
+ export function themeColorVar(token) {
7
+ return `var(--ab-color-${token})`;
8
+ }
6
9
  export function getSwatchColorVar(index) {
7
- return `var(--ab-color-swatch-${index})`;
10
+ return themeColorVar(`swatch-${index}`);
8
11
  }
9
- export function getGraySwatchColor() {
10
- return getSwatchColorVar(4);
12
+ export function getDefaultRangeColor() {
13
+ return themeColorVar('range-default');
11
14
  }
12
15
  export function getSwatchColorPaletteEntries() {
13
16
  return Array.from({ length: 20 }, (_, i) => getSwatchColorVar(i + 1));
@@ -324,8 +327,9 @@ export function isBrowserDocumentAvailable() {
324
327
  return typeof window !== 'undefined' && typeof window.document !== 'undefined';
325
328
  }
326
329
  export const UIHelper = {
330
+ themeColorVar,
327
331
  getSwatchColorVar,
328
- getGraySwatchColor,
332
+ getDefaultRangeColor,
329
333
  getSwatchColorPaletteEntries,
330
334
  getThemeSemanticColorPaletteEntries,
331
335
  getDefaultColorPalette,
@@ -4,7 +4,7 @@ import { buildCronExpression } from './Helpers/Scheduling/ScheduleHelper';
4
4
  import { EMPTY_STRING } from './Constants/GeneralConstants';
5
5
  import { ALERT_DEFAULT_MESSAGE_TYPE, ALERT_DEFAULT_SHOW_POPUP, PLUS_MINUS_DEFAULT_NUDGE_VALUE, } from './Constants/ObjectDefaultConstants';
6
6
  import { Bounce, Flip, Slide, Zoom } from '../components/Toastify';
7
- import { getSwatchColorVar } from './Helpers/UIHelper';
7
+ import { themeColorVar } from './Helpers/UIHelper';
8
8
  import { isPivotLayout } from './Helpers/Layouts/LayoutHelper';
9
9
  export function CreateEmptyCustomSort() {
10
10
  return { Uuid: createUuid(), Name: EMPTY_STRING, ColumnId: EMPTY_STRING, SortedValues: [] };
@@ -250,8 +250,8 @@ export function CreateDefaultStyledColumnBadge() {
250
250
  return {
251
251
  Shape: 'Rounded',
252
252
  PillStyle: {
253
- BackColor: getSwatchColorVar(3),
254
- ForeColor: getSwatchColorVar(1),
253
+ BackColor: themeColorVar('badge'),
254
+ ForeColor: themeColorVar('badge-foreground'),
255
255
  },
256
256
  };
257
257
  }
@@ -61,5 +61,5 @@ export const DashboardPopupSections = (props) => {
61
61
  return (_jsxs(Flex, { flexWrap: "wrap", alignItems: "center", className: "twa:gap-1", children: [_jsxs(Tag, { children: ["Tab: ", tab.Name] }), toolbarTitles.map((title, index) => (_jsx(Tag, { children: title }, `${tab.Name}-${title}-${index}`)))] }, tab.Uuid ?? tab.Name));
62
62
  }) })) : (_jsx(Tag, { children: "No Tabs Configured" }));
63
63
  const moduleButtonsSummary = moduleButtonLabels.length > 0 ? (_jsx(Flex, { flexWrap: "wrap", alignItems: "center", className: "twa:gap-1", children: moduleButtonLabels.map((label) => (_jsx(Tag, { children: label }, label))) })) : (_jsx(Tag, { children: "No Module Buttons" }));
64
- return (_jsxs(Flex, { flexDirection: "column", className: "twa:h-full twa:min-h-0 twa:gap-3 twa:overflow-y-auto", children: [props.areDashboardSettingsVisible && (_jsx(CollapsibleWizardCard, { ...bindCard('settings'), "data-name": "dashboard-settings", title: "Settings", help: "Control Dashboard visibility, expansion and floating mode", compactSummary: settingsToggles, compactSummaryInteractive: true, summary: settingsToggles, className: "twa:overflow-hidden", children: settingsToggles })), _jsx(CollapsibleWizardCard, { ...bindCard('pinned-toolbars'), "data-name": "dashboard-pinned-toolbars", title: "Pinned Toolbars", help: "Optional strip along the top of the grid \u2014 pin Toolbars you want always visible (e.g. Grid Filter)", compactSummary: renderCompactAccentTags(pinnedToolbarTitles, (title) => title, { emptyLabel: 'No Pinned Toolbars' }), summary: pinnedSummary, className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[200px] twa:overflow-hidden", children: _jsx(PinnedToolbarsSelector, {}) }), _jsx(CollapsibleWizardCard, { ...bindCard('tabs-toolbars'), "data-name": "dashboard-tabs-toolbars", title: "Tabs & Toolbars", help: "Group Toolbars into named Tabs in the Dashboard header (independent of Pinned Toolbars)", compactSummary: renderCompactAccentTags(tabsCompactLabels, (label) => label, { emptyLabel: 'No Tabs Configured' }), summary: tabsSummary, className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[280px] twa:overflow-hidden", children: _jsx(DashboardManagerUI, { disabled: props.isDashboardDisabled, availableToolbars: [...systemToolbars, ...customToolbars], tabs: tabs, onTabsChange: props.onDashboardSetTabs, api: api }) }), _jsx(CollapsibleWizardCard, { ...bindCard('module-buttons', { fillAvailable: true }), "data-name": "dashboard-module-buttons", title: "Module Buttons", help: "Buttons in the Dashboard header that open Module settings", compactSummary: renderCompactAccentTags(moduleButtonLabels, (label) => label, { emptyLabel: 'No Module Buttons' }), summary: moduleButtonsSummary, className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[240px] twa:overflow-hidden twa:flex twa:flex-col twa:!pt-0 twa:!pb-0 twa:px-1", children: _jsx(ModuleValueSelector, { disabled: props.isDashboardDisabled, options: allModuleButtons, value: selectedModuleButtons, onChange: (selectedValues) => props.onDashboardSetModuleButtons(selectedValues) }) })] }));
64
+ return (_jsxs(Flex, { flexDirection: "column", className: "twa:h-full twa:min-h-0 twa:gap-3 twa:overflow-y-auto", children: [props.areDashboardSettingsVisible && (_jsx(CollapsibleWizardCard, { "data-name": "dashboard-settings", title: "Settings", help: "Control Dashboard visibility, expansion and floating mode", summary: settingsToggles, collapsible: false, className: "twa:overflow-hidden" })), _jsx(CollapsibleWizardCard, { ...bindCard('pinned-toolbars'), "data-name": "dashboard-pinned-toolbars", title: "Pinned Toolbars", help: "Optional strip along the top of the grid \u2014 pin Toolbars you want always visible (e.g. Grid Filter)", compactSummary: renderCompactAccentTags(pinnedToolbarTitles, (title) => title, { emptyLabel: 'No Pinned Toolbars' }), summary: pinnedSummary, className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[200px] twa:overflow-hidden", children: _jsx(PinnedToolbarsSelector, {}) }), _jsx(CollapsibleWizardCard, { ...bindCard('tabs-toolbars'), "data-name": "dashboard-tabs-toolbars", title: "Tabs & Toolbars", help: "Group Toolbars into named Tabs in the Dashboard header (independent of Pinned Toolbars)", compactSummary: renderCompactAccentTags(tabsCompactLabels, (label) => label, { emptyLabel: 'No Tabs Configured' }), summary: tabsSummary, className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[280px] twa:overflow-hidden", children: _jsx(DashboardManagerUI, { disabled: props.isDashboardDisabled, availableToolbars: [...systemToolbars, ...customToolbars], tabs: tabs, onTabsChange: props.onDashboardSetTabs, api: api }) }), _jsx(CollapsibleWizardCard, { ...bindCard('module-buttons', { fillAvailable: true }), "data-name": "dashboard-module-buttons", title: "Module Buttons", help: "Buttons in the Dashboard header that open Module settings", compactSummary: renderCompactAccentTags(moduleButtonLabels, (label) => label, { emptyLabel: 'No Module Buttons' }), summary: moduleButtonsSummary, className: "twa:overflow-hidden twa:flex twa:flex-col", bodyClassName: "twa:min-h-[240px] twa:overflow-hidden twa:flex twa:flex-col twa:!pt-0 twa:!pb-0 twa:px-1", children: _jsx(ModuleValueSelector, { disabled: props.isDashboardDisabled, options: allModuleButtons, value: selectedModuleButtons, onChange: (selectedValues) => props.onDashboardSetModuleButtons(selectedValues) }) })] }));
65
65
  };