@adaptabletools/adaptable 21.0.12 → 21.1.0-canary.1

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 (66) hide show
  1. package/base.css +1811 -2336
  2. package/base.css.map +1 -1
  3. package/index.css +1768 -1413
  4. package/index.css.map +1 -1
  5. package/package.json +3 -3
  6. package/src/AdaptableInterfaces/IAdaptable.d.ts +2 -1
  7. package/src/AdaptableOptions/FilterOptions.d.ts +7 -0
  8. package/src/AdaptableOptions/PredicateOptions.d.ts +4 -3
  9. package/src/AdaptableState/Common/AdaptableColumn.d.ts +1 -1
  10. package/src/AdaptableState/Common/AdaptablePredicate.d.ts +12 -0
  11. package/src/AdaptableState/Common/AdaptablePredicate.js +132 -18
  12. package/src/AdaptableState/Selection/GridCell.d.ts +10 -0
  13. package/src/Api/Implementation/ExportApiImpl.js +2 -8
  14. package/src/Api/Implementation/PredicateApiImpl.d.ts +3 -1
  15. package/src/Api/Implementation/PredicateApiImpl.js +25 -2
  16. package/src/Api/Internal/AdaptableInternalApi.d.ts +2 -1
  17. package/src/Api/Internal/AdaptableInternalApi.js +6 -0
  18. package/src/Api/Internal/PredicateInternalApi.d.ts +3 -1
  19. package/src/Api/Internal/PredicateInternalApi.js +14 -0
  20. package/src/Api/PredicateApi.d.ts +1 -1
  21. package/src/Redux/Store/AdaptableStore.js +111 -3
  22. package/src/Utilities/Helpers/Helper.js +26 -2
  23. package/src/Utilities/Hooks/index.d.ts +4 -0
  24. package/src/Utilities/Hooks/index.js +4 -0
  25. package/src/Utilities/Hooks/useAdaptableColumn.d.ts +2 -0
  26. package/src/Utilities/Hooks/useAdaptableColumn.js +6 -0
  27. package/src/Utilities/Hooks/useAdaptableOptions.d.ts +2 -0
  28. package/src/Utilities/Hooks/useAdaptableOptions.js +5 -0
  29. package/src/Utilities/Hooks/useAdaptableState.d.ts +3 -0
  30. package/src/Utilities/Hooks/useAdaptableState.js +39 -0
  31. package/src/Utilities/Services/ModuleService.js +1 -1
  32. package/src/Utilities/adaptableQlUtils.js +3 -0
  33. package/src/View/AdaptableComputedCSSVarsContext.d.ts +12 -0
  34. package/src/View/AdaptableComputedCSSVarsContext.js +25 -0
  35. package/src/View/Components/AdaptableInput/AdaptableDateInlineInput.d.ts +1 -1
  36. package/src/View/Components/ColumnFilter/FloatingFilter.js +5 -1
  37. package/src/View/Components/ColumnFilter/components/FloatingFilterInputList.js +1 -1
  38. package/src/View/Components/ColumnFilter/components/FloatingFilterValues.js +34 -9
  39. package/src/View/Components/FilterForm/ListBoxFilterForm.d.ts +1 -0
  40. package/src/View/Components/FilterForm/ListBoxFilterForm.js +93 -16
  41. package/src/View/Layout/Wizard/sections/ColumnsSection.js +1 -1
  42. package/src/View/renderWithAdaptableContext.js +3 -1
  43. package/src/agGrid/AdaptableAgGrid.d.ts +3 -1
  44. package/src/agGrid/AdaptableAgGrid.js +361 -24
  45. package/src/agGrid/AdaptableFilterHandler.d.ts +3 -1
  46. package/src/agGrid/AdaptableFilterHandler.js +16 -12
  47. package/src/agGrid/AgGridAdapter.js +9 -5
  48. package/src/agGrid/AgGridColumnAdapter.js +14 -12
  49. package/src/components/OverlayTrigger/index.js +1 -1
  50. package/src/components/Select/Select.js +22 -22
  51. package/src/components/Tree/TreeDropdown/index.d.ts +27 -0
  52. package/src/components/Tree/TreeDropdown/index.js +250 -0
  53. package/src/components/Tree/TreeList/index.d.ts +25 -0
  54. package/src/components/Tree/TreeList/index.js +35 -0
  55. package/src/devTools/DevToolsTracks.d.ts +31 -0
  56. package/src/devTools/DevToolsTracks.js +31 -0
  57. package/src/devTools/PerfMarker.d.ts +12 -0
  58. package/src/devTools/PerfMarker.js +1 -0
  59. package/src/devTools/index.d.ts +102 -0
  60. package/src/devTools/index.js +159 -0
  61. package/src/env.js +2 -2
  62. package/src/layout-manager/src/index.d.ts +2 -0
  63. package/src/layout-manager/src/index.js +24 -0
  64. package/src/metamodel/adaptable.metamodel.d.ts +6 -0
  65. package/src/metamodel/adaptable.metamodel.js +1 -1
  66. package/tsconfig.esm.tsbuildinfo +1 -1
