@adaptabletools/adaptable 19.0.5 → 19.1.0-canary.0

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 (33) hide show
  1. package/package.json +2 -2
  2. package/src/AdaptableInterfaces/IAdaptable.d.ts +3 -0
  3. package/src/Api/ColumnApi.d.ts +9 -0
  4. package/src/Api/Implementation/ColumnApiImpl.d.ts +2 -0
  5. package/src/Api/Implementation/ColumnApiImpl.js +11 -3
  6. package/src/Api/Implementation/ConfigApiImpl.js +1 -0
  7. package/src/Api/Implementation/FlashingCellApiImpl.js +8 -6
  8. package/src/Api/Internal/ActionRowInternalApi.js +1 -1
  9. package/src/Api/Internal/AdaptableInternalApi.d.ts +2 -0
  10. package/src/Api/Internal/AdaptableInternalApi.js +4 -1
  11. package/src/Api/Internal/ColumnInternalApi.d.ts +0 -1
  12. package/src/Api/Internal/ColumnInternalApi.js +1 -4
  13. package/src/Api/Internal/FlashingCellInternalApi.js +4 -2
  14. package/src/PredefinedConfig/SystemState.d.ts +0 -6
  15. package/src/Redux/ActionsReducers/SystemRedux.d.ts +1 -17
  16. package/src/Redux/ActionsReducers/SystemRedux.js +0 -59
  17. package/src/Redux/Store/AdaptableStore.js +1 -19
  18. package/src/Strategy/FlashingCellModule.d.ts +2 -3
  19. package/src/Strategy/FlashingCellModule.js +6 -3
  20. package/src/Utilities/Services/FlashingCellService.d.ts +21 -0
  21. package/src/Utilities/Services/FlashingCellService.js +65 -0
  22. package/src/View/AdaptableWizardView/AdaptableConfigurationDialog/GridOptionsForm.js +3 -3
  23. package/src/View/AdaptableWizardView/helper.js +1 -1
  24. package/src/View/Components/NewScopeComponent.js +1 -1
  25. package/src/View/Components/Popups/AdaptablePopup/CustomSettingsPanelView.js +1 -1
  26. package/src/View/DataChangeHistory/DataChangeHistoryGrid.js +1 -1
  27. package/src/View/FlashingCell/Wizard/FlashingCellScopeWizardSection.js +2 -1
  28. package/src/agGrid/ActionColumnRenderer.js +2 -2
  29. package/src/agGrid/AdaptableAgGrid.d.ts +5 -2
  30. package/src/agGrid/AdaptableAgGrid.js +37 -25
  31. package/src/agGrid/AgGridAdapter.js +1 -1
  32. package/src/env.js +2 -2
  33. package/tsconfig.esm.tsbuildinfo +1 -1
