@backstage/plugin-search-react 1.4.0-next.2 → 1.5.0-next.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.
package/dist/index.esm.js CHANGED
@@ -1,20 +1,21 @@
1
- import { createApiRef, AnalyticsContext, useApi, useAnalytics, configApiRef } from '@backstage/core-plugin-api';
2
- import React, { useMemo, useContext, useState, useCallback, useEffect, forwardRef, useRef } from 'react';
3
- import { makeStyles, InputBase, InputAdornment, IconButton, CircularProgress, ListItemIcon, ListItemText, TextField, Chip, FormControl, FormLabel, FormControlLabel, Checkbox, InputLabel, Select, MenuItem, Button, TablePagination, ListItem, Box, Divider, List, Typography, ListSubheader, Menu } from '@material-ui/core';
1
+ import { createApiRef, AnalyticsContext, useApi, useAnalytics, configApiRef, createReactExtension, useElementFilter, getComponentData } from '@backstage/core-plugin-api';
2
+ import React, { useMemo, useContext, useState, useCallback, useEffect, forwardRef, useRef, createElement, Fragment, isValidElement, cloneElement } from 'react';
3
+ import { makeStyles, InputBase, InputAdornment, IconButton, CircularProgress, ListItemIcon, ListItemText, TextField, Chip, FormControl, FormLabel, FormControlLabel, Checkbox, InputLabel, Select, MenuItem, TablePagination, ListItem, Box, Divider, List, Typography as Typography$1, ListSubheader, Menu, Button } from '@material-ui/core';
4
4
  import useDebounce from 'react-use/lib/useDebounce';
5
5
  import SearchIcon from '@material-ui/icons/Search';
6
6
  import ClearButton from '@material-ui/icons/Clear';
7
- import { isEqual } from 'lodash';
7
+ import { isEqual, isFunction } from 'lodash';
8
8
  import useAsync from 'react-use/lib/useAsync';
9
9
  import usePrevious from 'react-use/lib/usePrevious';
10
10
  import { createVersionedContext, createVersionedValueMap } from '@backstage/version-bridge';
11
11
  import { Autocomplete } from '@material-ui/lab';
12
12
  import useAsyncFn from 'react-use/lib/useAsyncFn';
13
13
  import { Progress, ResponseErrorPanel, EmptyState, Link } from '@backstage/core-components';
14
- import ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';
15
- import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';
14
+ import Typography from '@material-ui/core/Typography';
16
15
  import qs from 'qs';
17
16
  import AddIcon from '@material-ui/icons/Add';
17
+ import ArrowRightIcon from '@material-ui/icons/ArrowForwardIos';
18
+ import ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';
18
19
 