@@ -24,7 +24,7 @@ export class AgGridAdapter {
24
24
  const ColumnDefFactory_Prototye_preWireBeans = ColumnDefFactory_Prototype.preWireBeans;
25
25
  ColumnDefFactory_Prototype.preWireBeans = function (beans) {
26
26
  ColumnDefFactory_Prototye_preWireBeans?.apply(this, arguments);
27
- const gridId = beans?.context?.getGridId();
27
+ const gridId = beans?.context?.getId();
28
28
  if (!gridId) {
29
29
  console.error('CRITICAL: No gridId found in beans, this should never happen!');
30
30
  }
@@ -137,7 +137,8 @@ export class AgGridAdapter {
137
137
  }
138
138
  const pivotColumnFilters = self.adaptableApi.filterApi.columnFilterApi
139
139
  .getActiveColumnFilters()
140
- .filter((columnFilter) => self.adaptableApi.columnApi.isPivotResultColumn(columnFilter.ColumnId));
140
+ .filter((columnFilter) => self.adaptableApi.columnApi.isPivotResultColumn(columnFilter.ColumnId) ||
141
+ self.adaptableApi.columnApi.isAutoRowGroupColumnForSingle(columnFilter.ColumnId));
141
142
  try {
142
143
  if (pivotColumnFilters.length > 0) {
143
144
  for (const columnFilter of pivotColumnFilters) {
@@ -160,7 +161,8 @@ export class AgGridAdapter {
160
161
  agGridColumnFilterService.doFiltersPass = this.DANGER_doFiltersPassMonkeyPatcher;
161
162
  this.DANGER_isAggFilterPresentMonkeyPatcher = function () {
162
163
  const columnFilters = self.adaptableApi.filterApi.columnFilterApi.getActiveColumnFilters();
163
- return columnFilters.some((colFilter) => self.adaptableApi.columnApi.isPivotResultColumn(colFilter.ColumnId));
164
+ return columnFilters.some((colFilter) => self.adaptableApi.columnApi.isPivotResultColumn(colFilter.ColumnId) ||
165
+ self.adaptableApi.columnApi.isAutoRowGroupColumnForSingle(colFilter.ColumnId));
164
166
  };
165
167
  agGridColumnFilterService.isAggFilterPresent = this.DANGER_isAggFilterPresentMonkeyPatcher;
166
168
  }
@@ -484,8 +486,10 @@ export class AgGridAdapter {
484
486
  this.logger.warn(`Column is undefined, returning 'text' for Type`);
485
487
  return 'text';
486
488
  }
487
- if (this.adaptableApi.columnApi.isAutoRowGroupColumnForSingle(agColumn.getId()) ||
488
- this.adaptableApi.columnApi.isSelectionColumn(agColumn.getId())) {
489
+ if (this.adaptableApi.columnApi.isAutoRowGroupColumnForSingle(agColumn.getId())) {
490
+ return 'groupColumn';
491
+ }
492
+ if (this.adaptableApi.columnApi.isSelectionColumn(agColumn.getId())) {
489
493
  return 'unknown';
490
494
  }
491
495
  if (this.adaptableApi.columnApi.isAutoRowGroupColumnForMulti(agColumn.getId())) {
@@ -592,31 +592,33 @@ export class AgGridColumnAdapter {
592
592
  });
593
593
  }
594
594
  else {
595
+ // TODO only set auto group column as filterable if at least one group columns is filterable
595
596
  this.setColDefProperty(col, 'filter', () => {
596
597
  return 'agGroupColumnFilter';
597
598
  });
598
599
  }
599
- return;
600
+ if (this.adaptableApi.columnApi.isAutoRowGroupColumnForMulti(colId)) {
601
+ return;
602
+ }
600
603
  }
601
604
  // setup "normal" column filter
602
605
  this.setColDefProperty(col, 'filter', (original_filter) => {
603
- if (!colDef.filter) {
604
- return;
605
- }
606
+ const pivotMode = this.adaptableInstance.isInPivotMode();
606
607
  if (!useAdaptableFilter) {
607
608
  return original_filter;
608
609
  }
609
- if (useAdaptableFilter &&
610
- typeof original_filter !== 'boolean' &&
610
+ if (!colDef.filter) {
611
+ return;
612
+ }
613
+ if (typeof original_filter !== 'boolean' &&
611
614
  typeof original_filter?.handler !== 'function' &&
612
- !this.adaptableInstance.isInPivotMode()) {
615
+ !pivotMode) {
613
616
  this.adaptableApi.consoleError(`Column '${colId}' has a custom filter defined in colDef.filter, but Adaptable Filtering accepts only the TRUE/FALSE values!`);
614
617
  return false;
615
618
  }
616
619
  return {
617
620
  component: AgGridFilterAdapterFactory(this.adaptableInstance),
618
- // doesFilterPass,
619
- handler: (params) => new AdaptableFilterHandler(this.adaptableApi, columnSetup),
621
+ handler: () => new AdaptableFilterHandler(this.adaptableApi, columnSetup),
620
622
  };
621
623
  });
622
624
  }
@@ -633,7 +635,7 @@ export class AgGridColumnAdapter {
633
635
  !colDef.floatingFilter ||
634
636
  !this.adaptableOptions.filterOptions.useAdaptableFiltering ||
635
637
  !this.adaptableApi.filterApi.columnFilterApi.isQuickFilterVisible();
636
- if (this.adaptableApi.columnApi.isAutoRowGroupColumn(col.getColId())) {
638
+ if (this.adaptableApi.columnApi.isAutoRowGroupColumnForMulti(col.getColId())) {
637
639
  this.setColDefProperty(col, 'floatingFilter', (original_floatingFilter) => {
638
640
  // the floating filter for the group column is "inherited" from the base column
639
641
  // via the colDef.filter = 'agGroupColumnFilter'
@@ -644,7 +646,7 @@ export class AgGridColumnAdapter {
644
646
  });
645
647
  this.setColDefProperty(col, 'suppressFloatingFilterButton', () => {
646
648
  // hide button for multi column groups
647
- return this.adaptableApi.columnApi.isAutoRowGroupColumnForMulti(col.getColId());
649
+ return true;
648
650
  });
649
651
  return;
650
652
  }
@@ -654,7 +656,7 @@ export class AgGridColumnAdapter {
654
656
  }
655
657
  return AgGridFloatingFilterAdapterFactory(this.adaptableInstance);
656
658
  });
657
- this.setColDefProperty(col, 'floatingFilter', (original_floatingFilter) => {
659
+ this.setColDefProperty(col, 'floatingFilter', () => {
658
660
  if (isFloatingFilterDisabled) {
659
661
  return;
660
662
  }
@@ -193,7 +193,7 @@ const OverlayTrigger = React.forwardRef((givenProps, ref) => {
193
193
  clearAllOverlays();
194
194
  hideOverlay('overlay-trigger');
195
195
  }
196
- } }, props.render({ targetWidth: targetWidth })));
196
+ } }, props.render({ targetWidth })));
197
197
  let preparedConstrainTo;
198
198
  if (constrainTo) {
199
199
  preparedConstrainTo = getConstrainElement(targetRef.current, constrainTo);
@@ -4,13 +4,14 @@ import ReactSelect, { components, } from 'react-select';
4
4
  import CreatableSelect from 'react-select/creatable';
5
5
  import { Icon } from '../icons';
6
6
  import { Box, Flex } from 'rebass';
7
- import { DataSource, InfiniteTable, components as InfiniteTableComponents, } from '@infinite-table/infinite-react';
7
+ import { DataSource, InfiniteTable, } from '@infinite-table/infinite-react';
8
8
  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
12
  import { ensurePortalElement } from '../OverlayTrigger';
13
- import { CSSNumericVariableWatch } from './CSSNumericVariableWatch';
13
+ import { CheckBox } from '../CheckBox';
14
+ import { useAdaptableComputedCSSVars } from '../../View/AdaptableComputedCSSVarsContext';
14
15
  const resizableDirections = {
15
16
  right: true,
16
17
  bottom: true,
@@ -52,15 +53,27 @@ const INFINITE_COLUMNS_WITH_CHECKBOX = {
52
53
  renderSelectionCheckBox: (params) => {
53
54
  // disable reacting to onChange
54
55
  // as we handle selection change in the onCellClick
55
- return React.createElement(InfiniteTableComponents.CheckBox, { checked: params.rowInfo?.rowSelected ?? false });
56
+ return React.createElement(CheckBox, { mx: 1, checked: params.rowInfo?.rowSelected ?? false });
56
57
  },
57
58
  renderHeaderSelectionCheckBox: true,
58
59
  className: 'ab-Select-CheckboxColumn',
59
60
  renderValue,
60
61
  renderHeader: (headerParams) => {
62
+ const selected = headerParams.allRowsSelected
63
+ ? true
64
+ : headerParams.someRowsSelected
65
+ ? null
66
+ : false;
67
+ const { api } = headerParams;
61
68
  return (React.createElement(React.Fragment, null,
62
- headerParams.renderBag.selectionCheckBox,
63
- headerParams.allRowsSelected ? '(Deselect All)' : '(Select All)'));
69
+ React.createElement(CheckBox, { mx: 1, checked: selected, onChange: (selected) => {
70
+ if (selected) {
71
+ api.rowSelectionApi.selectAll();
72
+ }
73
+ else {
74
+ api.rowSelectionApi.deselectAll();
75
+ }
76
+ } }, headerParams.allRowsSelected ? '(Deselect All)' : '(Select All)')));
64
77
  },
65
78
  renderMenuIcon: false,
66
79
  },
@@ -102,15 +115,11 @@ const doesOptionMatchValue = function (value) {
102
115
  };
103
116
  export const Select = function (props) {
104
117
  let maxLabelLength = 0;
105
- const cssVarsValuesRef = React.useRef({
106
- '--ab-cmp-select-menu__max-width': 0,
107
- '--ab-cmp-select-menu__min-width': 0,
108
- '--ab-cmp-select-menu__max-height': 0,
109
- });
118
+ const computedCSSVars = useAdaptableComputedCSSVars();
110
119
  const CSS_VARS_VALUES = {
111
- '--ab-cmp-select-menu__max-width': cssVarsValuesRef.current['--ab-cmp-select-menu__max-width'] || '60vw',
112
- '--ab-cmp-select-menu__min-width': cssVarsValuesRef.current['--ab-cmp-select-menu__min-width'] || 150,
113
- '--ab-cmp-select-menu__max-height': cssVarsValuesRef.current['--ab-cmp-select-menu__max-height'] || '60vh',
120
+ '--ab-cmp-select-menu__max-width': computedCSSVars['--ab-cmp-select-menu__max-width'] || '60vw',
121
+ '--ab-cmp-select-menu__min-width': computedCSSVars['--ab-cmp-select-menu__min-width'] || 150,
122
+ '--ab-cmp-select-menu__max-height': computedCSSVars['--ab-cmp-select-menu__max-height'] || '60vh',
114
123
  };
115
124
  const searchableInMenulist = props.searchable === 'menulist';
116
125
  const searchableInline = props.searchable === 'inline';
@@ -513,15 +522,6 @@ export const Select = function (props) {
513
522
  props.onInputChange?.(value);
514
523
  }, [props.onInputChange, isMulti]);
515
524
  return (React.createElement(React.Fragment, null,
516
- React.createElement(CSSNumericVariableWatch, { varName: "--ab-cmp-select-menu__max-width", onChange: (value) => {
517
- cssVarsValuesRef.current['--ab-cmp-select-menu__max-width'] = value;
518
- } }),
519
- React.createElement(CSSNumericVariableWatch, { varName: "--ab-cmp-select-menu__min-width", onChange: (value) => {
520
- cssVarsValuesRef.current['--ab-cmp-select-menu__min-width'] = value;
521
- } }),
522
- React.createElement(CSSNumericVariableWatch, { varName: "--ab-cmp-select-menu__max-height", onChange: (value) => {
523
- cssVarsValuesRef.current['--ab-cmp-select-menu__max-height'] = value;
524
- } }),
525
525
  React.createElement(SelectComponent, { ref: ref, openMenuOnClick: searchableInMenulist ? false : undefined, openMenuOnFocus: searchableInMenulist ? false : undefined, menuIsOpen: searchableInMenulist ? isSelectMenuOpen : undefined, isSearchable: searchableInline, "aria-label": props['aria-label'], onKeyDown: props.onKeyDown, inputValue: inputValue, onInputChange: onInputChange, onFocus: onFocus, onBlur: onBlur, onMenuOpen: props.onMenuOpen, isLoading: props.isLoading, options: props.options, className: join(props.className, 'ab-Select'), isDisabled: disabled, menuPlacement: props.menuPlacement ?? 'auto', hideSelectedOptions: false, isMulti: isMulti, value: selectedOption, blurInputOnSelect: false, menuPosition: props.menuPosition ?? 'absolute',
526
526
  // This needed so the menu is not clipped by overflow: hidden
527
527
  menuPortalTarget: ensurePortalElement(), isClearable: props.isClearable, closeMenuOnSelect: props.closeMenuOnSelect, onChange: (option) => {
@@ -0,0 +1,27 @@
1
+ import * as React from 'react';
2
+ import { TreeListItem, TreeListProps } from '../TreeList';
3
+ export type TreeDropdownProps<T extends TreeListItem<any>> = {
4
+ placeholder?: string;
5
+ style?: React.CSSProperties;
6
+ fieldStyle?: React.CSSProperties;
7
+ listSizeConstraints?: {
8
+ minWidth?: number | string;
9
+ maxWidth?: number | string;
10
+ minHeight?: number | string;
11
+ maxHeight?: number | string;
12
+ };
13
+ options: TreeListProps<T>['options'];
14
+ labelField?: string;
15
+ primaryKey?: keyof T;
16
+ value?: any[][] | string[];
17
+ defaultValue?: any[][] | string[];
18
+ toDisplayValue?: (value: any[][] | string[]) => string;
19
+ onChange: (value: any[][] | string[]) => void;
20
+ onMenuOpen?: () => void;
21
+ onMenuClose?: () => void;
22
+ onMouseDown?: (e: React.MouseEvent<HTMLDivElement>) => void;
23
+ resizable?: boolean;
24
+ clearable?: boolean;
25
+ };
26
+ export declare function toDisplayValueDefault(value: any[][] | string[]): string;
27
+ export declare function TreeDropdown<T extends TreeListItem<any>>(props: TreeDropdownProps<T>): React.JSX.Element;
@@ -0,0 +1,250 @@
1
+ import * as React from 'react';
2
+ import FieldWrap from '../../FieldWrap';
3
+ import { TreeList } from '../TreeList';
4
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
5
+ import OverlayTrigger from '../../OverlayTrigger';
6
+ import { Box, Flex } from 'rebass';
7
+ import NotifyResize from '../../NotifyResize';
8
+ import Input from '../../Input';
9
+ import { TreeSelectionState, withSelectedLeafNodesOnly, } from '../../InfiniteTable';
10
+ import SimpleButton from '../../SimpleButton';
11
+ import { CheckBox } from '../../CheckBox';
12
+ import { useLatest } from '../../utils/useLatest';
13
+ import { Resizable } from 're-resizable';
14
+ import { useAdaptableComputedCSSVars } from '../../../View/AdaptableComputedCSSVarsContext';
15
+ const resizableDirections = {
16
+ right: true,
17
+ bottom: true,
18
+ bottomRight: true,
19
+ };
20
+ export function toDisplayValueDefault(value) {
21
+ if (!Array.isArray(value)) {
22
+ return `${value}`;
23
+ }
24
+ return value.map((v) => (Array.isArray(v) ? v.join('-') : v)).join(', ');
25
+ }
26
+ const getLabelColumn = (field) => {
27
+ return {
28
+ field,
29
+ defaultFlex: 1,
30
+ renderTreeIcon: true,
31
+ defaultSortable: false,
32
+ resizable: false,
33
+ renderSelectionCheckBox: ({ rowInfo, dataSourceApi, api }) => {
34
+ if (!rowInfo.isTreeNode) {
35
+ return null;
36
+ }
37
+ return (React.createElement(CheckBox, { mx: 1, checked: rowInfo?.rowSelected, onChange: (checked) => {
38
+ dataSourceApi.treeApi.setNodeSelection(rowInfo.nodePath, checked);
39
+ api.focus();
40
+ } }));
41
+ },
42
+ renderHeader: ({ dataSourceApi, api, allRowsSelected, someRowsSelected }) => {
43
+ const { treeApi } = dataSourceApi;
44
+ const allFirstLevelCollapsed = dataSourceApi
45
+ .getOriginalDataArray()
46
+ .every((item) => !treeApi.isNodeExpanded([item.id]));
47
+ return (React.createElement(Flex, { flexDirection: 'row', alignItems: 'center', width: '100%', onMouseDown: (e) => {
48
+ // so we can keep the focus on the Grid
49
+ e.preventDefault();
50
+ } },
51
+ React.createElement(CheckBox, { checked: someRowsSelected && !allRowsSelected ? null : allRowsSelected, mr: 2, onChange: () => {
52
+ if (allRowsSelected) {
53
+ dataSourceApi.treeApi.deselectAll();
54
+ }
55
+ else {
56
+ dataSourceApi.treeApi.selectAll();
57
+ }
58
+ api.focus();
59
+ } }),
60
+ React.createElement(Flex, { flex: 1 }),
61
+ React.createElement(SimpleButton, { label: "toggle-expand-collapse", icon: allFirstLevelCollapsed ? 'expand-all' : 'collapse-all', onMouseDown: () => {
62
+ if (allFirstLevelCollapsed) {
63
+ dataSourceApi.treeApi.expandAll();
64
+ }
65
+ else {
66
+ dataSourceApi.treeApi.collapseAll();
67
+ }
68
+ }, iconPosition: "end" }, allFirstLevelCollapsed ? 'Expand All' : 'Collapse All')));
69
+ },
70
+ };
71
+ };
72
+ const sizeFull = {
73
+ width: '100%',
74
+ height: '100%',
75
+ };
76
+ function getRowCount(options) {
77
+ return options.reduce((acc, option) => {
78
+ if (Array.isArray(option.children)) {
79
+ return acc + getRowCount(option.children) + 1;
80
+ }
81
+ return acc + 1;
82
+ }, 0);
83
+ }
84
+ export function TreeDropdown(props) {
85
+ const [visible, doSetVisible] = useState(false);
86
+ const overlayDOMRef = useRef(null);
87
+ const getProps = useLatest(props);
88
+ const computedCSSVars = useAdaptableComputedCSSVars();
89
+ const [treeExpandState, setTreeExpandState] = useState(undefined);
90
+ const [searchValue, setSearchValue] = useState('');
91
+ const labelField = props.labelField ?? 'label';
92
+ const columns = useMemo(() => {
93
+ return {
94
+ label: getLabelColumn(labelField),
95
+ };
96
+ }, [labelField]);
97
+ const [stateValue, setStateValue] = useState(props.value !== undefined ? props.value : props.defaultValue || []);
98
+ const onChange = useCallback((value) => {
99
+ const paths = value instanceof TreeSelectionState
100
+ ? value.getState().selectedPaths
101
+ : value.selectedPaths || [];
102
+ if (props.value === undefined) {
103
+ setStateValue(paths);
104
+ }
105
+ props.onChange?.(paths);
106
+ }, [props.onChange, props.value]);
107
+ const value = props.value !== undefined ? props.value : stateValue;
108
+ const treeSelection = useMemo(() => {
109
+ const selection = {
110
+ defaultSelection: false,
111
+ selectedPaths: value,
112
+ };
113
+ return selection;
114
+ }, [value]);
115
+ const rowCount = useMemo(() => {
116
+ return getRowCount(props.options);
117
+ }, [props.options]);
118
+ const [size, setSize] = useState({
119
+ width: 0,
120
+ height: rowCount * 35,
121
+ });
122
+ const setHeight = useCallback((height) => {
123
+ setSize((s) => {
124
+ return {
125
+ ...s,
126
+ height,
127
+ };
128
+ });
129
+ }, []);
130
+ const setWidth = useCallback((width) => {
131
+ setSize((s) => {
132
+ return {
133
+ ...s,
134
+ width,
135
+ };
136
+ });
137
+ }, []);
138
+ const getSize = useLatest(size);
139
+ useEffect(() => {
140
+ if (!getSize().height) {
141
+ setHeight(rowCount * 35);
142
+ }
143
+ }, [rowCount]);
144
+ const setVisible = (visible) => {
145
+ if (visible) {
146
+ const { onMenuOpen } = getProps();
147
+ if (onMenuOpen) {
148
+ onMenuOpen();
149
+ }
150
+ requestAnimationFrame(() => {
151
+ doSetVisible(visible);
152
+ });
153
+ }
154
+ else {
155
+ const { onMenuClose } = getProps();
156
+ if (onMenuClose) {
157
+ onMenuClose();
158
+ }
159
+ doSetVisible(visible);
160
+ }
161
+ };
162
+ const [treeListApi, setTreeListApi] = useState(null);
163
+ const { listSizeConstraints } = props;
164
+ const nodeMatches = useCallback(({ data }) => {
165
+ return !searchValue
166
+ ? data
167
+ : `${data[labelField]}`.toLowerCase().includes(searchValue.toLowerCase());
168
+ }, [searchValue]);
169
+ const filterFunction = useCallback(({ data, filterTreeNode }) => {
170
+ if (!Array.isArray(data.children)) {
171
+ return nodeMatches({ data });
172
+ }
173
+ // allow non-leaf nodes to match
174
+ if (nodeMatches({ data })) {
175
+ return data;
176
+ }
177
+ return filterTreeNode(data);
178
+ }, [nodeMatches]);
179
+ return (React.createElement(Flex, { flexDirection: 'row', className: "ab-TreeDropdown", style: {
180
+ width: '100%',
181
+ ...props.style,
182
+ }, onMouseDown: props.onMouseDown, onBlur: (e) => {
183
+ const { relatedTarget } = e;
184
+ const overlayDOMNode = overlayDOMRef.current;
185
+ if ((overlayDOMNode && relatedTarget == overlayDOMNode) ||
186
+ overlayDOMNode?.contains(relatedTarget)) {
187
+ return;
188
+ }
189
+ setVisible(false);
190
+ } },
191
+ React.createElement(NotifyResize, { onResize: (newSize) => {
192
+ setWidth(newSize.width);
193
+ } }),
194
+ React.createElement(OverlayTrigger, { visible: visible, targetOffset: 20, render: () => {
195
+ const minWidth = listSizeConstraints?.minWidth ||
196
+ computedCSSVars['--ab-cmp-select-menu__min-width'] ||
197
+ 240;
198
+ const maxWidth = listSizeConstraints?.maxWidth ||
199
+ computedCSSVars['--ab-cmp-select-menu__max-width'] ||
200
+ '60vw';
201
+ const minHeight = listSizeConstraints?.minHeight || 200;
202
+ const maxHeight = listSizeConstraints?.maxHeight ||
203
+ computedCSSVars['--ab-cmp-select-menu__max-height'] ||
204
+ '50vh';
205
+ const resizable = getProps().resizable;
206
+ const treeList = (React.createElement(TreeList, { primaryKey: props.primaryKey ?? 'id', treeFilterFunction: filterFunction, columnHeaderHeight: 40, onReady: ({ api }) => {
207
+ setTreeListApi(api);
208
+ api.focus();
209
+ }, defaultTreeExpandState: treeExpandState, onTreeExpandStateChange: setTreeExpandState, columns: columns, options: props.options, treeSelection: treeSelection, onTreeSelectionChange: withSelectedLeafNodesOnly(onChange), style: resizable
210
+ ? sizeFull
211
+ : {
212
+ width: size.width,
213
+ height: size.height,
214
+ maxWidth,
215
+ minHeight,
216
+ maxHeight,
217
+ minWidth,
218
+ } }));
219
+ let children = (React.createElement(Flex, { flexDirection: 'column', height: '100%' },
220
+ React.createElement(Flex, { backgroundColor: 'defaultbackground', p: 1, alignItems: 'center', justifyContent: 'stretch', justifyItems: 'stretch' },
221
+ React.createElement(Input, { "data-name": "menulist-search-input", placeholder: "Search...", style: { width: '100%' }, value: searchValue, onChange: (e) => setSearchValue(e.target.value) })),
222
+ treeList));
223
+ if (resizable) {
224
+ const onResizeStop = (_e, _direction, ref) => {
225
+ const newSize = {
226
+ width: ref.style.width,
227
+ height: ref.style.height,
228
+ };
229
+ setSize(newSize);
230
+ };
231
+ children = (React.createElement(Resizable, { enable: resizableDirections, minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight, defaultSize: size, onResizeStop: onResizeStop, onResizeStart: (e) => {
232
+ // in order to prevent focus from being lost
233
+ e.preventDefault();
234
+ } }, children));
235
+ }
236
+ return (React.createElement(Box, { ref: overlayDOMRef, className: "ab-TreeDropdownOverlay", "data-name": "menu-container" }, children));
237
+ } },
238
+ React.createElement(FieldWrap, { style: { width: '100%', ...props.fieldStyle } },
239
+ React.createElement(Input, { type: "text", readOnly: true, "data-name": "Select Values", placeholder: props.placeholder ?? 'Select a value', style: {
240
+ width: '100%',
241
+ }, pr: props.clearable ? 0 : undefined, value: props.toDisplayValue ? props.toDisplayValue(value) : toDisplayValueDefault(value), onFocus: () => {
242
+ if (!visible) {
243
+ setVisible(true);
244
+ }
245
+ treeListApi?.focus();
246
+ } }),
247
+ props.clearable && (React.createElement(SimpleButton, { style: {
248
+ visibility: Array.isArray(value) && value.length > 0 ? 'visible' : 'hidden',
249
+ }, variant: "text", icon: "close", onClick: () => onChange({ selectedPaths: [] }) }))))));
250
+ }
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ import { DataSourcePropOnTreeSelectionChange_MultiNode, InfiniteTableProps, TreeDataSourceProps } from '../../InfiniteTable';
3
+ export type TreeListItem<T = any> = {
4
+ id: string | number;
5
+ label: string;
6
+ children?: TreeListItem<T>[];
7
+ };
8
+ export type TreeListProps<T extends TreeListItem<T>> = {
9
+ options: T[];
10
+ debugId?: string;
11
+ primaryKey?: keyof T;
12
+ domProps?: InfiniteTableProps<T>['domProps'];
13
+ style?: React.CSSProperties;
14
+ rowHeight?: number | string;
15
+ treeSelection?: TreeDataSourceProps<T>['treeSelection'];
16
+ defaultTreeSelection?: TreeDataSourceProps<T>['defaultTreeSelection'];
17
+ onTreeSelectionChange?: DataSourcePropOnTreeSelectionChange_MultiNode;
18
+ defaultTreeExpandState?: TreeDataSourceProps<T>['defaultTreeExpandState'];
19
+ onTreeExpandStateChange?: TreeDataSourceProps<T>['onTreeExpandStateChange'];
20
+ columns?: InfiniteTableProps<T>['columns'];
21
+ columnHeaderHeight?: number | string;
22
+ onReady?: InfiniteTableProps<T>['onReady'];
23
+ treeFilterFunction?: TreeDataSourceProps<T>['treeFilterFunction'];
24
+ };
25
+ export declare function TreeList<T extends TreeListItem<T>>(props: TreeListProps<T>): React.JSX.Element;
@@ -0,0 +1,35 @@
1
+ import * as React from 'react';
2
+ import { TreeDataSource, TreeGrid, } from '../../InfiniteTable';
3
+ import { Flex } from 'rebass';
4
+ import join from '../../../../../adaptable-react-aggrid/src/utils/join';
5
+ const columns = {
6
+ label: {
7
+ field: 'label',
8
+ header: 'Label',
9
+ defaultFlex: 1,
10
+ renderTreeIcon: true,
11
+ renderSelectionCheckBox: true,
12
+ defaultSortable: false,
13
+ },
14
+ };
15
+ const domProps = {
16
+ style: {
17
+ height: '100%',
18
+ flex: 1,
19
+ },
20
+ className: 'ab-TreeList',
21
+ };
22
+ const DEFAULT_TREE_EXPAND_STATE = {
23
+ expandedPaths: [],
24
+ defaultExpanded: false,
25
+ };
26
+ export function TreeList(props) {
27
+ return (React.createElement(Flex, { flex: 1, flexDirection: 'column', className: "ab-TreeList", style: props.style },
28
+ React.createElement(TreeDataSource, { data: props.options, primaryKey: props.primaryKey ?? 'id', defaultTreeSelection: props.defaultTreeSelection, treeSelection: props.treeSelection, onTreeSelectionChange: props.onTreeSelectionChange, treeFilterFunction: props.treeFilterFunction, onTreeExpandStateChange: props.onTreeExpandStateChange, defaultTreeExpandState: props.defaultTreeExpandState ?? DEFAULT_TREE_EXPAND_STATE },
29
+ React.createElement(TreeGrid, { defaultActiveRowIndex: 0, onReady: props.onReady, debugId: props.debugId, keyboardSelection: true, rowHeight: props.rowHeight ?? '--ab-grid-row-height', keyboardNavigation: "row", columnHeaderHeight: props.columnHeaderHeight, domProps: {
30
+ ...domProps,
31
+ ...props.domProps,
32
+ className: join(domProps.className, props.domProps?.className),
33
+ style: { ...domProps.style, ...props.domProps?.style },
34
+ }, columns: props.columns ?? columns, showZebraRows: false }))));
35
+ }
@@ -0,0 +1,31 @@
1
+ export declare const DevToolsTracks: {
2
+ readonly Init: {
3
+ readonly track: "Initialisation";
4
+ readonly labels: {
5
+ readonly Init: "Init";
6
+ readonly InitStore: "Init store";
7
+ readonly LoadStore: "Loading store";
8
+ readonly InitAGGrid: "AG Grid init";
9
+ };
10
+ };
11
+ readonly LayoutManager: {
12
+ readonly track: "Layout Manager";
13
+ readonly labels: {
14
+ readonly SetLayout: "Setting layout";
15
+ readonly ApplyPivotLayout: "Apply pivot layout";
16
+ readonly ApplyTableLayout: "Apply table layout";
17
+ };
18
+ };
19
+ readonly Runtime: {
20
+ readonly track: "Runtime";
21
+ readonly labels: {
22
+ readonly SetLayout: "Setting layout";
23
+ };
24
+ };
25
+ readonly Redux: {
26
+ readonly track: "Redux";
27
+ readonly labels: {
28
+ readonly Action: "Action";
29
+ };
30
+ };
31
+ };
@@ -0,0 +1,31 @@
1
+ export const DevToolsTracks = {
2
+ Init: {
3
+ track: 'Initialisation',
4
+ labels: {
5
+ Init: 'Init',
6
+ InitStore: 'Init store',
7
+ LoadStore: 'Loading store',
8
+ InitAGGrid: 'AG Grid init',
9
+ },
10
+ },
11
+ LayoutManager: {
12
+ track: 'Layout Manager',
13
+ labels: {
14
+ SetLayout: 'Setting layout',
15
+ ApplyPivotLayout: 'Apply pivot layout',
16
+ ApplyTableLayout: 'Apply table layout',
17
+ },
18
+ },
19
+ Runtime: {
20
+ track: 'Runtime',
21
+ labels: {
22
+ SetLayout: 'Setting layout',
23
+ },
24
+ },
25
+ Redux: {
26
+ track: 'Redux',
27
+ labels: {
28
+ Action: 'Action',
29
+ },
30
+ },
31
+ };
@@ -0,0 +1,12 @@
1
+ export type PerfMarkerDetails = {
2
+ name: string;
3
+ value: string | number | boolean;
4
+ }[];
5
+ export interface PerfMarker {
6
+ start(options?: {
7
+ details?: PerfMarkerDetails;
8
+ }): PerfMarker;
9
+ end(options?: {
10
+ details?: PerfMarkerDetails;
11
+ }): PerfMarker;
12
+ }
@@ -0,0 +1 @@
1
+ export {};