@@ -61,7 +61,7 @@ export const NewScopeComponent = (props) => {
61
61
  const { columnScopeApi: scopeApi, columnApi } = api;
62
62
  const [columnsSearchText, setColumnsSearchText] = useState('');
63
63
  const scopeColumns = React.useMemo(() => {
64
- const allColumns = props.scopeColumns || columnApi.getColumns();
64
+ const allColumns = props.scopeColumns || columnApi.getStandardColumns();
65
65
  if (typeof props.isColumnAvailable === 'function') {
66
66
  return allColumns.filter((c) => props.isColumnAvailable(c));
67
67
  }
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { ExternalRenderer } from '../../ExternalRenderer';
3
3
  export const CustomSettingsPanelView = (props) => {
4
- return (React.createElement(ExternalRenderer, { render: props.settingsPanel.render, componentName: props.settingsPanel.name, frameworkComponent: props.settingsPanel.frameworkComponent }));
4
+ return (React.createElement(ExternalRenderer, { key: props.settingsPanel.name, render: props.settingsPanel.render, componentName: props.settingsPanel.name, frameworkComponent: props.settingsPanel.frameworkComponent }));
5
5
  };
@@ -268,7 +268,7 @@ const buildGridOptions = (mainAdaptableInstance, changeHistoryLog) => {
268
268
  },
269
269
  ],
270
270
  rowData: mapChangeHistoryRowData(changeHistoryLog, mainAdaptableInstance),
271
- enableRangeSelection: true,
271
+ cellSelection: true,
272
272
  suppressColumnVirtualisation: false,
273
273
  sideBar: false,
274
274
  rowSelection: 'multiple',
@@ -4,11 +4,12 @@ import { NewScopeComponent } from '../../Components/NewScopeComponent';
4
4
  import { useOnePageAdaptableWizardContext } from '../../Wizard/OnePageAdaptableWizard';
5
5
  export const FlashingAlertScopeWizardSection = (props) => {
6
6
  const { data, api } = useOnePageAdaptableWizardContext();
7
+ const availableColumns = React.useMemo(() => api.columnApi.getNonSpecialColumns(), []);
7
8
  return (React.createElement(Flex, { flexDirection: "column", style: { height: '100%' }, padding: 2 },
8
9
  React.createElement(NewScopeComponent, { descriptions: {
9
10
  rowScope: 'Changes anywhere in the row will trigger an Flashing Cell',
10
11
  columnScope: 'Changes in selected columns will trigger an Flashing Cell',
11
- }, scope: data.Scope, updateScope: (Scope) => {
12
+ }, scopeColumns: availableColumns, scope: data.Scope, updateScope: (Scope) => {
12
13
  const newData = Object.assign(Object.assign({}, data), { Scope });
13
14
  if (newData.Rule.Predicates) {
14
15
  // when scope is changed, reset the rule to predicate of AnyChange
@@ -47,7 +47,7 @@ export const ReactActionColumnRenderer = (props) => {
47
47
  const isGroupedRow = adaptable.api.gridApi.isGroupRowNode(props.node);
48
48
  const isSummaryRow = adaptable.api.gridApi.isSummaryNode(props.node);
49
49
  let shouldRender = true;
50
- const isActionRowColumn = adaptable.api.columnApi.internalApi.isActionRowButtonColumn(props.colDef.colId);
50
+ const isActionRowColumn = adaptable.api.columnApi.isActionRowButtonColumn(props.colDef.colId);
51
51
  if (isGroupedRow) {
52
52
  if (isActionRowColumn || ((_a = actionColumn.rowScope) === null || _a === void 0 ? void 0 : _a.ExcludeGroupRows)) {
53
53
  shouldRender = false;
@@ -105,7 +105,7 @@ export class ActionColumnRenderer {
105
105
  const isGroupedRow = adaptable.api.gridApi.isGroupRowNode(params.node);
106
106
  const isSummaryRow = adaptable.api.gridApi.isSummaryNode(params.node);
107
107
  let shouldRender = true;
108
- const isActionRowColumn = adaptable.api.columnApi.internalApi.isActionRowButtonColumn(params.colDef.colId);
108
+ const isActionRowColumn = adaptable.api.columnApi.isActionRowButtonColumn(params.colDef.colId);
109
109
  if (isGroupedRow) {
110
110
  if (isActionRowColumn || ((_a = actionColumn.rowScope) === null || _a === void 0 ? void 0 : _a.ExcludeGroupRows)) {
111
111
  shouldRender = false;
@@ -26,6 +26,7 @@ import { RenderReactRootFn } from '../renderReactRoot';
26
26
  import { AgGridOptionsService } from './AgGridOptionsService';
27
27
  import { AgGridColumnAdapter } from './AgGridColumnAdapter';
28
28
  import { RowEditService } from '../Utilities/Services/RowEditService';
29
+ import { FlashingCellService } from '../Utilities/Services/FlashingCellService';
29
30
  export type AdaptableLifecycleState = 'initial' | 'preprocessOptions' | 'initAdaptableState' | 'setupAgGrid' | 'initAgGrid' | 'agGridReady' | 'available' | 'ready' | 'preDestroyed';
30
31
  type RenderAgGridFrameworkComponentResult = false | GridApi;
31
32
  interface AdaptableInitInternalConfig<TData = any> {
@@ -83,6 +84,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
83
84
  RowEditService: RowEditService;
84
85
  Fdc3Service: Fdc3Service;
85
86
  CellPopupService: CellPopupService;
87
+ FlashingCellService: FlashingCellService;
86
88
  private LicenseService;
87
89
  private ChartingService;
88
90
  private ThemeService;
@@ -106,7 +108,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
106
108
  private listenerPivotChanged;
107
109
  private listenerColumnRowGroupChanged;
108
110
  private listenerColumnResized;
109
- private listenerRangeSelectionChanged;
111
+ private listenerCellSelectionChanged;
110
112
  private listenerSortChanged;
111
113
  private listenerModelUpdated;
112
114
  private columnMinMaxValuesCache;
@@ -162,7 +164,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
162
164
  private enhanceColDefsWithSpecialColumns;
163
165
  useRowNodeLookUp(): boolean;
164
166
  getAgGridContainerElement(): HTMLElement | null;
165
- getAdaptableContainerElement(): HTMLElement | null;
167
+ getAdaptableContainerElement(): HTMLElement;
166
168
  refreshSelectedCellsState(): SelectedCellInfo | undefined;
167
169
  refreshSelectedRowsState(): SelectedRowInfo | undefined;
168
170
  isGridRowSelectable(): boolean;
@@ -204,6 +206,7 @@ export declare class AdaptableAgGrid implements IAdaptable {
204
206
  redrawRows(rowNodes?: IRowNode[]): void;
205
207
  redrawRow(rowNode: IRowNode): void;
206
208
  refreshCells(rowNodes: IRowNode[], columns: (string | Column)[], forceUpdate: boolean, suppressFlash?: boolean): void;
209
+ refreshAllCells(forceUpdate?: boolean): void;
207
210
  refreshColumns(columns: (string | Column)[], forceUpdate: boolean, suppressFlash?: boolean): void;
208
211
  jumpToRow(rowNode: IRowNode): void;
209
212
  jumpToColumn(columnId: string): void;
@@ -93,6 +93,7 @@ import { createElement } from 'react';
93
93
  import { removeUuidAndSource } from '../Utilities/Helpers/AdaptableHelper';
94
94
  import { buildSortedColumnStateForLayout } from './buildSortedColumnStateForLayout';
95
95
  import { ROW_SUMMARY_ROW_ID } from '../PredefinedConfig/Common/RowSummary';
96
+ import { FlashingCellService } from '../Utilities/Services/FlashingCellService';
96
97
  const LocalEventService_Prototype = LocalEventService.prototype;
97
98
  const LocalEventService_dispatchEvent = LocalEventService_Prototype.dispatchEvent;
98
99
  const GridOptionsService_updateGridOptions = GridOptionsService.prototype.updateGridOptions;
@@ -1193,20 +1194,22 @@ export class AdaptableAgGrid {
1193
1194
  return this.agGridAdapter.getAgGridApi().getGridOption('getRowId') != undefined;
1194
1195
  }
1195
1196
  getAgGridContainerElement() {
1197
+ var _a, _b, _c, _d, _e, _f;
1196
1198
  if (!this.DANGER_USE_GETTER_agGridContainerElement) {
1197
1199
  this.DANGER_USE_GETTER_agGridContainerElement =
1198
- typeof this.adaptableOptions.containerOptions.agGridContainer === 'string'
1199
- ? document.getElementById(this.adaptableOptions.containerOptions.agGridContainer)
1200
- : this.adaptableOptions.containerOptions.agGridContainer;
1200
+ typeof ((_b = (_a = this.adaptableOptions) === null || _a === void 0 ? void 0 : _a.containerOptions) === null || _b === void 0 ? void 0 : _b.agGridContainer) === 'string'
1201
+ ? document.getElementById((_d = (_c = this.adaptableOptions) === null || _c === void 0 ? void 0 : _c.containerOptions) === null || _d === void 0 ? void 0 : _d.agGridContainer)
1202
+ : (_f = (_e = this.adaptableOptions) === null || _e === void 0 ? void 0 : _e.containerOptions) === null || _f === void 0 ? void 0 : _f.agGridContainer;
1201
1203
  }
1202
1204
  return this.DANGER_USE_GETTER_agGridContainerElement;
1203
1205
  }
1204
1206
  getAdaptableContainerElement() {
1207
+ var _a, _b, _c, _d, _e, _f;
1205
1208
  if (!this.DANGER_USE_GETTER_adaptableContainerElement) {
1206
1209
  this.DANGER_USE_GETTER_adaptableContainerElement =
1207
- typeof this.adaptableOptions.containerOptions.adaptableContainer === 'string'
1208
- ? document.getElementById(this.adaptableOptions.containerOptions.adaptableContainer)
1209
- : this.adaptableOptions.containerOptions.adaptableContainer;
1210
+ typeof ((_b = (_a = this.adaptableOptions) === null || _a === void 0 ? void 0 : _a.containerOptions) === null || _b === void 0 ? void 0 : _b.adaptableContainer) === 'string'
1211
+ ? document.getElementById((_d = (_c = this.adaptableOptions) === null || _c === void 0 ? void 0 : _c.containerOptions) === null || _d === void 0 ? void 0 : _d.adaptableContainer)
1212
+ : (_f = (_e = this.adaptableOptions) === null || _e === void 0 ? void 0 : _e.containerOptions) === null || _f === void 0 ? void 0 : _f.adaptableContainer;
1210
1213
  }
1211
1214
  return this.DANGER_USE_GETTER_adaptableContainerElement;
1212
1215
  }
@@ -1235,11 +1238,21 @@ export class AdaptableAgGrid {
1235
1238
  }
1236
1239
  isGridRowSelectable() {
1237
1240
  const rowSelection = this.agGridAdapter.getAgGridApi().getGridOption('rowSelection');
1238
- return rowSelection === 'single' || rowSelection === 'multiple';
1241
+ if (rowSelection == undefined) {
1242
+ return false;
1243
+ }
1244
+ if (rowSelection === 'single' || rowSelection === 'multiple') {
1245
+ return true;
1246
+ }
1247
+ if (rowSelection.mode === 'singleRow' || rowSelection.mode === 'multiRow') {
1248
+ return true;
1249
+ }
1250
+ return false;
1239
1251
  }
1240
1252
  isGridRangeSelectable() {
1241
1253
  return (this.agGridAdapter.isModulePresent(ModuleNames.RangeSelectionModule) &&
1242
- this.agGridAdapter.getGridOption('enableRangeSelection'));
1254
+ (this.agGridAdapter.getGridOption('enableRangeSelection') ||
1255
+ !!this.agGridAdapter.getGridOption('cellSelection')));
1243
1256
  }
1244
1257
  initAdaptableStore() {
1245
1258
  const perfNewAdaptableStore = this.logger.beginPerf(`initAdaptableStore()`);
@@ -1388,7 +1401,6 @@ export class AdaptableAgGrid {
1388
1401
  const columnEventsThatTriggersStateChange = [
1389
1402
  'columnMoved',
1390
1403
  'gridColumnsChanged',
1391
- 'columnEverythingChanged',
1392
1404
  'displayedColumnsChanged',
1393
1405
  'columnVisible',
1394
1406
  'newColumnsLoaded',
@@ -1547,7 +1559,7 @@ export class AdaptableAgGrid {
1547
1559
  }
1548
1560
  this.refreshSelectedCellsState();
1549
1561
  }, 250);
1550
- this.agGridAdapter.getAgGridApi().addEventListener('rangeSelectionChanged', (this.listenerRangeSelectionChanged = (params) => {
1562
+ this.agGridAdapter.getAgGridApi().addEventListener('cellSelectionChanged', (this.listenerCellSelectionChanged = (params) => {
1551
1563
  if (params.finished == true) {
1552
1564
  this.debouncedSetSelectedCells();
1553
1565
  }
@@ -1665,6 +1677,7 @@ export class AdaptableAgGrid {
1665
1677
  this.TeamSharingService = new TeamSharingService(this.api);
1666
1678
  this.Fdc3Service = new Fdc3Service(this.api);
1667
1679
  this.CellPopupService = new CellPopupService(this.api);
1680
+ this.FlashingCellService = new FlashingCellService(this.api);
1668
1681
  this.RowEditService = new RowEditService(this.api);
1669
1682
  this.MetamodelService = new MetamodelService(() => this.api.optionsApi.getAdaptableOptions(), true);
1670
1683
  }
@@ -1988,6 +2001,9 @@ export class AdaptableAgGrid {
1988
2001
  };
1989
2002
  this.agGridAdapter.getAgGridApi().refreshCells(refreshCellParams);
1990
2003
  }
2004
+ refreshAllCells(forceUpdate) {
2005
+ this.agGridAdapter.getAgGridApi().refreshCells({ force: forceUpdate });
2006
+ }
1991
2007
  refreshColumns(columns, forceUpdate, suppressFlash) {
1992
2008
  this.refreshCells(null, columns, forceUpdate, suppressFlash);
1993
2009
  }
@@ -2003,7 +2019,7 @@ export class AdaptableAgGrid {
2003
2019
  }
2004
2020
  selectColumn(columnId, config) {
2005
2021
  if (!(config === null || config === void 0 ? void 0 : config.keepExistingSelection)) {
2006
- this.agGridAdapter.getAgGridApi().clearRangeSelection();
2022
+ this.agGridAdapter.getAgGridApi().clearCellSelection();
2007
2023
  }
2008
2024
  const cellRangeParams = {
2009
2025
  rowStartIndex: 0,
@@ -2015,7 +2031,7 @@ export class AdaptableAgGrid {
2015
2031
  }
2016
2032
  selectColumns(columnIds, config) {
2017
2033
  if (!(config === null || config === void 0 ? void 0 : config.keepExistingSelection)) {
2018
- this.agGridAdapter.getAgGridApi().clearRangeSelection();
2034
+ this.agGridAdapter.getAgGridApi().clearCellSelection();
2019
2035
  }
2020
2036
  const rowCount = this.agGridAdapter.getAgGridApi().getDisplayedRowCount();
2021
2037
  columnIds.forEach((colId) => {
@@ -2034,7 +2050,7 @@ export class AdaptableAgGrid {
2034
2050
  deselectAll() {
2035
2051
  // need to do both as first just clears selected rows and second clears ranges
2036
2052
  this.agGridAdapter.getAgGridApi().deselectAll();
2037
- this.agGridAdapter.getAgGridApi().clearRangeSelection();
2053
+ this.agGridAdapter.getAgGridApi().clearCellSelection();
2038
2054
  }
2039
2055
  setGridData(dataSource) {
2040
2056
  if (!this.isReady) {
@@ -2103,13 +2119,7 @@ export class AdaptableAgGrid {
2103
2119
  if (!rowNode) {
2104
2120
  return false;
2105
2121
  }
2106
- if (rowNode.isEmptyRowGroupNode()) {
2107
- return true;
2108
- }
2109
- if (rowNode.group && rowNode.group === true) {
2110
- return true;
2111
- }
2112
- if (rowNode.leafGroup && rowNode.leafGroup === true) {
2122
+ if (rowNode.group === true || rowNode.leafGroup === true) {
2113
2123
  return true;
2114
2124
  }
2115
2125
  return false;
@@ -2581,7 +2591,7 @@ export class AdaptableAgGrid {
2581
2591
  }
2582
2592
  selectCells(columnIds, startNode, endNode, clearSelection) {
2583
2593
  if (clearSelection) {
2584
- this.agGridAdapter.getAgGridApi().clearRangeSelection();
2594
+ this.agGridAdapter.getAgGridApi().clearCellSelection();
2585
2595
  }
2586
2596
  const cellRangeParams = {
2587
2597
  rowStartIndex: startNode.rowIndex,
@@ -2964,7 +2974,7 @@ export class AdaptableAgGrid {
2964
2974
  return this.agGridAdapter.getRegisteredModules();
2965
2975
  }
2966
2976
  destroy(config) {
2967
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
2977
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
2968
2978
  if (((_a = this.agGridAdapter) === null || _a === void 0 ? void 0 : _a.getAgGridApi()) && !this.agGridAdapter.getAgGridApi().isDestroyed()) {
2969
2979
  this.agGridAdapter
2970
2980
  .getAgGridApi()
@@ -2983,7 +2993,7 @@ export class AdaptableAgGrid {
2983
2993
  .removeEventListener('columnRowGroupChanged', this.listenerColumnRowGroupChanged);
2984
2994
  this.agGridAdapter
2985
2995
  .getAgGridApi()
2986
- .removeEventListener('rangeSelectionChanged', this.listenerRangeSelectionChanged);
2996
+ .removeEventListener('cellSelectionChanged', this.listenerCellSelectionChanged);
2987
2997
  this.agGridAdapter
2988
2998
  .getAgGridApi()
2989
2999
  .removeEventListener('columnResized', this.listenerColumnResized);
@@ -3008,7 +3018,7 @@ export class AdaptableAgGrid {
3008
3018
  this.listenerPivotChanged = null;
3009
3019
  this.listenerCellEditingStarted = null;
3010
3020
  this.listenerColumnRowGroupChanged = null;
3011
- this.listenerRangeSelectionChanged = null;
3021
+ this.listenerCellSelectionChanged = null;
3012
3022
  this.listenerColumnResized = null;
3013
3023
  this.listenerGlobalSetRowSelection = null;
3014
3024
  this.listenerSortChanged = null;
@@ -3078,10 +3088,10 @@ export class AdaptableAgGrid {
3078
3088
  AdaptableAgGrid.dismissInstance(this);
3079
3089
  (_g = this.unmountLoadingScreen) === null || _g === void 0 ? void 0 : _g.call(this);
3080
3090
  this.unmountLoadingScreen = null;
3081
- const abContainerElement = this.getAdaptableContainerElement();
3082
3091
  if (config && !config.unmount) {
3083
3092
  return;
3084
3093
  }
3094
+ const abContainerElement = this.getAdaptableContainerElement();
3085
3095
  if (abContainerElement != null) {
3086
3096
  (_h = this.unmountReactRoot) === null || _h === void 0 ? void 0 : _h.call(this);
3087
3097
  }
@@ -3114,6 +3124,8 @@ export class AdaptableAgGrid {
3114
3124
  this.MetamodelService = null;
3115
3125
  (_6 = (_5 = this.LicenseService) === null || _5 === void 0 ? void 0 : _5.destroy) === null || _6 === void 0 ? void 0 : _6.call(_5);
3116
3126
  this.LicenseService = null;
3127
+ (_8 = (_7 = this.FlashingCellService) === null || _7 === void 0 ? void 0 : _7.destroy) === null || _8 === void 0 ? void 0 : _8.call(_7);
3128
+ this.FlashingCellService = null;
3117
3129
  }
3118
3130
  canExportToExcel() {
3119
3131
  return this.agGridAdapter.isModulePresent(ModuleNames.ExcelExportModule);
@@ -218,7 +218,7 @@ export class AgGridAdapter {
218
218
  const isRealColumnGroup = ColumnGroup
219
219
  ? ColumnGroup.columnGroupId !== ColumnGroup.friendlyName
220
220
  : false;
221
- const isActionRowButtonColumn = this.adaptableInstance.api.columnApi.internalApi.isActionRowButtonColumn(colId);
221
+ const isActionRowButtonColumn = this.adaptableInstance.api.columnApi.isActionRowButtonColumn(colId);
222
222
  const isFdc3MainActionColumn = this.adaptableInstance.api.fdc3Api.internalApi.isFdc3MainActionColumn(colId);
223
223
  let friendlyName;
224
224
  const colExists = this.adaptableInstance.api.columnApi.doesColumnExist(ColumnId);
package/src/env.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export default {
2
2
  INFINITE_TABLE_LICENSE_KEY: "StartDate=2021-06-29|EndDate=2030-01-01|Owner=Adaptable|Type=distribution|TS=1624971462479|C=137829811,1004007071,2756196225,1839832928,3994409405,636616862" || '',
3
- PUBLISH_TIMESTAMP: 1728922220996 || Date.now(),
4
- VERSION: "19.0.5" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1730460284413 || Date.now(),
4
+ VERSION: "19.1.0-canary.0" || '--current-version--',
5
5
  };