@adaptabletools/adaptable 21.0.0-canary.3 → 21.0.0-canary.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adaptabletools/adaptable",
3
- "version": "21.0.0-canary.3",
3
+ "version": "21.0.0-canary.5",
4
4
  "description": "Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements",
5
5
  "keywords": [
6
6
  "web-components",
@@ -26,7 +26,7 @@ export interface FilterOptions<TData = any> {
26
26
  */
27
27
  clearFiltersOnStartUp?: boolean;
28
28
  /**
29
- * Provide custom values (or sorting / count info) when using the `In` Filter
29
+ * Provide custom values (or sorting / count info) when using `In` Predicate in Column or Grid Filter
30
30
  * @param context
31
31
  * @returns
32
32
  */
@@ -208,17 +208,16 @@ export interface InFilterValue<ValueType = any> {
208
208
  /**
209
209
  * Result when providing custom values for the IN Column Filter
210
210
  */
211
- export type InFilterValueResult = {
211
+ export interface InFilterValueResult {
212
212
  /**
213
213
  * List of Items to display in the IN Column Filter
214
214
  */
215
215
  values: InFilterValue[];
216
216
  /**
217
- * When TRUE, displays the provided values without any filtering.
218
- * When FALSE, the values are filtered based on the current search text.
217
+ * If true, AdapTable will not filter the list using the current search value
219
218
  */
220
219
  skipDefaultSearch?: boolean;
221
- };
220
+ }
222
221
  /**
223
222
  * Information about items in the IN Column Filter
224
223
  */
@@ -249,11 +248,11 @@ export interface CustomInFilterValuesContext<TData = any> extends AdaptableColum
249
248
  */
250
249
  defaultValues: Required<InFilterValueInfo>[];
251
250
  /**
252
- * Default values but Sorted based on Column's sort
251
+ * Default values but sorted (if Column is sorted)
253
252
  */
254
253
  sortedValues: Required<InFilterValueInfo>[];
255
254
  /**
256
- * Default values but in the order in which they are currently listed in the grid - (after all the sorting has been applied, or, if no sorting, in their natural order)
255
+ * Default values in order which currently listed in the grid
257
256
  */
258
257
  orderedValues: Required<InFilterValueInfo>[];
259
258
  /**
@@ -261,8 +260,7 @@ export interface CustomInFilterValuesContext<TData = any> extends AdaptableColum
261
260
  */
262
261
  currentSearchValue: string;
263
262
  /**
264
- * Memoized result from previous invocation. Helps avoid expensive recomputations,
265
- * especially for async operations (e.g. server-side filtering).
263
+ * Previous filter result; avoids expensive recomputations (e.g for async op or server-side filtering)
266
264
  */
267
265
  previousFilterResult?: InFilterValueResult;
268
266
  }
@@ -525,7 +525,7 @@ export class AlertInternalApi extends ApiBase {
525
525
  isValidExpression &&
526
526
  this.getAdaptableApi()
527
527
  .internalApi.getQueryLanguageService()
528
- .evaluateBooleanExpression(expression, 'Alert', rowNode, dataChangedEvent);
528
+ .evaluateBooleanExpression(expression, 'Alert', rowNode, { dataChangedEvent });
529
529
  }
530
530
  catch (error) {
531
531
  isSatisfiedExpression = false;
@@ -1,4 +1,4 @@
1
- import { HeaderValueGetterParams, IRowNode } from 'ag-grid-enterprise';
1
+ import { Column, HeaderValueGetterParams, IRowNode } from 'ag-grid-enterprise';
2
2
  import { AdaptableColumn, AdaptableFormat, AdaptablePredicateDef, ColumnScope, FormatColumn, FormatColumnConfig, FormatColumnTarget, StringFormatterOptions } from '../../types';
3
3
  import { ApiBase } from '../Implementation/ApiBase';
4
4
  export declare class FormatColumnInternalApi extends ApiBase {
@@ -85,7 +85,7 @@ export declare class FormatColumnInternalApi extends ApiBase {
85
85
  * @param column
86
86
  * @param params
87
87
  */
88
- formatColumnShouldRenderInCell(formatColumn: FormatColumn, column: AdaptableColumn, rowNode: IRowNode, cellValue: any): boolean;
88
+ formatColumnShouldRenderInCell(formatColumn: FormatColumn, column: AdaptableColumn, rowNode: IRowNode, cellValue: any, pivotResultColumn?: Column): boolean;
89
89
  /**
90
90
  * Checks if format column is relevant for a given Column Header
91
91
  *
@@ -95,17 +95,6 @@ export declare class FormatColumnInternalApi extends ApiBase {
95
95
  formatColumnShouldRenderInHeader(formatColumn: FormatColumn, column: AdaptableColumn): boolean;
96
96
  private evaluatePredicate;
97
97
  private evaluateExpression;
98
- /**
99
- * Extract from the given FormatColumns only the ones which are relevant for a given cell (intersection of given AdaptableColumn and RowNode)
100
- *
101
- * @param formatColumns
102
- * @param column
103
- * @param params
104
- */
105
- getFormatColumnsRelevantForColumn(formatColumns: FormatColumn[], column: AdaptableColumn, params: {
106
- node: IRowNode;
107
- value: any;
108
- }): FormatColumn[];
109
98
  /**
110
99
  * Extract from the given FormatColumns the one which is the most relevant for a given cell (intersection of given AdaptableColumn and RowNode)
111
100
  *
@@ -222,7 +222,7 @@ export class FormatColumnInternalApi extends ApiBase {
222
222
  * @param column
223
223
  * @param params
224
224
  */
225
- formatColumnShouldRenderInCell(formatColumn, column, rowNode, cellValue) {
225
+ formatColumnShouldRenderInCell(formatColumn, column, rowNode, cellValue, pivotResultColumn) {
226
226
  // suspended is important to be first
227
227
  if (formatColumn.IsSuspended) {
228
228
  return false;
@@ -270,7 +270,7 @@ export class FormatColumnInternalApi extends ApiBase {
270
270
  return this.evaluatePredicate(formatColumn, predicateDefHandlerContext);
271
271
  } // then run the Expression
272
272
  else if (formatColumn.Rule.BooleanExpression) {
273
- return this.evaluateExpression(formatColumn, rowNode);
273
+ return this.evaluateExpression(formatColumn, rowNode, pivotResultColumn);
274
274
  }
275
275
  // nothing has passed then return false
276
276
  return false;
@@ -294,29 +294,19 @@ export class FormatColumnInternalApi extends ApiBase {
294
294
  evaluatePredicate(formatColumn, predicateDefHandlerContext) {
295
295
  return this.getPredicateApi().handleColumnPredicates(formatColumn.Rule?.Predicates, predicateDefHandlerContext, false);
296
296
  }
297
- evaluateExpression(formatColumn, node) {
297
+ evaluateExpression(formatColumn, node, pivotResultColumn) {
298
298
  const isValidExpression = this.getExpressionApi().isValidBooleanExpression(formatColumn.Rule.BooleanExpression, ModuleConstants.FormatColumnModuleId, `Invalid format column rule '${formatColumn.Rule.BooleanExpression}'`);
299
299
  try {
300
300
  return (isValidExpression &&
301
301
  this.getAdaptableApi()
302
302
  .internalApi.getQueryLanguageService()
303
- .evaluateBooleanExpression(formatColumn.Rule.BooleanExpression, ModuleConstants.FormatColumnModuleId, node));
303
+ .evaluateBooleanExpression(formatColumn.Rule.BooleanExpression, ModuleConstants.FormatColumnModuleId, node, { pivotResultColumn }));
304
304
  }
305
305
  catch (error) {
306
306
  errorOnce(error.message);
307
307
  return false;
308
308
  }
309
309
  }
310
- /**
311
- * Extract from the given FormatColumns only the ones which are relevant for a given cell (intersection of given AdaptableColumn and RowNode)
312
- *
313
- * @param formatColumns
314
- * @param column
315
- * @param params
316
- */
317
- getFormatColumnsRelevantForColumn(formatColumns, column, params) {
318
- return formatColumns.filter((formatColumn) => this.formatColumnShouldRenderInCell(formatColumn, column, params.node, params.value));
319
- }
320
310
  /**
321
311
  * Extract from the given FormatColumns the one which is the most relevant for a given cell (intersection of given AdaptableColumn and RowNode)
322
312
  *
@@ -85,7 +85,9 @@ export class FlashingCellModule extends AdaptableModuleBase {
85
85
  isValidExpression &&
86
86
  this.api.internalApi
87
87
  .getQueryLanguageService()
88
- .evaluateBooleanExpression(expression, this.moduleInfo.ModuleName, rowNode, cellDataChangedInfo);
88
+ .evaluateBooleanExpression(expression, this.moduleInfo.ModuleName, rowNode, {
89
+ dataChangedEvent: cellDataChangedInfo,
90
+ });
89
91
  }
90
92
  catch (error) {
91
93
  isSatisfiedExpression = false;
@@ -60,6 +60,14 @@ export const scalarExpressionFunctions = {
60
60
  if (!column.queryable) {
61
61
  throw new ExpressionEvaluationError('COL', `Column name "${columnId}" is not queryable`);
62
62
  }
63
+ // see #derived_pivot_cell_style
64
+ if (context.pivotResultColumn) {
65
+ const baseColumnId = context.pivotResultColumn.getColDef()?.pivotValueColumn?.getColId();
66
+ if (baseColumnId === columnId) {
67
+ // we evaluate the pivot result column instead of the base column
68
+ return context.adaptableApi?.gridApi.getNormalisedValueFromRowNode(context.node, context.pivotResultColumn.getColId());
69
+ }
70
+ }
63
71
  return context.adaptableApi?.gridApi.getNormalisedValueFromRowNode(context.node, columnId);
64
72
  },
65
73
  description: 'Returns the value of a Column',
@@ -1,6 +1,6 @@
1
1
  import { Observable } from 'rxjs';
2
2
  import { IAdaptableService } from './IAdaptableService';
3
- import { IRowNode } from 'ag-grid-enterprise';
3
+ import { Column, IRowNode } from 'ag-grid-enterprise';
4
4
  import { CellDataChangedInfo } from '../../../AdaptableState/Common/CellDataChangedInfo';
5
5
  import { RowDataChangedInfo } from '../../../AdaptableState/Common/RowDataChangedInfo';
6
6
  import { AdaptableModule } from '../../../AdaptableState/Common/Types';
@@ -11,7 +11,10 @@ import { ScalarFunctionName } from '../../ExpressionFunctions/scalarExpressionFu
11
11
  import { ObservableFunctionName } from '../../ExpressionFunctions/observableExpressionFunctions';
12
12
  import { ExpressionFunctionMap } from '../../../parser/src/types';
13
13
  export interface IQueryLanguageService extends IAdaptableService {
14
- evaluateBooleanExpression(expression: string, module: AdaptableModule, rowNode: IRowNode, dataChangedEvent?: CellDataChangedInfo): boolean;
14
+ evaluateBooleanExpression(expression: string, module: AdaptableModule, rowNode: IRowNode, evalContext?: {
15
+ dataChangedEvent?: CellDataChangedInfo;
16
+ pivotResultColumn?: Column;
17
+ }): boolean;
15
18
  evaluateScalarExpression(expression: string, module: AdaptableModule, rowNode: IRowNode): any;
16
19
  evaluateObservableExpression(expression: string, module: AdaptableModule): Observable<CellDataChangedInfo | RowDataChangedInfo>;
17
20
  evaluateAggregatedBooleanExpression(expression: string, module: AdaptableModule): BooleanAggregationParameter;
@@ -1,4 +1,4 @@
1
- import { IRowNode } from 'ag-grid-enterprise';
1
+ import { Column, IRowNode } from 'ag-grid-enterprise';
2
2
  import { Observable } from 'rxjs';
3
3
  import { AdaptableApi, RowDataChangedInfo } from '../../../types';
4
4
  import { GlobalExpressionFunctionsContext } from '../../AdaptableOptions/ExpressionOptions';
@@ -16,7 +16,10 @@ export declare class QueryLanguageService implements IQueryLanguageService {
16
16
  private cacheAggregatedScalarValidation;
17
17
  private cacheModuleSpecificExpressionFunctions;
18
18
  constructor(adaptableApi: AdaptableApi);
19
- evaluateBooleanExpression(expression: string, module: AdaptableModule, rowNode: any, dataChangedEvent?: CellDataChangedInfo): any;
19
+ evaluateBooleanExpression(expression: string, module: AdaptableModule, rowNode: any, evalContext?: {
20
+ dataChangedEvent?: CellDataChangedInfo;
21
+ pivotResultColumn?: Column;
22
+ }): any;
20
23
  evaluateScalarExpression(expression: string, module: AdaptableModule, rowNode: IRowNode): any;
21
24
  evaluateAggregatedScalarExpression(expression: string, module: AdaptableModule, getRowNodes?: () => IRowNode[]): ScalarAggregationParameter;
22
25
  evaluateObservableExpression(reactiveExpression: string, module: AdaptableModule): Observable<CellDataChangedInfo | RowDataChangedInfo>;
@@ -17,7 +17,7 @@ export class QueryLanguageService {
17
17
  this.cacheAggregatedScalarValidation = new Map();
18
18
  this.cacheModuleSpecificExpressionFunctions = new Map();
19
19
  }
20
- evaluateBooleanExpression(expression, module, rowNode, dataChangedEvent) {
20
+ evaluateBooleanExpression(expression, module, rowNode, evalContext) {
21
21
  if (expression == undefined) {
22
22
  // should never happen, but just in case
23
23
  this.adaptableApi.logError('QueryLanguageService.evaluateBooleanExpression was called with an undefined expression');
@@ -29,7 +29,8 @@ export class QueryLanguageService {
29
29
  node: rowNode,
30
30
  functions: booleanAndScalarFunctions,
31
31
  evaluateCustomQueryVariable: this.evaluateCustomQueryVariable,
32
- dataChangedEvent,
32
+ dataChangedEvent: evalContext?.dataChangedEvent,
33
+ pivotResultColumn: evalContext?.pivotResultColumn,
33
34
  ...this.adaptableApi.internalApi.buildBaseContext(),
34
35
  });
35
36
  }
@@ -121,7 +122,7 @@ export class QueryLanguageService {
121
122
  newValue: 100,
122
123
  oldValue: 150,
123
124
  };
124
- this.evaluateBooleanExpression(expression, module, firstRowNode, dataChangedEvent);
125
+ this.evaluateBooleanExpression(expression, module, firstRowNode, { dataChangedEvent });
125
126
  const result = {
126
127
  isValid: true,
127
128
  errorMessage: '',
@@ -314,7 +314,13 @@ export class AgGridColumnAdapter {
314
314
  const baseColumn = params.column.getColDef()?.pivotValueColumn;
315
315
  if (baseColumn) {
316
316
  const baseColDefCellStyle = baseColumn?.getColDef()?.cellStyle;
317
- const baseColParams = { ...params, column: baseColumn };
317
+ const baseColParams = {
318
+ ...params,
319
+ column: baseColumn,
320
+ // @ts-ignore
321
+ // #derived_pivot_cell_style
322
+ __pivotResultColumn: params.column,
323
+ };
318
324
  baseStyles =
319
325
  typeof baseColDefCellStyle === 'function'
320
326
  ? baseColDefCellStyle(baseColParams)
@@ -1139,7 +1145,9 @@ export class AgGridColumnAdapter {
1139
1145
  return {};
1140
1146
  }
1141
1147
  const relevantFormatColumnsWithStyle = activeFormatColumnsWithStyle.filter((formatColumn) => {
1142
- return this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInCell(formatColumn, abColumn, params.node, params.value);
1148
+ return this.adaptableApi.formatColumnApi.internalApi.formatColumnShouldRenderInCell(formatColumn, abColumn, params.node, params.value,
1149
+ // @ts-ignore see #derived_pivot_cell_style
1150
+ params.__pivotResultColumn);
1143
1151
  });
1144
1152
  return this.getFormatColumnAdaptableStyle(relevantFormatColumnsWithStyle);
1145
1153
  }
@@ -5,7 +5,6 @@ export declare const ensureLoadingScreenPortalElement: () => HTMLElement;
5
5
  export interface ModalProps extends FlexProps {
6
6
  isOpen?: boolean;
7
7
  baseZIndex?: number;
8
- backdropZIndexOffset?: number;
9
8
  onBringToFront?: () => void;
10
9
  }
11
10
  export declare const Modal: React.FunctionComponent<React.PropsWithChildren<ModalProps>>;
@@ -7,6 +7,7 @@ import { Flex } from 'rebass';
7
7
  import { baseClassName, default as Backdrop } from './Backdrop';
8
8
  import { createUuid } from '../utils/uuid';
9
9
  import { isBrowserDocumentAvailable } from '../../View/UIHelper';
10
+ import { useStacking } from '../WindowModal/useStacking';
10
11
  let portalElement;
11
12
  let loadingScreenPortalElement;
12
13
  export const ensurePortalElement = () => {
@@ -38,8 +39,9 @@ export const Modal = (props) => {
38
39
  const uuid = useMemo(() => createUuid(), []);
39
40
  const counter = useMemo(() => globalCounter++, [isOpen]);
40
41
  const openTimestamp = counter;
41
- const backdropZIndexOffset = props.backdropZIndexOffset || 1;
42
- const zIndex = (props.baseZIndex || 2000) + counter;
42
+ const backdropZIndexOffset = 1;
43
+ const stacking = useStacking();
44
+ const zIndex = stacking.zIndex;
43
45
  return createPortal(isOpen ? (React.createElement(React.Fragment, null,
44
46
  React.createElement(Backdrop, { timestamp: openTimestamp, uuid: uuid, zIndex: zIndex - backdropZIndexOffset, onBringToFront: onBringToFront }),
45
47
  React.createElement(RemoveScroll, null,
@@ -13,6 +13,7 @@ import contains from '../utils/contains';
13
13
  import { isBrowserDocumentAvailable } from '../../View/UIHelper';
14
14
  import { useOverlay } from '../InfiniteTable';
15
15
  import { useAdaptable } from '../../View/AdaptableContext';
16
+ import { OVERLAY_BASE_Z_INDEX } from '../overlayBaseZIndex';
16
17
  export const getConstrainElement = (target, constrainTo) => {
17
18
  let el = null;
18
19
  if (typeof constrainTo === 'string') {
@@ -31,6 +32,7 @@ export const getConstrainRect = (target, constrainTo) => {
31
32
  return getDocRect();
32
33
  };
33
34
  let portalElement;
35
+ const OVERLAY_TRIGGER_Z_INDEX = OVERLAY_BASE_Z_INDEX;
34
36
  const ensurePortalElement = () => {
35
37
  if (!isBrowserDocumentAvailable()) {
36
38
  return;
@@ -40,7 +42,7 @@ const ensurePortalElement = () => {
40
42
  }
41
43
  portalElement = document.createElement('div');
42
44
  portalElement.style.position = 'absolute';
43
- portalElement.style.zIndex = '9999999';
45
+ portalElement.style.zIndex = OVERLAY_TRIGGER_Z_INDEX.toString();
44
46
  portalElement.style.top = '0px';
45
47
  portalElement.style.left = '0px';
46
48
  document.body.appendChild(portalElement);
@@ -9,6 +9,7 @@ import { useCallback, useMemo, useState } from 'react';
9
9
  import join from '../utils/join';
10
10
  import { Resizable } from 're-resizable';
11
11
  import Tooltip from '../Tooltip';
12
+ import { OVERLAY_BASE_Z_INDEX } from '../overlayBaseZIndex';
12
13
  const resizableDirections = {
13
14
  right: true,
14
15
  bottom: true,
@@ -533,7 +534,7 @@ export const Select = function (props) {
533
534
  menuPortal: (baseStyle) => {
534
535
  return {
535
536
  ...baseStyle,
536
- zIndex: 999999,
537
+ zIndex: OVERLAY_BASE_Z_INDEX,
537
538
  textAlign: 'left',
538
539
  };
539
540
  },
@@ -541,7 +542,7 @@ export const Select = function (props) {
541
542
  menu: (baseStyle, state) => {
542
543
  return {
543
544
  ...baseStyle,
544
- zIndex: 999999,
545
+ zIndex: OVERLAY_BASE_Z_INDEX,
545
546
  boxShadow: 'var(--ab-cmp-select-menu__box-shadow)',
546
547
  minWidth: `var(--ab-cmp-select-menu__min-width)`,
547
548
  width: resizable ? '100%' : `${Math.max(maxLabelLength, 10)}ch`,
@@ -4,6 +4,15 @@ const setZIndexMap = {};
4
4
  const zIndexMap = [];
5
5
  // starts with 3000, to be above the default zIndex of the Modal component
6
6
  const BASE_Z_INDEX = 3000;
7
+ const Z_INDEX_GAP = 5;
8
+ let GLOBAL_COUNTER = 0;
9
+ const getNewOffset = () => {
10
+ const counter = GLOBAL_COUNTER++;
11
+ return counter * Z_INDEX_GAP;
12
+ };
13
+ const getNewZIndex = () => {
14
+ return BASE_Z_INDEX + getNewOffset();
15
+ };
7
16
  /**
8
17
  * Used to facilitate the stacking between multiple opened windows.
9
18
  * When calling 'bringToFront' brings caller to top.
@@ -11,7 +20,7 @@ const BASE_Z_INDEX = 3000;
11
20
  */
12
21
  export const useStacking = () => {
13
22
  const modalZIndexId = React.useMemo(() => createUuid(), []);
14
- const [zIndex, setZIndex] = React.useState(BASE_Z_INDEX);
23
+ const [zIndex, setZIndex] = React.useState(getNewZIndex);
15
24
  React.useEffect(() => {
16
25
  setZIndexMap[modalZIndexId] = setZIndex;
17
26
  return () => {
@@ -30,8 +39,8 @@ export const useStacking = () => {
30
39
  else {
31
40
  zIndexMap.push(modalZIndexId);
32
41
  }
33
- zIndexMap.forEach((id, index) => {
34
- setZIndexMap?.[id]?.(BASE_Z_INDEX + index * 10);
42
+ zIndexMap.forEach((id) => {
43
+ setZIndexMap?.[id]?.(getNewZIndex());
35
44
  });
36
45
  }, []);
37
46
  return {
@@ -0,0 +1 @@
1
+ export declare const OVERLAY_BASE_Z_INDEX = 9999999;
@@ -0,0 +1 @@
1
+ export const OVERLAY_BASE_Z_INDEX = 9999999;
package/src/env.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export default {
2
2
  NEXT_PUBLIC_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: 1757076026384 || Date.now(),
4
- VERSION: "21.0.0-canary.3" || '--current-version--',
3
+ PUBLISH_TIMESTAMP: 1757190997535 || Date.now(),
4
+ VERSION: "21.0.0-canary.5" || '--current-version--',
5
5
  };
@@ -2464,11 +2464,19 @@ export declare const ADAPTABLE_METAMODEL: {
2464
2464
  name: string;
2465
2465
  kind: string;
2466
2466
  desc: string;
2467
- props: {
2467
+ props: ({
2468
2468
  name: string;
2469
2469
  kind: string;
2470
2470
  desc: string;
2471
- }[];
2471
+ isOpt?: undefined;
2472
+ ref?: undefined;
2473
+ } | {
2474
+ name: string;
2475
+ kind: string;
2476
+ desc: string;
2477
+ isOpt: boolean;
2478
+ ref: string;
2479
+ })[];
2472
2480
  };
2473
2481
  CustomQueryVariableContext: {
2474
2482
  name: string;
@@ -4086,6 +4094,22 @@ export declare const ADAPTABLE_METAMODEL: {
4086
4094
  isOpt: boolean;
4087
4095
  }[];
4088
4096
  };
4097
+ InFilterValueResult: {
4098
+ name: string;
4099
+ kind: string;
4100
+ desc: string;
4101
+ props: ({
4102
+ name: string;
4103
+ kind: string;
4104
+ desc: string;
4105
+ isOpt: boolean;
4106
+ } | {
4107
+ name: string;
4108
+ kind: string;
4109
+ desc: string;
4110
+ isOpt?: undefined;
4111
+ })[];
4112
+ };
4089
4113
  InitialState: {
4090
4114
  name: string;
4091
4115
  kind: string;