@finos/legend-query-builder 4.14.69 → 4.14.71

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 (100) hide show
  1. package/lib/__lib__/QueryBuilderTesting.d.ts +1 -0
  2. package/lib/__lib__/QueryBuilderTesting.d.ts.map +1 -1
  3. package/lib/__lib__/QueryBuilderTesting.js +1 -0
  4. package/lib/__lib__/QueryBuilderTesting.js.map +1 -1
  5. package/lib/components/QueryBuilderConstantExpressionPanel.d.ts.map +1 -1
  6. package/lib/components/QueryBuilderConstantExpressionPanel.js +2 -1
  7. package/lib/components/QueryBuilderConstantExpressionPanel.js.map +1 -1
  8. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts +1 -0
  9. package/lib/components/explorer/QueryBuilderExplorerPanel.d.ts.map +1 -1
  10. package/lib/components/explorer/QueryBuilderExplorerPanel.js +87 -52
  11. package/lib/components/explorer/QueryBuilderExplorerPanel.js.map +1 -1
  12. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts +4 -0
  13. package/lib/components/explorer/QueryBuilderPropertySearchPanel.d.ts.map +1 -1
  14. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js +172 -108
  15. package/lib/components/explorer/QueryBuilderPropertySearchPanel.js.map +1 -1
  16. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.d.ts.map +1 -1
  17. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js +2 -1
  18. package/lib/components/fetch-structure/QueryBuilderPostFilterPanel.js.map +1 -1
  19. package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
  20. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +29 -18
  21. package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
  22. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.d.ts.map +1 -1
  23. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js +13 -4
  24. package/lib/components/fetch-structure/QueryBuilderTDSWindowPanel.js.map +1 -1
  25. package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
  26. package/lib/components/filter/QueryBuilderFilterPanel.js +4 -3
  27. package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
  28. package/lib/components/result/QueryBuilderResultPanel.d.ts +12 -0
  29. package/lib/components/result/QueryBuilderResultPanel.d.ts.map +1 -1
  30. package/lib/components/result/QueryBuilderResultPanel.js +60 -8
  31. package/lib/components/result/QueryBuilderResultPanel.js.map +1 -1
  32. package/lib/components/shared/QueryBuilderFilterHelper.d.ts.map +1 -1
  33. package/lib/components/shared/QueryBuilderFilterHelper.js +3 -0
  34. package/lib/components/shared/QueryBuilderFilterHelper.js.map +1 -1
  35. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts +11 -0
  36. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.d.ts.map +1 -1
  37. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js +6 -3
  38. package/lib/components/shared/QueryBuilderPropertyInfoTooltip.js.map +1 -1
  39. package/lib/graph-manager/QueryBuilderConfig.d.ts +4 -0
  40. package/lib/graph-manager/QueryBuilderConfig.d.ts.map +1 -1
  41. package/lib/graph-manager/QueryBuilderConfig.js +5 -0
  42. package/lib/graph-manager/QueryBuilderConfig.js.map +1 -1
  43. package/lib/index.css +2 -2
  44. package/lib/index.css.map +1 -1
  45. package/lib/package.json +1 -1
  46. package/lib/stores/QueryBuilderConstantsState.d.ts +1 -0
  47. package/lib/stores/QueryBuilderConstantsState.d.ts.map +1 -1
  48. package/lib/stores/QueryBuilderConstantsState.js +6 -1
  49. package/lib/stores/QueryBuilderConstantsState.js.map +1 -1
  50. package/lib/stores/QueryBuilderResultState.d.ts +11 -3
  51. package/lib/stores/QueryBuilderResultState.d.ts.map +1 -1
  52. package/lib/stores/QueryBuilderResultState.js +47 -4
  53. package/lib/stores/QueryBuilderResultState.js.map +1 -1
  54. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts +4 -0
  55. package/lib/stores/QueryBuilderValueSpecificationBuilderHelper.d.ts.map +1 -1
  56. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts +3 -1
  57. package/lib/stores/explorer/QueryBuilderExplorerState.d.ts.map +1 -1
  58. package/lib/stores/explorer/QueryBuilderExplorerState.js +63 -8
  59. package/lib/stores/explorer/QueryBuilderExplorerState.js.map +1 -1
  60. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts +24 -0
  61. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.d.ts.map +1 -0
  62. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js +39 -0
  63. package/lib/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.js.map +1 -0
  64. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts +8 -4
  65. package/lib/stores/explorer/QueryBuilderPropertySearchState.d.ts.map +1 -1
  66. package/lib/stores/explorer/QueryBuilderPropertySearchState.js +204 -114
  67. package/lib/stores/explorer/QueryBuilderPropertySearchState.js.map +1 -1
  68. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.d.ts.map +1 -1
  69. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js +8 -1
  70. package/lib/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.js.map +1 -1
  71. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.d.ts.map +1 -1
  72. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js +12 -1
  73. package/lib/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.js.map +1 -1
  74. package/lib/stores/filter/QueryBuilderFilterState.d.ts +8 -1
  75. package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
  76. package/lib/stores/filter/QueryBuilderFilterState.js +27 -10
  77. package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
  78. package/package.json +8 -8
  79. package/src/__lib__/QueryBuilderTesting.ts +1 -0
  80. package/src/components/QueryBuilderConstantExpressionPanel.tsx +2 -1
  81. package/src/components/explorer/QueryBuilderExplorerPanel.tsx +220 -114
  82. package/src/components/explorer/QueryBuilderPropertySearchPanel.tsx +618 -388
  83. package/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +5 -2
  84. package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +78 -44
  85. package/src/components/fetch-structure/QueryBuilderTDSWindowPanel.tsx +63 -10
  86. package/src/components/filter/QueryBuilderFilterPanel.tsx +4 -2
  87. package/src/components/result/QueryBuilderResultPanel.tsx +207 -20
  88. package/src/components/shared/QueryBuilderFilterHelper.ts +8 -0
  89. package/src/components/shared/QueryBuilderPropertyInfoTooltip.tsx +13 -3
  90. package/src/graph-manager/QueryBuilderConfig.ts +6 -0
  91. package/src/stores/QueryBuilderConstantsState.ts +16 -1
  92. package/src/stores/QueryBuilderResultState.ts +64 -10
  93. package/src/stores/QueryBuilderValueSpecificationBuilderHelper.ts +5 -0
  94. package/src/stores/explorer/QueryBuilderExplorerState.ts +92 -8
  95. package/src/stores/explorer/QueryBuilderFuzzySearchAdvancedConfigState.ts +46 -0
  96. package/src/stores/explorer/QueryBuilderPropertySearchState.ts +280 -142
  97. package/src/stores/fetch-structure/tds/post-filter/QueryBuilderPostFilterState.ts +8 -1
  98. package/src/stores/fetch-structure/tds/projection/QueryBuilderProjectionValueSpecificationBuilder.ts +15 -2
  99. package/src/stores/filter/QueryBuilderFilterState.ts +34 -11
  100. package/tsconfig.json +1 -0
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { forwardRef, useEffect, useRef, useState } from 'react';
17
+ import { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
18
18
  import { observer } from 'mobx-react-lite';
19
19
  import {
20
20
  type TreeNodeContainerProps,
@@ -56,6 +56,8 @@ import {
56
56
  PanelHeaderActionItem,
57
57
  PanelHeaderActions,
58
58
  PanelHeader,
59
+ TimesIcon,
60
+ ClickAwayListener,
59
61
  } from '@finos/legend-art';
60
62
  import {
61
63
  type QueryBuilderExplorerTreeDragSource,
@@ -64,8 +66,6 @@ import {
64
66
  QueryBuilderExplorerTreeRootNodeData,
65
67
  QueryBuilderExplorerTreePropertyNodeData,
66
68
  QueryBuilderExplorerTreeSubTypeNodeData,
67
- getQueryBuilderPropertyNodeData,
68
- getQueryBuilderSubTypeNodeData,
69
69
  buildPropertyExpressionFromExplorerTreeNodeData,
70
70
  } from '../../stores/explorer/QueryBuilderExplorerState.js';
71
71
  import { useDrag } from 'react-dnd';
@@ -86,17 +86,16 @@ import {
86
86
  PRIMITIVE_TYPE,
87
87
  Enumeration,
88
88
  TYPE_CAST_TOKEN,
89
- getAllClassDerivedProperties,
90
89
  getMultiplicityDescription,
91
- getAllClassProperties,
92
- getAllOwnClassProperties,
93
90
  isElementDeprecated,
94
91
  } from '@finos/legend-graph';
95
92
  import { useApplicationStore } from '@finos/legend-application';
96
93
  import { QUERY_BUILDER_TEST_ID } from '../../__lib__/QueryBuilderTesting.js';
97
94
  import {
95
+ debounce,
98
96
  filterByType,
99
97
  guaranteeNonNullable,
98
+ isNonNullable,
100
99
  prettyCONSTName,
101
100
  } from '@finos/legend-shared';
102
101
  import { QueryBuilderPropertySearchPanel } from './QueryBuilderPropertySearchPanel.js';
@@ -105,6 +104,7 @@ import { QueryBuilderSimpleProjectionColumnState } from '../../stores/fetch-stru
105
104
  import { getClassPropertyIcon } from '@finos/legend-lego/graph-editor';
106
105
  import { QueryBuilderRootClassInfoTooltip } from '../shared/QueryBuilderRootClassInfoTooltip.js';
107
106
  import { QueryBuilderTelemetryHelper } from '../../__lib__/QueryBuilderTelemetryHelper.js';
107
+ import type { QueryBuilderPropertySearchState } from '../../stores/explorer/QueryBuilderPropertySearchState.js';
108
108
 
109
109
  export const checkForDeprecatedNode = (
110
110
  node: QueryBuilderExplorerTreeNodeData,
@@ -163,55 +163,81 @@ export const QueryBuilderSubclassInfoTooltip: React.FC<{
163
163
  multiplicity: Multiplicity;
164
164
  }> = (props) => {
165
165
  const { subclass, path, isMapped, children, placement, multiplicity } = props;
166
+
167
+ const [open, setIsOpen] = useState(false);
168
+
166
169
  return (
167
- <Tooltip
168
- arrow={true}
169
- {...(placement !== undefined ? { placement } : {})}
170
- classes={{
171
- tooltip: 'query-builder__tooltip',
172
- arrow: 'query-builder__tooltip__arrow',
173
- tooltipPlacementRight: 'query-builder__tooltip--right',
174
- }}
175
- TransitionProps={{
176
- // disable transition
177
- // NOTE: somehow, this is the only workaround we have, if for example
178
- // we set `appear = true`, the tooltip will jump out of position
179
- timeout: 0,
180
- }}
181
- title={
182
- <div className="query-builder__tooltip__content">
183
- <div className="query-builder__tooltip__item">
184
- <div className="query-builder__tooltip__item__label">Type</div>
185
- <div className="query-builder__tooltip__item__value">
186
- {subclass.path}
187
- </div>
188
- </div>
189
- <div className="query-builder__tooltip__item">
190
- <div className="query-builder__tooltip__item__label">Path</div>
191
- <div className="query-builder__tooltip__item__value">{path}</div>
192
- </div>
193
- <div className="query-builder__tooltip__item">
194
- <div className="query-builder__tooltip__item__label">
195
- Multiplicity
196
- </div>
197
- <div className="query-builder__tooltip__item__value">
198
- {getMultiplicityDescription(multiplicity)}
199
- </div>
200
- </div>
201
- <div className="query-builder__tooltip__item">
202
- <div className="query-builder__tooltip__item__label">Mapped</div>
203
- <div className="query-builder__tooltip__item__value">
204
- {isMapped ? 'Yes' : 'No'}
170
+ <ClickAwayListener
171
+ onClickAway={() => setIsOpen(false)}
172
+ mouseEvent="onMouseDown"
173
+ >
174
+ <div>
175
+ <Tooltip
176
+ arrow={true}
177
+ {...(placement !== undefined ? { placement } : {})}
178
+ classes={{
179
+ tooltip: 'query-builder__tooltip',
180
+ arrow: 'query-builder__tooltip__arrow',
181
+ tooltipPlacementRight: 'query-builder__tooltip--right',
182
+ }}
183
+ open={open}
184
+ onClose={() => setIsOpen(false)}
185
+ TransitionProps={{
186
+ // disable transition
187
+ // NOTE: somehow, this is the only workaround we have, if for example
188
+ // we set `appear = true`, the tooltip will jump out of position
189
+ timeout: 0,
190
+ }}
191
+ disableFocusListener={true}
192
+ disableHoverListener={true}
193
+ disableTouchListener={true}
194
+ title={
195
+ <div className="query-builder__tooltip__content">
196
+ <div className="query-builder__tooltip__item">
197
+ <div className="query-builder__tooltip__item__label">Type</div>
198
+ <div className="query-builder__tooltip__item__value">
199
+ {subclass.path}
200
+ </div>
201
+ </div>
202
+ <div className="query-builder__tooltip__item">
203
+ <div className="query-builder__tooltip__item__label">Path</div>
204
+ <div className="query-builder__tooltip__item__value">
205
+ {path}
206
+ </div>
207
+ </div>
208
+ <div className="query-builder__tooltip__item">
209
+ <div className="query-builder__tooltip__item__label">
210
+ Multiplicity
211
+ </div>
212
+ <div className="query-builder__tooltip__item__value">
213
+ {getMultiplicityDescription(multiplicity)}
214
+ </div>
215
+ </div>
216
+ <div className="query-builder__tooltip__item">
217
+ <div className="query-builder__tooltip__item__label">
218
+ Mapped
219
+ </div>
220
+ <div className="query-builder__tooltip__item__value">
221
+ {isMapped ? 'Yes' : 'No'}
222
+ </div>
223
+ </div>
224
+ <QueryBuilderTaggedValueInfoTooltip
225
+ taggedValues={subclass.taggedValues}
226
+ />
205
227
  </div>
228
+ }
229
+ >
230
+ <div
231
+ onClick={(event: React.MouseEvent) => {
232
+ setIsOpen(!open);
233
+ event.stopPropagation();
234
+ }}
235
+ >
236
+ {children}
206
237
  </div>
207
- <QueryBuilderTaggedValueInfoTooltip
208
- taggedValues={subclass.taggedValues}
209
- />
210
- </div>
211
- }
212
- >
213
- {children}
214
- </Tooltip>
238
+ </Tooltip>
239
+ </div>
240
+ </ClickAwayListener>
215
241
  );
216
242
  };
217
243
 
@@ -782,43 +808,9 @@ const QueryBuilderExplorerTree = observer(
782
808
  const treeData = explorerState.nonNullableTreeData;
783
809
  const onNodeSelect = (node: QueryBuilderExplorerTreeNodeData): void => {
784
810
  if (node.childrenIds.length) {
785
- node.isOpen = !node.isOpen;
786
- if (
787
- node.isOpen &&
788
- (node instanceof QueryBuilderExplorerTreePropertyNodeData ||
789
- node instanceof QueryBuilderExplorerTreeSubTypeNodeData) &&
790
- node.type instanceof Class
791
- ) {
792
- (node instanceof QueryBuilderExplorerTreeSubTypeNodeData
793
- ? getAllOwnClassProperties(node.type)
794
- : getAllClassProperties(node.type).concat(
795
- getAllClassDerivedProperties(node.type),
796
- )
797
- ).forEach((property) => {
798
- const propertyTreeNodeData = getQueryBuilderPropertyNodeData(
799
- property,
800
- node,
801
- guaranteeNonNullable(
802
- explorerState.mappingModelCoverageAnalysisResult,
803
- ),
804
- );
805
- if (propertyTreeNodeData) {
806
- treeData.nodes.set(propertyTreeNodeData.id, propertyTreeNodeData);
807
- }
808
- });
809
- node.type._subclasses.forEach((subclass) => {
810
- const subTypeTreeNodeData = getQueryBuilderSubTypeNodeData(
811
- subclass,
812
- node,
813
- guaranteeNonNullable(
814
- explorerState.mappingModelCoverageAnalysisResult,
815
- ),
816
- );
817
- treeData.nodes.set(subTypeTreeNodeData.id, subTypeTreeNodeData);
818
- });
819
- }
811
+ node.setIsOpen(!node.isOpen);
812
+ explorerState.generateOpenNodeChildren(node);
820
813
  }
821
- explorerState.refreshTree();
822
814
  };
823
815
  const getChildNodes = (
824
816
  node: QueryBuilderExplorerTreeNodeData,
@@ -860,19 +852,150 @@ const QueryBuilderExplorerTree = observer(
860
852
  },
861
853
  );
862
854
 
855
+ export const QUERY_BUILDER_EXPLORER_SEARCH_INPUT_NAME =
856
+ 'query-builder-explorer-search-input';
857
+
858
+ const QUERY_BUILDER_PROPERTY_SEARCH_MIN_SEARCH_LENGTH = 2;
859
+
860
+ const QueryBuilderExplorerSearchInput = observer(
861
+ forwardRef<
862
+ HTMLInputElement,
863
+ { propertySearchState: QueryBuilderPropertySearchState }
864
+ >(function QueryBuilderExplorerSearchInput(props, ref) {
865
+ const { propertySearchState } = props;
866
+
867
+ // initialize search state on mount
868
+ useEffect(() => {
869
+ if (
870
+ !propertySearchState.initializationState.hasSucceeded &&
871
+ !propertySearchState.initializationState.isInProgress &&
872
+ isNonNullable(
873
+ propertySearchState.queryBuilderState.explorerState.treeData,
874
+ )
875
+ ) {
876
+ propertySearchState
877
+ .initialize()
878
+ .catch(
879
+ propertySearchState.queryBuilderState.applicationStore
880
+ .alertUnhandledError,
881
+ );
882
+ }
883
+ }, [
884
+ propertySearchState,
885
+ propertySearchState.initializationState,
886
+ propertySearchState.queryBuilderState.explorerState.treeData,
887
+ ]);
888
+
889
+ // search text
890
+ const debouncedSearchProperty = useMemo(
891
+ () => debounce(() => propertySearchState.search(), 100),
892
+ [propertySearchState],
893
+ );
894
+
895
+ const onSearchPropertyTextChange: React.ChangeEventHandler<
896
+ HTMLInputElement
897
+ > = (event) => {
898
+ (async () => {
899
+ propertySearchState.setSearchText(event.target.value);
900
+ if (
901
+ event.target.value.length >=
902
+ QUERY_BUILDER_PROPERTY_SEARCH_MIN_SEARCH_LENGTH
903
+ ) {
904
+ if (
905
+ propertySearchState.queryBuilderState.explorerState.treeData &&
906
+ !propertySearchState.isSearchPanelOpen
907
+ ) {
908
+ propertySearchState.setIsSearchPanelOpen(true);
909
+ if (
910
+ !propertySearchState.initializationState.hasSucceeded &&
911
+ !propertySearchState.initializationState.isInProgress
912
+ ) {
913
+ await propertySearchState.initialize();
914
+ }
915
+ }
916
+ await debouncedSearchProperty();
917
+ } else {
918
+ propertySearchState.setIsSearchPanelOpen(false);
919
+ }
920
+ })().catch(
921
+ propertySearchState.queryBuilderState.applicationStore
922
+ .alertUnhandledError,
923
+ );
924
+ };
925
+
926
+ // search actions
927
+ const clearSearch = (): void => {
928
+ propertySearchState.resetSearch();
929
+ };
930
+
931
+ return (
932
+ <div className="query-builder__explorer__property-search__input__container">
933
+ <input
934
+ ref={ref}
935
+ name={QUERY_BUILDER_EXPLORER_SEARCH_INPUT_NAME}
936
+ className={clsx(
937
+ 'query-builder__explorer__property-search__input input--dark',
938
+ {
939
+ 'query-builder__explorer__property-search__input--searching':
940
+ propertySearchState.searchText,
941
+ },
942
+ )}
943
+ spellCheck={false}
944
+ onChange={onSearchPropertyTextChange}
945
+ onKeyDown={(event): void => {
946
+ if (event.key === 'Escape') {
947
+ clearSearch();
948
+ propertySearchState.setIsSearchPanelOpen(false);
949
+ }
950
+ }}
951
+ value={propertySearchState.searchText}
952
+ placeholder="One or more terms, ESC to clear"
953
+ />
954
+ {propertySearchState.searchText.length >=
955
+ QUERY_BUILDER_PROPERTY_SEARCH_MIN_SEARCH_LENGTH && (
956
+ <div className="query-builder__explorer__property-search__input__search__count">
957
+ {propertySearchState.filteredSearchResults.length +
958
+ (propertySearchState.isOverSearchLimit &&
959
+ propertySearchState.filteredSearchResults.length !== 0
960
+ ? '+'
961
+ : '')}
962
+ </div>
963
+ )}
964
+ {!propertySearchState.searchText ? (
965
+ <>
966
+ <div className="query-builder__explorer__property-search__input__search__icon">
967
+ <SearchIcon />
968
+ </div>
969
+ </>
970
+ ) : (
971
+ <button
972
+ className="query-builder__explorer__property-search__input__clear-btn"
973
+ tabIndex={-1}
974
+ onClick={clearSearch}
975
+ title="Clear"
976
+ >
977
+ <TimesIcon />
978
+ </button>
979
+ )}
980
+ </div>
981
+ );
982
+ }),
983
+ );
984
+
863
985
  export const QueryBuilderExplorerPanel = observer(
864
986
  (props: { queryBuilderState: QueryBuilderState }) => {
865
987
  const { queryBuilderState } = props;
866
- const searchButtonRef = useRef<HTMLButtonElement>(null);
988
+ const searchInputRef = useRef<HTMLInputElement>(null);
867
989
  const explorerState = queryBuilderState.explorerState;
868
990
  const propertySearchPanelState = explorerState.propertySearchState;
869
991
  const applicationStore = useApplicationStore();
870
992
  const collapseTree = (): void => {
871
993
  if (explorerState.treeData) {
872
994
  Array.from(explorerState.treeData.nodes.values()).forEach((node) => {
873
- node.isOpen = false;
995
+ if (!(node instanceof QueryBuilderExplorerTreeRootNodeData)) {
996
+ node.setIsOpen(false);
997
+ }
874
998
  });
875
- explorerState.refreshTree();
876
999
  }
877
1000
  };
878
1001
  const toggleShowUnmappedProperties = (): void => {
@@ -891,16 +1014,6 @@ export const QueryBuilderExplorerPanel = observer(
891
1014
  explorerState.setHighlightUsedProperties(
892
1015
  !explorerState.highlightUsedProperties,
893
1016
  );
894
- const togglePropertySearch = (): void => {
895
- if (explorerState.treeData) {
896
- if (!propertySearchPanelState.isSearchPanelOpen) {
897
- propertySearchPanelState.setIsSearchPanelOpen(true);
898
- propertySearchPanelState.initialize();
899
- } else {
900
- propertySearchPanelState.setIsSearchPanelOpen(false);
901
- }
902
- }
903
- };
904
1017
 
905
1018
  useEffect(() => {
906
1019
  flowResult(explorerState.analyzeMappingModelCoverage()).catch(
@@ -919,19 +1032,11 @@ export const QueryBuilderExplorerPanel = observer(
919
1032
  })}
920
1033
  >
921
1034
  <PanelHeader title="explorer">
1035
+ <QueryBuilderExplorerSearchInput
1036
+ propertySearchState={propertySearchPanelState}
1037
+ ref={searchInputRef}
1038
+ />
922
1039
  <PanelHeaderActions>
923
- <button
924
- ref={searchButtonRef}
925
- className={clsx('panel__header__action', {
926
- 'query-builder__explorer__header__action--active':
927
- propertySearchPanelState.isSearchPanelOpen,
928
- })}
929
- onClick={togglePropertySearch}
930
- tabIndex={-1}
931
- title="Toggle property search"
932
- >
933
- <SearchIcon />
934
- </button>
935
1040
  <PanelHeaderActionItem onClick={collapseTree} title="Collapse Tree">
936
1041
  <CompressIcon />
937
1042
  </PanelHeaderActionItem>
@@ -984,7 +1089,8 @@ export const QueryBuilderExplorerPanel = observer(
984
1089
  {propertySearchPanelState.isSearchPanelOpen && (
985
1090
  <QueryBuilderPropertySearchPanel
986
1091
  queryBuilderState={queryBuilderState}
987
- triggerElement={searchButtonRef.current}
1092
+ triggerElement={searchInputRef.current}
1093
+ clearSearch={() => propertySearchPanelState.resetSearch()}
988
1094
  />
989
1095
  )}
990
1096
  </PanelHeader>