19
20
  const searchApiRef = createApiRef({
20
21
  id: "plugin.search.queryservice"
@@ -621,96 +622,6 @@ SearchFilter.Checkbox = (props) => /* @__PURE__ */ React.createElement(SearchFil
621
622
  SearchFilter.Select = (props) => /* @__PURE__ */ React.createElement(SearchFilter, { ...props, component: SelectFilter });
622
623
  SearchFilter.Autocomplete = (props) => /* @__PURE__ */ React.createElement(SearchFilter, { ...props, component: AutocompleteFilter });
623
624
 
624
- const SearchResultContext = (props) => {
625
- const { children } = props;
626
- const context = useSearch();
627
- const state = context.result;
628
- return children(state);
629
- };
630
- const SearchResultApi = (props) => {
631
- const { query, children } = props;
632
- const searchApi = useApi(searchApiRef);
633
- const state = useAsync(() => {
634
- const { term = "", types = [], filters = {}, ...rest } = query;
635
- return searchApi.query({ ...rest, term, types, filters });
636
- }, [query]);
637
- return children(state);
638
- };
639
- const SearchResultState = (props) => {
640
- const { query, children } = props;
641
- return query ? /* @__PURE__ */ React.createElement(SearchResultApi, { query }, children) : /* @__PURE__ */ React.createElement(SearchResultContext, null, children);
642
- };
643
- const SearchResultComponent = (props) => {
644
- const {
645
- query,
646
- children,
647
- noResultsComponent = /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Sorry, no results were found" })
648
- } = props;
649
- return /* @__PURE__ */ React.createElement(SearchResultState, { query }, ({ loading, error, value }) => {
650
- if (loading) {
651
- return /* @__PURE__ */ React.createElement(Progress, null);
652
- }
653
- if (error) {
654
- return /* @__PURE__ */ React.createElement(
655
- ResponseErrorPanel,
656
- {
657
- title: "Error encountered while fetching search results",
658
- error
659
- }
660
- );
661
- }
662
- if (!(value == null ? void 0 : value.results.length)) {
663
- return noResultsComponent;
664
- }
665
- return children(value);
666
- });
667
- };
668
- const SearchResult = (props) => /* @__PURE__ */ React.createElement(
669
- AnalyticsContext,
670
- {
671
- attributes: {
672
- pluginId: "search",
673
- extension: "SearchResult"
674
- }
675
- },
676
- /* @__PURE__ */ React.createElement(SearchResultComponent, { ...props })
677
- );
678
-
679
- const useStyles$1 = makeStyles((theme) => ({
680
- root: {
681
- display: "flex",
682
- justifyContent: "space-between",
683
- gap: theme.spacing(2),
684
- margin: theme.spacing(2, 0)
685
- }
686
- }));
687
- const SearchResultPager = () => {
688
- const { fetchNextPage, fetchPreviousPage } = useSearch();
689
- const classes = useStyles$1();
690
- if (!fetchNextPage && !fetchPreviousPage) {
691
- return /* @__PURE__ */ React.createElement(React.Fragment, null);
692
- }
693
- return /* @__PURE__ */ React.createElement("nav", { "aria-label": "pagination navigation", className: classes.root }, /* @__PURE__ */ React.createElement(
694
- Button,
695
- {
696
- "aria-label": "previous page",
697
- disabled: !fetchPreviousPage,
698
- onClick: fetchPreviousPage,
699
- startIcon: /* @__PURE__ */ React.createElement(ArrowBackIosIcon, null)
700
- },
701
- "Previous"
702
- ), /* @__PURE__ */ React.createElement(
703
- Button,
704
- {
705
- "aria-label": "next page",
706
- disabled: !fetchNextPage,
707
- onClick: fetchNextPage,
708
- endIcon: /* @__PURE__ */ React.createElement(ArrowForwardIosIcon, null)
709
- },
710
- "Next"
711
- ));
712
- };
713
-
714
625
  const encodePageCursor = (pageCursor) => {
715
626
  return Buffer.from(pageCursor.toString(), "utf-8").toString("base64");
716
627
  };
@@ -775,26 +686,79 @@ const SearchPagination = (props) => {
775
686
  );
776
687
  };
777
688
 
689
+ const SearchResultContext = (props) => {
690
+ const { children } = props;
691
+ const context = useSearch();
692
+ const { result: state, ...query } = context;
693
+ return children(state, query);
694
+ };
695
+ const SearchResultApi = (props) => {
696
+ const { query, children } = props;
697
+ const searchApi = useApi(searchApiRef);
698
+ const state = useAsync(() => {
699
+ const { term = "", types = [], filters = {}, ...rest } = query;
700
+ return searchApi.query({ ...rest, term, types, filters });
701
+ }, [query]);
702
+ return children(state, query);
703
+ };
704
+ const SearchResultState = (props) => {
705
+ const { query, children } = props;
706
+ return query ? /* @__PURE__ */ React.createElement(SearchResultApi, { query }, children) : /* @__PURE__ */ React.createElement(SearchResultContext, null, children);
707
+ };
708
+ const SearchResultComponent = (props) => {
709
+ const {
710
+ query,
711
+ children,
712
+ noResultsComponent = /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Sorry, no results were found" }),
713
+ ...rest
714
+ } = props;
715
+ return /* @__PURE__ */ React.createElement(SearchResultState, { query }, ({ loading, error, value }) => {
716
+ if (loading) {
717
+ return /* @__PURE__ */ React.createElement(Progress, null);
718
+ }
719
+ if (error) {
720
+ return /* @__PURE__ */ React.createElement(
721
+ ResponseErrorPanel,
722
+ {
723
+ title: "Error encountered while fetching search results",
724
+ error
725
+ }
726
+ );
727
+ }
728
+ if (!(value == null ? void 0 : value.results.length)) {
729
+ return noResultsComponent;
730
+ }
731
+ if (isFunction(children)) {
732
+ return children(value);
733
+ }
734
+ return /* @__PURE__ */ React.createElement(SearchResultListItemExtensions, { ...rest, results: value.results }, children);
735
+ });
736
+ };
737
+ const SearchResult = (props) => /* @__PURE__ */ React.createElement(
738
+ AnalyticsContext,
739
+ {
740
+ attributes: {
741
+ pluginId: "search",
742
+ extension: "SearchResult"
743
+ }
744
+ },
745
+ /* @__PURE__ */ React.createElement(SearchResultComponent, { ...props })
746
+ );
747
+
778
748
  const DefaultResultListItemComponent = ({
779
749
  result,
780
750
  highlight,
781
- rank,
782
751
  icon,
783
752
  secondaryAction,
784
753
  lineClamp = 5
785
754
  }) => {
786
- const analytics = useAnalytics();
787
- const handleClick = () => {
788
- analytics.captureEvent("discover", result.title, {
789
- attributes: { to: result.location },
790
- value: rank
791
- });
792
- };
755
+ if (!result)
756
+ return null;
793
757
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ListItem, { alignItems: "center" }, icon && /* @__PURE__ */ React.createElement(ListItemIcon, null, icon), /* @__PURE__ */ React.createElement(
794
758
  ListItemText,
795
759
  {
796
760
  primaryTypographyProps: { variant: "h6" },
797
- primary: /* @__PURE__ */ React.createElement(Link, { noTrack: true, to: result.location, onClick: handleClick }, (highlight == null ? void 0 : highlight.fields.title) ? /* @__PURE__ */ React.createElement(
761
+ primary: /* @__PURE__ */ React.createElement(Link, { noTrack: true, to: result.location }, (highlight == null ? void 0 : highlight.fields.title) ? /* @__PURE__ */ React.createElement(
798
762
  HighlightedSearchResultText,
799
763
  {
800
764
  text: (highlight == null ? void 0 : highlight.fields.title) || "",
@@ -803,8 +767,9 @@ const DefaultResultListItemComponent = ({
803
767
  }
804
768
  ) : result.title),
805
769
  secondary: /* @__PURE__ */ React.createElement(
806
- "span",
770
+ Typography,
807
771
  {
772
+ component: "span",
808
773
  style: {
809
774
  display: "-webkit-box",
810
775
  WebkitBoxOrient: "vertical",
@@ -839,8 +804,8 @@ const HigherOrderDefaultResultListItem = (props) => {
839
804
 
840
805
  const SearchResultListLayout = (props) => {
841
806
  const {
842
- loading,
843
807
  error,
808
+ loading,
844
809
  resultItems,
845
810
  renderResultItem = (resultItem) => /* @__PURE__ */ React.createElement(
846
811
  HigherOrderDefaultResultListItem,
@@ -849,19 +814,30 @@ const SearchResultListLayout = (props) => {
849
814
  result: resultItem.document
850
815
  }
851
816
  ),
852
- noResultsComponent = /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Sorry, no results were found" }),
817
+ disableRenderingWithNoResults,
818
+ noResultsComponent = disableRenderingWithNoResults ? null : /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Sorry, no results were found" }),
853
819
  ...rest
854
820
  } = props;
855
- return /* @__PURE__ */ React.createElement(List, { ...rest }, loading ? /* @__PURE__ */ React.createElement(Progress, null) : null, !loading && error ? /* @__PURE__ */ React.createElement(
856
- ResponseErrorPanel,
857
- {
858
- title: "Error encountered while fetching search results",
859
- error
860
- }
861
- ) : null, !loading && !error && (resultItems == null ? void 0 : resultItems.length) ? resultItems.map(renderResultItem) : null, !loading && !error && !(resultItems == null ? void 0 : resultItems.length) ? /* @__PURE__ */ React.createElement(ListItem, null, noResultsComponent) : null);
821
+ if (loading) {
822
+ return /* @__PURE__ */ React.createElement(Progress, null);
823
+ }
824
+ if (error) {
825
+ return /* @__PURE__ */ React.createElement(
826
+ ResponseErrorPanel,
827
+ {
828
+ title: "Error encountered while fetching search results",
829
+ error
830
+ }
831
+ );
832
+ }
833
+ if (!(resultItems == null ? void 0 : resultItems.length)) {
834
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, noResultsComponent);
835
+ }
836
+ return /* @__PURE__ */ React.createElement(List, { ...rest }, resultItems.map(renderResultItem));
862
837
  };
863
838
  const SearchResultList = (props) => {
864
- const { query, disableRenderingWithNoResults, ...rest } = props;
839
+ const { query, renderResultItem, children, ...rest } = props;
840
+ const defaultRenderResultItem = useSearchResultListItemExtensions(children);
865
841
  return /* @__PURE__ */ React.createElement(
866
842
  AnalyticsContext,
867
843
  {
@@ -870,25 +846,20 @@ const SearchResultList = (props) => {
870
846
  extension: "SearchResultList"
871
847
  }
872
848
  },
873
- /* @__PURE__ */ React.createElement(SearchResultState, { query }, ({ loading, error, value }) => {
874
- var _a;
875
- if (!((_a = value == null ? void 0 : value.results) == null ? void 0 : _a.length) && disableRenderingWithNoResults) {
876
- return null;
849
+ /* @__PURE__ */ React.createElement(SearchResultState, { query }, ({ loading, error, value }) => /* @__PURE__ */ React.createElement(
850
+ SearchResultListLayout,
851
+ {
852
+ ...rest,
853
+ error,
854
+ loading,
855
+ resultItems: value == null ? void 0 : value.results,
856
+ renderResultItem: renderResultItem != null ? renderResultItem : defaultRenderResultItem
877
857
  }
878
- return /* @__PURE__ */ React.createElement(
879
- SearchResultListLayout,
880
- {
881
- ...rest,
882
- loading,
883
- error,
884
- resultItems: value == null ? void 0 : value.results
885
- }
886
- );
887
- })
858
+ ))
888
859
  );
889
860
  };
890
861
 
891
- const useStyles = makeStyles((theme) => ({
862
+ const useStyles$1 = makeStyles((theme) => ({
892
863
  listSubheader: {
893
864
  display: "flex",
894
865
  alignItems: "center"
@@ -917,7 +888,7 @@ const useStyles = makeStyles((theme) => ({
917
888
  }
918
889
  }));
919
890
  const SearchResultGroupFilterFieldLayout = (props) => {
920
- const classes = useStyles();
891
+ const classes = useStyles$1();
921
892
  const { label, children, ...rest } = props;
922
893
  return /* @__PURE__ */ React.createElement(
923
894
  Chip,
@@ -956,7 +927,7 @@ const SearchResultGroupTextFilterField = (props) => {
956
927
  [onChange]
957
928
  );
958
929
  return /* @__PURE__ */ React.createElement(SearchResultGroupFilterFieldLayout, { label, onDelete }, /* @__PURE__ */ React.createElement(
959
- Typography,
930
+ Typography$1,
960
931
  {
961
932
  role: "textbox",
962
933
  component: "span",
@@ -1009,15 +980,15 @@ const SearchResultGroupSelectFilterField = (props) => {
1009
980
  ));
1010
981
  };
1011
982
  function SearchResultGroupLayout(props) {
1012
- const classes = useStyles();
983
+ const classes = useStyles$1();
1013
984
  const [anchorEl, setAnchorEl] = useState(null);
1014
985
  const {
1015
- loading,
1016
986
  error,
987
+ loading,
1017
988
  icon,
1018
989
  title,
1019
990
  titleProps = {},
1020
- link = /* @__PURE__ */ React.createElement(React.Fragment, null, "See all", /* @__PURE__ */ React.createElement(ArrowForwardIosIcon, { className: classes.listSubheaderLinkIcon })),
991
+ link = /* @__PURE__ */ React.createElement(React.Fragment, null, "See all", /* @__PURE__ */ React.createElement(ArrowRightIcon, { className: classes.listSubheaderLinkIcon })),
1021
992
  linkProps = {},
1022
993
  filterOptions,
1023
994
  renderFilterOption = (filterOption) => /* @__PURE__ */ React.createElement(MenuItem, { key: String(filterOption), value: String(filterOption) }, filterOption),
@@ -1031,7 +1002,8 @@ function SearchResultGroupLayout(props) {
1031
1002
  result: resultItem.document
1032
1003
  }
1033
1004
  ),
1034
- noResultsComponent = /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Sorry, no results were found" }),
1005
+ disableRenderingWithNoResults,
1006
+ noResultsComponent = disableRenderingWithNoResults ? null : /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Sorry, no results were found" }),
1035
1007
  ...rest
1036
1008
  } = props;
1037
1009
  const handleClick = useCallback((e) => {
@@ -1040,8 +1012,23 @@ function SearchResultGroupLayout(props) {
1040
1012
  const handleClose = useCallback(() => {
1041
1013
  setAnchorEl(null);
1042
1014
  }, []);
1015
+ if (loading) {
1016
+ return /* @__PURE__ */ React.createElement(Progress, null);
1017
+ }
1018
+ if (error) {
1019
+ return /* @__PURE__ */ React.createElement(
1020
+ ResponseErrorPanel,
1021
+ {
1022
+ title: "Error encountered while fetching search results",
1023
+ error
1024
+ }
1025
+ );
1026
+ }
1027
+ if (!(resultItems == null ? void 0 : resultItems.length)) {
1028
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, noResultsComponent);
1029
+ }
1043
1030
  return /* @__PURE__ */ React.createElement(List, { ...rest }, /* @__PURE__ */ React.createElement(ListSubheader, { className: classes.listSubheader }, icon, /* @__PURE__ */ React.createElement(
1044
- Typography,
1031
+ Typography$1,
1045
1032
  {
1046
1033
  className: classes.listSubheaderName,
1047
1034
  component: "strong",
@@ -1076,30 +1063,11 @@ function SearchResultGroupLayout(props) {
1076
1063
  var _a;
1077
1064
  return (_a = renderFilterField == null ? void 0 : renderFilterField(filterField)) != null ? _a : null;
1078
1065
  }
1079
- ), /* @__PURE__ */ React.createElement(Link, { className: classes.listSubheaderLink, to: "/search", ...linkProps }, link)), loading ? /* @__PURE__ */ React.createElement(Progress, null) : null, !loading && error ? /* @__PURE__ */ React.createElement(
1080
- ResponseErrorPanel,
1081
- {
1082
- title: "Error encountered while fetching search results",
1083
- error
1084
- }
1085
- ) : null, !loading && !error && (resultItems == null ? void 0 : resultItems.length) ? resultItems.map(renderResultItem) : null, !loading && !error && !(resultItems == null ? void 0 : resultItems.length) ? /* @__PURE__ */ React.createElement(ListItem, null, noResultsComponent) : null);
1066
+ ), /* @__PURE__ */ React.createElement(Link, { className: classes.listSubheaderLink, to: "/search", ...linkProps }, link)), resultItems.map(renderResultItem));
1086
1067
  }
1087
1068
  function SearchResultGroup(props) {
1088
- const {
1089
- query,
1090
- linkProps = {},
1091
- disableRenderingWithNoResults,
1092
- ...rest
1093
- } = props;
1094
- const to = `/search?${qs.stringify(
1095
- {
1096
- query: query.term,
1097
- types: query.types,
1098
- filters: query.filters,
1099
- pageCursor: query.pageCursor
1100
- },
1101
- { arrayFormat: "brackets" }
1102
- )}`;
1069
+ const { query, children, renderResultItem, linkProps = {}, ...rest } = props;
1070
+ const defaultRenderResultItem = useSearchResultListItemExtensions(children);
1103
1071
  return /* @__PURE__ */ React.createElement(
1104
1072
  AnalyticsContext,
1105
1073
  {
@@ -1108,25 +1076,164 @@ function SearchResultGroup(props) {
1108
1076
  extension: "SearchResultGroup"
1109
1077
  }
1110
1078
  },
1111
- /* @__PURE__ */ React.createElement(SearchResultState, { query }, ({ loading, error, value }) => {
1112
- var _a, _b;
1113
- if (!((_a = value == null ? void 0 : value.results) == null ? void 0 : _a.length) && disableRenderingWithNoResults) {
1114
- return null;
1115
- }
1079
+ /* @__PURE__ */ React.createElement(SearchResultState, { query }, ({ loading, error, value }, { term, types, pageCursor, filters = {} }) => {
1080
+ const to = `/search?${qs.stringify(
1081
+ { term, types, filters, pageCursor, query: term },
1082
+ { arrayFormat: "brackets" }
1083
+ )}`;
1116
1084
  return /* @__PURE__ */ React.createElement(
1117
1085
  SearchResultGroupLayout,
1118
1086
  {
1119
1087
  ...rest,
1120
- loading,
1121
1088
  error,
1089
+ loading,
1122
1090
  linkProps: { to, ...linkProps },
1091
+ filterFields: Object.keys(filters),
1123
1092
  resultItems: value == null ? void 0 : value.results,
1124
- filterFields: Object.keys((_b = query.filters) != null ? _b : {})
1093
+ renderResultItem: renderResultItem != null ? renderResultItem : defaultRenderResultItem
1125
1094
  }
1126
1095
  );
1127
1096
  })
1128
1097
  );
1129
1098
  }
1130
1099
 
1131
- export { AutocompleteFilter, CheckboxFilter, HigherOrderDefaultResultListItem as DefaultResultListItem, HighlightedSearchResultText, MockSearchApi, SearchAutocomplete, SearchAutocompleteDefaultOption, SearchBar, SearchBarBase, SearchContextProvider, SearchFilter, SearchPagination, SearchPaginationBase, SearchResult, SearchResultApi, SearchResultComponent, SearchResultContext, SearchResultGroup, SearchResultGroupFilterFieldLayout, SearchResultGroupLayout, SearchResultGroupSelectFilterField, SearchResultGroupTextFilterField, SearchResultList, SearchResultListLayout, SearchResultPager, SearchResultState, SelectFilter, searchApiRef, useSearch, useSearchContextCheck };
1100
+ const useStyles = makeStyles((theme) => ({
1101
+ root: {
1102
+ display: "flex",
1103
+ justifyContent: "space-between",
1104
+ gap: theme.spacing(2),
1105
+ margin: theme.spacing(2, 0)
1106
+ }
1107
+ }));
1108
+ const SearchResultPager = () => {
1109
+ const { fetchNextPage, fetchPreviousPage } = useSearch();
1110
+ const classes = useStyles();
1111
+ if (!fetchNextPage && !fetchPreviousPage) {
1112
+ return /* @__PURE__ */ React.createElement(React.Fragment, null);
1113
+ }
1114
+ return /* @__PURE__ */ React.createElement("nav", { "aria-label": "pagination navigation", className: classes.root }, /* @__PURE__ */ React.createElement(
1115
+ Button,
1116
+ {
1117
+ "aria-label": "previous page",
1118
+ disabled: !fetchPreviousPage,
1119
+ onClick: fetchPreviousPage,
1120
+ startIcon: /* @__PURE__ */ React.createElement(ArrowBackIosIcon, null)
1121
+ },
1122
+ "Previous"
1123
+ ), /* @__PURE__ */ React.createElement(
1124
+ Button,
1125
+ {
1126
+ "aria-label": "next page",
1127
+ disabled: !fetchNextPage,
1128
+ onClick: fetchNextPage,
1129
+ endIcon: /* @__PURE__ */ React.createElement(ArrowRightIcon, null)
1130
+ },
1131
+ "Next"
1132
+ ));
1133
+ };
1134
+
1135
+ const SEARCH_RESULT_LIST_ITEM_EXTENSION = "search.results.list.items.extensions.v1";
1136
+ const findSearchResultListItemExtensionElement = (elements, result) => {
1137
+ for (const element of elements) {
1138
+ if (!isValidElement(element))
1139
+ continue;
1140
+ const predicate = getComponentData(
1141
+ element,
1142
+ SEARCH_RESULT_LIST_ITEM_EXTENSION
1143
+ );
1144
+ if (!(predicate == null ? void 0 : predicate(result)))
1145
+ continue;
1146
+ return cloneElement(element, {
1147
+ rank: result.rank,
1148
+ highlight: result.highlight,
1149
+ result: result.document,
1150
+ // Use props in situations where a consumer is manually rendering the extension
1151
+ ...element.props
1152
+ });
1153
+ }
1154
+ return null;
1155
+ };
1156
+ const SearchResultListItemExtension = ({
1157
+ rank,
1158
+ result,
1159
+ noTrack,
1160
+ children
1161
+ }) => {
1162
+ const analytics = useAnalytics();
1163
+ const handleClickCapture = useCallback(() => {
1164
+ if (noTrack)
1165
+ return;
1166
+ if (!result)
1167
+ return;
1168
+ analytics.captureEvent("discover", result.title, {
1169
+ attributes: { to: result.location },
1170
+ value: rank
1171
+ });
1172
+ }, [rank, result, noTrack, analytics]);
1173
+ return /* @__PURE__ */ React.createElement(Box, { role: "button", tabIndex: 0, onClickCapture: handleClickCapture }, children);
1174
+ };
1175
+ const createSearchResultListItemExtension = (options) => {
1176
+ const { name, component, predicate = () => true } = options;
1177
+ return createReactExtension({
1178
+ name,
1179
+ component: {
1180
+ lazy: () => component().then(
1181
+ (type) => (props) => /* @__PURE__ */ React.createElement(
1182
+ SearchResultListItemExtension,
1183
+ {
1184
+ rank: props.rank,
1185
+ result: props.result,
1186
+ noTrack: props.noTrack
1187
+ },
1188
+ createElement(type, props)
1189
+ )
1190
+ )
1191
+ },
1192
+ data: {
1193
+ [SEARCH_RESULT_LIST_ITEM_EXTENSION]: predicate
1194
+ }
1195
+ });
1196
+ };
1197
+ const useSearchResultListItemExtensions = (children) => {
1198
+ const elements = useElementFilter(
1199
+ children,
1200
+ (collection) => {
1201
+ return collection.selectByComponentData({
1202
+ key: SEARCH_RESULT_LIST_ITEM_EXTENSION
1203
+ }).getElements();
1204
+ },
1205
+ [children]
1206
+ );
1207
+ return useCallback(
1208
+ (result, key) => {
1209
+ const element = findSearchResultListItemExtensionElement(
1210
+ elements,
1211
+ result
1212
+ );
1213
+ return /* @__PURE__ */ React.createElement(Fragment, { key }, element != null ? element : /* @__PURE__ */ React.createElement(
1214
+ SearchResultListItemExtension,
1215
+ {
1216
+ rank: result.rank,
1217
+ result: result.document
1218
+ },
1219
+ /* @__PURE__ */ React.createElement(
1220
+ HigherOrderDefaultResultListItem,
1221
+ {
1222
+ rank: result.rank,
1223
+ highlight: result.highlight,
1224
+ result: result.document
1225
+ }
1226
+ )
1227
+ ));
1228
+ },
1229
+ [elements]
1230
+ );
1231
+ };
1232
+ const SearchResultListItemExtensions = (props) => {
1233
+ const { results, children, ...rest } = props;
1234
+ const render = useSearchResultListItemExtensions(children);
1235
+ return /* @__PURE__ */ React.createElement(List, { ...rest }, results.map(render));
1236
+ };
1237
+
1238
+ export { AutocompleteFilter, CheckboxFilter, HigherOrderDefaultResultListItem as DefaultResultListItem, HighlightedSearchResultText, MockSearchApi, SearchAutocomplete, SearchAutocompleteDefaultOption, SearchBar, SearchBarBase, SearchContextProvider, SearchFilter, SearchPagination, SearchPaginationBase, SearchResult, SearchResultApi, SearchResultComponent, SearchResultContext, SearchResultGroup, SearchResultGroupFilterFieldLayout, SearchResultGroupLayout, SearchResultGroupSelectFilterField, SearchResultGroupTextFilterField, SearchResultList, SearchResultListItemExtensions, SearchResultListLayout, SearchResultPager, SearchResultState, SelectFilter, createSearchResultListItemExtension, searchApiRef, useSearch, useSearchContextCheck, useSearchResultListItemExtensions };
1132
1239
  //# sourceMappingURL=index.esm.js.map