@backstage/plugin-search-react 1.10.0 → 1.10.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @backstage/plugin-search-react
2
2
 
3
+ ## 1.10.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 8947a4e: Skip the very first empty search when going to the landing page
8
+ - Updated dependencies
9
+ - @backstage/frontend-plugin-api@0.13.2
10
+ - @backstage/core-components@0.18.4
11
+ - @backstage/core-plugin-api@1.12.1
12
+ - @backstage/theme@0.7.1
13
+
14
+ ## 1.10.1-next.0
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+ - @backstage/frontend-plugin-api@0.13.2-next.0
20
+ - @backstage/core-plugin-api@1.12.1-next.0
21
+ - @backstage/theme@0.7.1-next.0
22
+ - @backstage/core-components@0.18.4-next.0
23
+ - @backstage/types@1.2.2
24
+ - @backstage/version-bridge@1.0.11
25
+ - @backstage/plugin-search-common@1.2.21
26
+
3
27
  ## 1.10.0
4
28
 
5
29
  ### Minor Changes
package/dist/alpha.d.ts CHANGED
@@ -3,7 +3,6 @@ import * as react from 'react';
3
3
  import { JSX as JSX$1 } from 'react';
4
4
  import { ListItemProps } from '@material-ui/core/ListItem';
5
5
  import { SearchDocument, SearchResult } from '@backstage/plugin-search-common';
6
- import * as _backstage_core_plugin_api_alpha from '@backstage/core-plugin-api/alpha';
7
6
 
8
7
  /** @alpha */
9
8
  type BaseSearchResultListItemProps<T = {}> = T & {
@@ -134,7 +133,7 @@ declare const SearchFilterBlueprint: _backstage_frontend_plugin_api.ExtensionBlu
134
133
  /**
135
134
  * @alpha
136
135
  */
137
- declare const searchReactTranslationRef: _backstage_core_plugin_api_alpha.TranslationRef<"search-react", {
136
+ declare const searchReactTranslationRef: _backstage_frontend_plugin_api.TranslationRef<"search-react", {
138
137
  readonly "searchBar.title": "Search";
139
138
  readonly "searchBar.placeholder": "Search in {{org}}";
140
139
  readonly "searchBar.clearButtonTitle": "Clear";
@@ -148,4 +147,5 @@ declare const searchReactTranslationRef: _backstage_core_plugin_api_alpha.Transl
148
147
  readonly "searchResultPager.previous": "Previous";
149
148
  }>;
150
149
 
151
- export { type BaseSearchResultListItemProps, SearchFilterBlueprint, type SearchFilterBlueprintParams, type SearchFilterExtensionComponent, type SearchFilterExtensionComponentProps, SearchFilterResultTypeBlueprint, type SearchFilterResultTypeBlueprintParams, type SearchResultItemExtensionComponent, type SearchResultItemExtensionPredicate, SearchResultListItemBlueprint, type SearchResultListItemBlueprintParams, searchReactTranslationRef };
150
+ export { SearchFilterBlueprint, SearchFilterResultTypeBlueprint, SearchResultListItemBlueprint, searchReactTranslationRef };
151
+ export type { BaseSearchResultListItemProps, SearchFilterBlueprintParams, SearchFilterExtensionComponent, SearchFilterExtensionComponentProps, SearchFilterResultTypeBlueprintParams, SearchResultItemExtensionComponent, SearchResultItemExtensionPredicate, SearchResultListItemBlueprintParams };
@@ -42,10 +42,20 @@ const useSearchContextValue = (initialValue = defaultInitialSearchState) => {
42
42
  const [pageCursor, setPageCursor] = useState(
43
43
  initialValue.pageCursor
44
44
  );
45
+ const isFirstEmptyMount = useRef(true);
45
46
  const prevTerm = usePrevious(term);
46
47
  const prevFilters = usePrevious(filters);
47
48
  const abortControllerRef = useRef(null);
48
49
  const result = useAsync(async () => {
50
+ if (isFirstEmptyMount.current) {
51
+ if (!term && !types.length && !Object.keys(filters).length) {
52
+ return {
53
+ results: [],
54
+ numberOfResults: 0
55
+ };
56
+ }
57
+ isFirstEmptyMount.current = false;
58
+ }
49
59
  if (abortControllerRef.current) {
50
60
  abortControllerRef.current.abort();
51
61
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SearchContext.esm.js","sources":["../../src/context/SearchContext.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isEqual } from 'lodash';\nimport {\n SetStateAction,\n Dispatch,\n DispatchWithoutAction,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport useAsync, { AsyncState } from 'react-use/esm/useAsync';\nimport usePrevious from 'react-use/esm/usePrevious';\n\nimport {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport { JsonObject } from '@backstage/types';\nimport {\n AnalyticsContext,\n useApi,\n configApiRef,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchResultSet } from '@backstage/plugin-search-common';\n\nimport { searchApiRef } from '../api';\n\n/**\n *\n * @public\n */\nexport type SearchContextValue = {\n result: AsyncState<SearchResultSet>;\n setTerm: Dispatch<SetStateAction<string>>;\n setTypes: Dispatch<SetStateAction<string[]>>;\n setFilters: Dispatch<SetStateAction<JsonObject>>;\n setPageLimit: Dispatch<SetStateAction<number | undefined>>;\n setPageCursor: Dispatch<SetStateAction<string | undefined>>;\n fetchNextPage?: DispatchWithoutAction;\n fetchPreviousPage?: DispatchWithoutAction;\n} & SearchContextState;\n\n/**\n *\n * @public\n */\nexport type SearchContextState = {\n term: string;\n types: string[];\n filters: JsonObject;\n pageLimit?: number;\n pageCursor?: string;\n};\n\nconst SearchContext = createVersionedContext<{\n 1: SearchContextValue;\n}>('search-context');\n\n/**\n * @public\n *\n * React hook which provides the search context\n */\nexport const useSearch = () => {\n const context = useContext(SearchContext);\n if (!context) {\n throw new Error('useSearch must be used within a SearchContextProvider');\n }\n\n const value = context.atVersion(1);\n if (!value) {\n throw new Error('No SearchContext v1 found');\n }\n return value;\n};\n\n/**\n * @public\n *\n * React hook which checks for an existing search context\n */\nexport const useSearchContextCheck = () => {\n const context = useContext(SearchContext);\n return context !== undefined;\n};\n\n/**\n * The initial state of `SearchContextProvider`.\n *\n */\nconst defaultInitialSearchState: SearchContextState = {\n term: '',\n types: [],\n filters: {},\n pageLimit: undefined,\n pageCursor: undefined,\n};\n\nconst useSearchContextValue = (\n initialValue: SearchContextState = defaultInitialSearchState,\n) => {\n const searchApi = useApi(searchApiRef);\n const analytics = useAnalytics();\n\n const [term, setTerm] = useState<string>(initialValue.term);\n const [types, setTypes] = useState<string[]>(initialValue.types);\n const [filters, setFilters] = useState<JsonObject>(initialValue.filters);\n const [pageLimit, setPageLimit] = useState<number | undefined>(\n initialValue.pageLimit,\n );\n const [pageCursor, setPageCursor] = useState<string | undefined>(\n initialValue.pageCursor,\n );\n\n const prevTerm = usePrevious(term);\n const prevFilters = usePrevious(filters);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const result = useAsync(async () => {\n // Here we cancel the previous request before making a new one\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n const resultSet = await searchApi.query(\n {\n term,\n types,\n filters,\n pageLimit,\n pageCursor,\n },\n { signal: controller.signal },\n );\n\n if (term) {\n analytics.captureEvent('search', term, {\n value: resultSet.numberOfResults,\n });\n }\n return resultSet;\n }, [term, types, filters, pageLimit, pageCursor]);\n\n const hasNextPage =\n !result.loading && !result.error && result.value?.nextPageCursor;\n const hasPreviousPage =\n !result.loading && !result.error && result.value?.previousPageCursor;\n\n const fetchNextPage = useCallback(() => {\n setPageCursor(result.value?.nextPageCursor);\n }, [result.value?.nextPageCursor]);\n\n const fetchPreviousPage = useCallback(() => {\n setPageCursor(result.value?.previousPageCursor);\n }, [result.value?.previousPageCursor]);\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n useEffect(() => {\n // Any time a term is reset, we want to start from page 0.\n // Only reset the term if it has been modified by the user at least once, the initial state must not reset the term.\n if (prevTerm !== undefined && term !== prevTerm) {\n setPageCursor(undefined);\n }\n }, [term, prevTerm, setPageCursor]);\n\n useEffect(() => {\n // Any time filters is reset, we want to start from page 0.\n // Only reset the page if it has been modified by the user at least once, the initial state must not reset the page.\n if (prevFilters !== undefined && !isEqual(filters, prevFilters)) {\n setPageCursor(undefined);\n }\n }, [filters, prevFilters, setPageCursor]);\n\n const value: SearchContextValue = {\n result,\n term,\n setTerm,\n types,\n setTypes,\n filters,\n setFilters,\n pageLimit,\n setPageLimit,\n pageCursor,\n setPageCursor,\n fetchNextPage: hasNextPage ? fetchNextPage : undefined,\n fetchPreviousPage: hasPreviousPage ? fetchPreviousPage : undefined,\n };\n\n return value;\n};\n\nexport type LocalSearchContextProps = PropsWithChildren<{\n initialState?: SearchContextState;\n}>;\n\nconst LocalSearchContext = (props: SearchContextProviderProps) => {\n const { initialState, children } = props;\n const value = useSearchContextValue(initialState);\n\n return (\n <AnalyticsContext\n attributes={{ searchTypes: value.types.sort().join(',') }}\n >\n <SearchContext.Provider value={createVersionedValueMap({ 1: value })}>\n {children}\n </SearchContext.Provider>\n </AnalyticsContext>\n );\n};\n\n/**\n * Props for {@link SearchContextProvider}\n *\n * @public\n */\nexport type SearchContextProviderProps =\n | PropsWithChildren<{\n /**\n * State initialized by a local context.\n */\n initialState?: SearchContextState;\n /**\n * Do not create an inheritance from the parent, as a new initial state must be defined in a local context.\n */\n inheritParentContextIfAvailable?: never;\n }>\n | PropsWithChildren<{\n /**\n * Does not accept initial state since it is already initialized by parent context.\n */\n initialState?: never;\n /**\n * If true, don't create a child context if there is a parent one already defined.\n * @remarks Defaults to false.\n */\n inheritParentContextIfAvailable?: boolean;\n }>;\n\n/**\n * @public\n * Search context provider which gives you access to shared state between search components\n */\nexport const SearchContextProvider = (props: SearchContextProviderProps) => {\n const { initialState, inheritParentContextIfAvailable, children } = props;\n const hasParentContext = useSearchContextCheck();\n\n const configApi = useApi(configApiRef);\n\n const propsInitialSearchState = initialState ?? {};\n\n const configInitialSearchState = configApi.has('search.query.pageLimit')\n ? { pageLimit: configApi.getNumber('search.query.pageLimit') }\n : {};\n\n const searchContextInitialState = {\n ...defaultInitialSearchState,\n ...propsInitialSearchState,\n ...configInitialSearchState,\n };\n\n return hasParentContext && inheritParentContextIfAvailable ? (\n <>{children}</>\n ) : (\n <LocalSearchContext initialState={searchContextInitialState}>\n {children}\n </LocalSearchContext>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAyEA,MAAM,aAAA,GAAgB,uBAEnB,gBAAgB,CAAA;AAOZ,MAAM,YAAY,MAAM;AAC7B,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,EACzE;AAEA,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,SAAA,CAAU,CAAC,CAAA;AACjC,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,EAC7C;AACA,EAAA,OAAO,KAAA;AACT;AAOO,MAAM,wBAAwB,MAAM;AACzC,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AACxC,EAAA,OAAO,OAAA,KAAY,MAAA;AACrB;AAMA,MAAM,yBAAA,GAAgD;AAAA,EACpD,IAAA,EAAM,EAAA;AAAA,EACN,OAAO,EAAC;AAAA,EACR,SAAS,EAAC;AAAA,EACV,SAAA,EAAW,MAAA;AAAA,EACX,UAAA,EAAY;AACd,CAAA;AAEA,MAAM,qBAAA,GAAwB,CAC5B,YAAA,GAAmC,yBAAA,KAChC;AACH,EAAA,MAAM,SAAA,GAAY,OAAO,YAAY,CAAA;AACrC,EAAA,MAAM,YAAY,YAAA,EAAa;AAE/B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,QAAA,CAAiB,aAAa,IAAI,CAAA;AAC1D,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAAA,CAAmB,aAAa,KAAK,CAAA;AAC/D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,QAAA,CAAqB,aAAa,OAAO,CAAA;AACvE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAA;AAAA,IAChC,YAAA,CAAa;AAAA,GACf;AACA,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAI,QAAA;AAAA,IAClC,YAAA,CAAa;AAAA,GACf;AAEA,EAAA,MAAM,QAAA,GAAW,YAAY,IAAI,CAAA;AACjC,EAAA,MAAM,WAAA,GAAc,YAAY,OAAO,CAAA;AACvC,EAAA,MAAM,kBAAA,GAAqB,OAA+B,IAAI,CAAA;AAE9D,EAAA,MAAM,MAAA,GAAS,SAAS,YAAY;AAElC,IAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,MAAA,kBAAA,CAAmB,QAAQ,KAAA,EAAM;AAAA,IACnC;AAEA,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,kBAAA,CAAmB,OAAA,GAAU,UAAA;AAE7B,IAAA,MAAM,SAAA,GAAY,MAAM,SAAA,CAAU,KAAA;AAAA,MAChC;AAAA,QACE,IAAA;AAAA,QACA,KAAA;AAAA,QACA,OAAA;AAAA,QACA,SAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,EAAE,MAAA,EAAQ,UAAA,CAAW,MAAA;AAAO,KAC9B;AAEA,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,SAAA,CAAU,YAAA,CAAa,UAAU,IAAA,EAAM;AAAA,QACrC,OAAO,SAAA,CAAU;AAAA,OAClB,CAAA;AAAA,IACH;AACA,IAAA,OAAO,SAAA;AAAA,EACT,GAAG,CAAC,IAAA,EAAM,OAAO,OAAA,EAAS,SAAA,EAAW,UAAU,CAAC,CAAA;AAEhD,EAAA,MAAM,WAAA,GACJ,CAAC,MAAA,CAAO,OAAA,IAAW,CAAC,MAAA,CAAO,KAAA,IAAS,OAAO,KAAA,EAAO,cAAA;AACpD,EAAA,MAAM,eAAA,GACJ,CAAC,MAAA,CAAO,OAAA,IAAW,CAAC,MAAA,CAAO,KAAA,IAAS,OAAO,KAAA,EAAO,kBAAA;AAEpD,EAAA,MAAM,aAAA,GAAgB,YAAY,MAAM;AACtC,IAAA,aAAA,CAAc,MAAA,CAAO,OAAO,cAAc,CAAA;AAAA,EAC5C,CAAA,EAAG,CAAC,MAAA,CAAO,KAAA,EAAO,cAAc,CAAC,CAAA;AAEjC,EAAA,MAAM,iBAAA,GAAoB,YAAY,MAAM;AAC1C,IAAA,aAAA,CAAc,MAAA,CAAO,OAAO,kBAAkB,CAAA;AAAA,EAChD,CAAA,EAAG,CAAC,MAAA,CAAO,KAAA,EAAO,kBAAkB,CAAC,CAAA;AAErC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,QAAA,kBAAA,CAAmB,QAAQ,KAAA,EAAM;AAAA,MACnC;AAAA,IACF,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,SAAA,CAAU,MAAM;AAGd,IAAA,IAAI,QAAA,KAAa,MAAA,IAAa,IAAA,KAAS,QAAA,EAAU;AAC/C,MAAA,aAAA,CAAc,MAAS,CAAA;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,QAAA,EAAU,aAAa,CAAC,CAAA;AAElC,EAAA,SAAA,CAAU,MAAM;AAGd,IAAA,IAAI,gBAAgB,MAAA,IAAa,CAAC,OAAA,CAAQ,OAAA,EAAS,WAAW,CAAA,EAAG;AAC/D,MAAA,aAAA,CAAc,MAAS,CAAA;AAAA,IACzB;AAAA,EACF,CAAA,EAAG,CAAC,OAAA,EAAS,WAAA,EAAa,aAAa,CAAC,CAAA;AAExC,EAAA,MAAM,KAAA,GAA4B;AAAA,IAChC,MAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,YAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA,EAAe,cAAc,aAAA,GAAgB,MAAA;AAAA,IAC7C,iBAAA,EAAmB,kBAAkB,iBAAA,GAAoB;AAAA,GAC3D;AAEA,EAAA,OAAO,KAAA;AACT,CAAA;AAMA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAAsC;AAChE,EAAA,MAAM,EAAE,YAAA,EAAc,QAAA,EAAS,GAAI,KAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,sBAAsB,YAAY,CAAA;AAEhD,EAAA,uBACE,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,UAAA,EAAY,EAAE,WAAA,EAAa,KAAA,CAAM,MAAM,IAAA,EAAK,CAAE,IAAA,CAAK,GAAG,CAAA,EAAE;AAAA,MAExD,QAAA,kBAAA,GAAA,CAAC,aAAA,CAAc,QAAA,EAAd,EAAuB,KAAA,EAAO,uBAAA,CAAwB,EAAE,CAAA,EAAG,KAAA,EAAO,CAAA,EAChE,QAAA,EACH;AAAA;AAAA,GACF;AAEJ,CAAA;AAkCO,MAAM,qBAAA,GAAwB,CAAC,KAAA,KAAsC;AAC1E,EAAA,MAAM,EAAE,YAAA,EAAc,+BAAA,EAAiC,QAAA,EAAS,GAAI,KAAA;AACpE,EAAA,MAAM,mBAAmB,qBAAA,EAAsB;AAE/C,EAAA,MAAM,SAAA,GAAY,OAAO,YAAY,CAAA;AAErC,EAAA,MAAM,uBAAA,GAA0B,gBAAgB,EAAC;AAEjD,EAAA,MAAM,wBAAA,GAA2B,SAAA,CAAU,GAAA,CAAI,wBAAwB,CAAA,GACnE,EAAE,SAAA,EAAW,SAAA,CAAU,SAAA,CAAU,wBAAwB,CAAA,EAAE,GAC3D,EAAC;AAEL,EAAA,MAAM,yBAAA,GAA4B;AAAA,IAChC,GAAG,yBAAA;AAAA,IACH,GAAG,uBAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,OAAO,gBAAA,IAAoB,kDACzB,GAAA,CAAA,QAAA,EAAA,EAAG,QAAA,EAAS,oBAEZ,GAAA,CAAC,kBAAA,EAAA,EAAmB,YAAA,EAAc,yBAAA,EAC/B,QAAA,EACH,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"SearchContext.esm.js","sources":["../../src/context/SearchContext.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { isEqual } from 'lodash';\nimport {\n SetStateAction,\n Dispatch,\n DispatchWithoutAction,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport useAsync, { AsyncState } from 'react-use/esm/useAsync';\nimport usePrevious from 'react-use/esm/usePrevious';\n\nimport {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport { JsonObject } from '@backstage/types';\nimport {\n AnalyticsContext,\n useApi,\n configApiRef,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchResultSet } from '@backstage/plugin-search-common';\n\nimport { searchApiRef } from '../api';\n\n/**\n *\n * @public\n */\nexport type SearchContextValue = {\n result: AsyncState<SearchResultSet>;\n setTerm: Dispatch<SetStateAction<string>>;\n setTypes: Dispatch<SetStateAction<string[]>>;\n setFilters: Dispatch<SetStateAction<JsonObject>>;\n setPageLimit: Dispatch<SetStateAction<number | undefined>>;\n setPageCursor: Dispatch<SetStateAction<string | undefined>>;\n fetchNextPage?: DispatchWithoutAction;\n fetchPreviousPage?: DispatchWithoutAction;\n} & SearchContextState;\n\n/**\n *\n * @public\n */\nexport type SearchContextState = {\n term: string;\n types: string[];\n filters: JsonObject;\n pageLimit?: number;\n pageCursor?: string;\n};\n\nconst SearchContext = createVersionedContext<{\n 1: SearchContextValue;\n}>('search-context');\n\n/**\n * @public\n *\n * React hook which provides the search context\n */\nexport const useSearch = () => {\n const context = useContext(SearchContext);\n if (!context) {\n throw new Error('useSearch must be used within a SearchContextProvider');\n }\n\n const value = context.atVersion(1);\n if (!value) {\n throw new Error('No SearchContext v1 found');\n }\n return value;\n};\n\n/**\n * @public\n *\n * React hook which checks for an existing search context\n */\nexport const useSearchContextCheck = () => {\n const context = useContext(SearchContext);\n return context !== undefined;\n};\n\n/**\n * The initial state of `SearchContextProvider`.\n *\n */\nconst defaultInitialSearchState: SearchContextState = {\n term: '',\n types: [],\n filters: {},\n pageLimit: undefined,\n pageCursor: undefined,\n};\n\nconst useSearchContextValue = (\n initialValue: SearchContextState = defaultInitialSearchState,\n) => {\n const searchApi = useApi(searchApiRef);\n const analytics = useAnalytics();\n\n const [term, setTerm] = useState<string>(initialValue.term);\n const [types, setTypes] = useState<string[]>(initialValue.types);\n const [filters, setFilters] = useState<JsonObject>(initialValue.filters);\n const [pageLimit, setPageLimit] = useState<number | undefined>(\n initialValue.pageLimit,\n );\n const [pageCursor, setPageCursor] = useState<string | undefined>(\n initialValue.pageCursor,\n );\n const isFirstEmptyMount = useRef(true);\n\n const prevTerm = usePrevious(term);\n const prevFilters = usePrevious(filters);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const result = useAsync(async (): Promise<SearchResultSet> => {\n if (isFirstEmptyMount.current) {\n if (!term && !types.length && !Object.keys(filters).length) {\n return {\n results: [],\n numberOfResults: 0,\n };\n }\n\n isFirstEmptyMount.current = false;\n }\n\n // Here we cancel the previous request before making a new one\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n const resultSet = await searchApi.query(\n {\n term,\n types,\n filters,\n pageLimit,\n pageCursor,\n },\n { signal: controller.signal },\n );\n\n if (term) {\n analytics.captureEvent('search', term, {\n value: resultSet.numberOfResults,\n });\n }\n return resultSet;\n }, [term, types, filters, pageLimit, pageCursor]);\n\n const hasNextPage =\n !result.loading && !result.error && result.value?.nextPageCursor;\n const hasPreviousPage =\n !result.loading && !result.error && result.value?.previousPageCursor;\n\n const fetchNextPage = useCallback(() => {\n setPageCursor(result.value?.nextPageCursor);\n }, [result.value?.nextPageCursor]);\n\n const fetchPreviousPage = useCallback(() => {\n setPageCursor(result.value?.previousPageCursor);\n }, [result.value?.previousPageCursor]);\n\n useEffect(() => {\n return () => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n };\n }, []);\n\n useEffect(() => {\n // Any time a term is reset, we want to start from page 0.\n // Only reset the term if it has been modified by the user at least once, the initial state must not reset the term.\n if (prevTerm !== undefined && term !== prevTerm) {\n setPageCursor(undefined);\n }\n }, [term, prevTerm, setPageCursor]);\n\n useEffect(() => {\n // Any time filters is reset, we want to start from page 0.\n // Only reset the page if it has been modified by the user at least once, the initial state must not reset the page.\n if (prevFilters !== undefined && !isEqual(filters, prevFilters)) {\n setPageCursor(undefined);\n }\n }, [filters, prevFilters, setPageCursor]);\n\n const value: SearchContextValue = {\n result,\n term,\n setTerm,\n types,\n setTypes,\n filters,\n setFilters,\n pageLimit,\n setPageLimit,\n pageCursor,\n setPageCursor,\n fetchNextPage: hasNextPage ? fetchNextPage : undefined,\n fetchPreviousPage: hasPreviousPage ? fetchPreviousPage : undefined,\n };\n\n return value;\n};\n\nexport type LocalSearchContextProps = PropsWithChildren<{\n initialState?: SearchContextState;\n}>;\n\nconst LocalSearchContext = (props: SearchContextProviderProps) => {\n const { initialState, children } = props;\n const value = useSearchContextValue(initialState);\n\n return (\n <AnalyticsContext\n attributes={{ searchTypes: value.types.sort().join(',') }}\n >\n <SearchContext.Provider value={createVersionedValueMap({ 1: value })}>\n {children}\n </SearchContext.Provider>\n </AnalyticsContext>\n );\n};\n\n/**\n * Props for {@link SearchContextProvider}\n *\n * @public\n */\nexport type SearchContextProviderProps =\n | PropsWithChildren<{\n /**\n * State initialized by a local context.\n */\n initialState?: SearchContextState;\n /**\n * Do not create an inheritance from the parent, as a new initial state must be defined in a local context.\n */\n inheritParentContextIfAvailable?: never;\n }>\n | PropsWithChildren<{\n /**\n * Does not accept initial state since it is already initialized by parent context.\n */\n initialState?: never;\n /**\n * If true, don't create a child context if there is a parent one already defined.\n * @remarks Defaults to false.\n */\n inheritParentContextIfAvailable?: boolean;\n }>;\n\n/**\n * @public\n * Search context provider which gives you access to shared state between search components\n */\nexport const SearchContextProvider = (props: SearchContextProviderProps) => {\n const { initialState, inheritParentContextIfAvailable, children } = props;\n const hasParentContext = useSearchContextCheck();\n\n const configApi = useApi(configApiRef);\n\n const propsInitialSearchState = initialState ?? {};\n\n const configInitialSearchState = configApi.has('search.query.pageLimit')\n ? { pageLimit: configApi.getNumber('search.query.pageLimit') }\n : {};\n\n const searchContextInitialState = {\n ...defaultInitialSearchState,\n ...propsInitialSearchState,\n ...configInitialSearchState,\n };\n\n return hasParentContext && inheritParentContextIfAvailable ? (\n <>{children}</>\n ) : (\n <LocalSearchContext initialState={searchContextInitialState}>\n {children}\n </LocalSearchContext>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -59,7 +59,7 @@ const createSearchResultListItemExtension = (options) => {
59
59
  name,
60
60
  component: {
61
61
  lazy: () => component().then(
62
- (type) => (props) => /* @__PURE__ */ jsx(
62
+ (type) => ((props) => /* @__PURE__ */ jsx(
63
63
  SearchResultListItemExtension,
64
64
  {
65
65
  rank: props.rank,
@@ -67,7 +67,7 @@ const createSearchResultListItemExtension = (options) => {
67
67
  noTrack: props.noTrack,
68
68
  children: createElement(type, props)
69
69
  }
70
- )
70
+ ))
71
71
  )
72
72
  },
73
73
  data: {
@@ -1 +1 @@
1
- {"version":3,"file":"extensions.esm.js","sources":["../src/extensions.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Fragment,\n ReactNode,\n PropsWithChildren,\n isValidElement,\n createElement,\n cloneElement,\n useCallback,\n} from 'react';\n\nimport {\n getComponentData,\n useElementFilter,\n Extension,\n createReactExtension,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchDocument, SearchResult } from '@backstage/plugin-search-common';\n\nimport List, { ListProps } from '@material-ui/core/List';\nimport ListItem, { ListItemProps } from '@material-ui/core/ListItem';\n\nimport { DefaultResultListItem } from './components/DefaultResultListItem';\n\n/**\n * @internal\n * Key for result extensions.\n */\nconst SEARCH_RESULT_LIST_ITEM_EXTENSION =\n 'search.results.list.items.extensions.v1';\n\n/**\n * @internal\n * Returns the first extension element found for a given result, and null otherwise.\n * @param elements - All extension elements.\n * @param result - The search result.\n */\nconst findSearchResultListItemExtensionElement = (\n elements: ReactNode[],\n result: SearchResult,\n) => {\n for (const element of elements) {\n if (!isValidElement(element)) continue;\n const predicate = getComponentData<(result: SearchResult) => boolean>(\n element,\n SEARCH_RESULT_LIST_ITEM_EXTENSION,\n );\n if (!predicate?.(result)) continue;\n return cloneElement(element, {\n rank: result.rank,\n highlight: result.highlight,\n result: result.document,\n // Use props in situations where a consumer is manually rendering the extension\n ...element.props,\n });\n }\n return null;\n};\n\n/**\n * @public\n * Extends props for any search result list item extension\n */\nexport type SearchResultListItemExtensionProps<Props extends {} = {}> = Props &\n PropsWithChildren<\n {\n rank?: number;\n result?: SearchDocument;\n noTrack?: boolean;\n } & Omit<ListItemProps, 'button'>\n >;\n\n/**\n * @internal\n * Extends children with extension capabilities.\n * @param props - see {@link SearchResultListItemExtensionProps}.\n */\nexport const SearchResultListItemExtension = (\n props: SearchResultListItemExtensionProps,\n) => {\n const {\n rank,\n result,\n noTrack,\n children,\n alignItems = 'flex-start',\n ...rest\n } = props;\n const analytics = useAnalytics();\n\n const handleClickCapture = useCallback(() => {\n if (noTrack) return;\n if (!result) return;\n analytics.captureEvent('discover', result.title, {\n attributes: { to: result.location },\n value: rank,\n });\n }, [rank, result, noTrack, analytics]);\n\n return (\n <ListItem\n divider\n alignItems={alignItems}\n onClickCapture={handleClickCapture}\n {...rest}\n >\n {children}\n </ListItem>\n );\n};\n\n/**\n * @public\n * Options for {@link createSearchResultListItemExtension}.\n */\nexport type SearchResultListItemExtensionOptions<\n Component extends (props: any) => JSX.Element | null,\n> = {\n /**\n * The extension name.\n */\n name: string;\n /**\n * The extension component.\n */\n component: () => Promise<Component>;\n /**\n * When an extension defines a predicate, it returns true if the result should be rendered by that extension.\n * Defaults to a predicate that returns true, which means it renders all sorts of results.\n */\n predicate?: (result: SearchResult) => boolean;\n};\n\n/**\n * @public\n * Creates a search result item extension.\n * @param options - The extension options, see {@link SearchResultListItemExtensionOptions} for more details.\n */\nexport const createSearchResultListItemExtension = <\n Component extends (props: any) => JSX.Element | null,\n>(\n options: SearchResultListItemExtensionOptions<Component>,\n): Extension<Component> => {\n const { name, component, predicate = () => true } = options;\n\n return createReactExtension<Component>({\n name,\n component: {\n lazy: () =>\n component().then(\n type =>\n (props => (\n <SearchResultListItemExtension\n rank={props.rank}\n result={props.result}\n noTrack={props.noTrack}\n >\n {createElement(type, props)}\n </SearchResultListItemExtension>\n )) as Component,\n ),\n },\n data: {\n [SEARCH_RESULT_LIST_ITEM_EXTENSION]: predicate,\n },\n });\n};\n\n/**\n * @public\n * Returns a function that renders a result using extensions.\n */\nexport const useSearchResultListItemExtensions = (children: ReactNode) => {\n const elements = useElementFilter(\n children,\n collection => {\n return collection\n .selectByComponentData({\n key: SEARCH_RESULT_LIST_ITEM_EXTENSION,\n })\n .getElements();\n },\n [children],\n );\n\n return useCallback(\n (result: SearchResult, key?: number) => {\n const element = findSearchResultListItemExtensionElement(\n elements,\n result,\n );\n\n return (\n <Fragment key={key}>\n {element ?? (\n <SearchResultListItemExtension\n rank={result.rank}\n result={result.document}\n >\n <DefaultResultListItem\n rank={result.rank}\n highlight={result.highlight}\n result={result.document}\n />\n </SearchResultListItemExtension>\n )}\n </Fragment>\n );\n },\n [elements],\n );\n};\n\n/**\n * @public\n * Props for {@link SearchResultListItemExtensions}\n */\nexport type SearchResultListItemExtensionsProps = Omit<ListProps, 'results'> & {\n /**\n * Search result list.\n */\n results: SearchResult[];\n};\n\n/**\n * @public\n * Render results using search extensions.\n * @param props - see {@link SearchResultListItemExtensionsProps}\n */\nexport const SearchResultListItemExtensions = (\n props: SearchResultListItemExtensionsProps,\n) => {\n const { results, children, ...rest } = props;\n const render = useSearchResultListItemExtensions(children);\n return <List {...rest}>{results.map(render)}</List>;\n};\n"],"names":["DefaultResultListItem"],"mappings":"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"}
1
+ {"version":3,"file":"extensions.esm.js","sources":["../src/extensions.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Fragment,\n ReactNode,\n PropsWithChildren,\n isValidElement,\n createElement,\n cloneElement,\n useCallback,\n} from 'react';\n\nimport {\n getComponentData,\n useElementFilter,\n Extension,\n createReactExtension,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchDocument, SearchResult } from '@backstage/plugin-search-common';\n\nimport List, { ListProps } from '@material-ui/core/List';\nimport ListItem, { ListItemProps } from '@material-ui/core/ListItem';\n\nimport { DefaultResultListItem } from './components/DefaultResultListItem';\n\n/**\n * @internal\n * Key for result extensions.\n */\nconst SEARCH_RESULT_LIST_ITEM_EXTENSION =\n 'search.results.list.items.extensions.v1';\n\n/**\n * @internal\n * Returns the first extension element found for a given result, and null otherwise.\n * @param elements - All extension elements.\n * @param result - The search result.\n */\nconst findSearchResultListItemExtensionElement = (\n elements: ReactNode[],\n result: SearchResult,\n) => {\n for (const element of elements) {\n if (!isValidElement(element)) continue;\n const predicate = getComponentData<(result: SearchResult) => boolean>(\n element,\n SEARCH_RESULT_LIST_ITEM_EXTENSION,\n );\n if (!predicate?.(result)) continue;\n return cloneElement(element, {\n rank: result.rank,\n highlight: result.highlight,\n result: result.document,\n // Use props in situations where a consumer is manually rendering the extension\n ...element.props,\n });\n }\n return null;\n};\n\n/**\n * @public\n * Extends props for any search result list item extension\n */\nexport type SearchResultListItemExtensionProps<Props extends {} = {}> = Props &\n PropsWithChildren<\n {\n rank?: number;\n result?: SearchDocument;\n noTrack?: boolean;\n } & Omit<ListItemProps, 'button'>\n >;\n\n/**\n * @internal\n * Extends children with extension capabilities.\n * @param props - see {@link SearchResultListItemExtensionProps}.\n */\nexport const SearchResultListItemExtension = (\n props: SearchResultListItemExtensionProps,\n) => {\n const {\n rank,\n result,\n noTrack,\n children,\n alignItems = 'flex-start',\n ...rest\n } = props;\n const analytics = useAnalytics();\n\n const handleClickCapture = useCallback(() => {\n if (noTrack) return;\n if (!result) return;\n analytics.captureEvent('discover', result.title, {\n attributes: { to: result.location },\n value: rank,\n });\n }, [rank, result, noTrack, analytics]);\n\n return (\n <ListItem\n divider\n alignItems={alignItems}\n onClickCapture={handleClickCapture}\n {...rest}\n >\n {children}\n </ListItem>\n );\n};\n\n/**\n * @public\n * Options for {@link createSearchResultListItemExtension}.\n */\nexport type SearchResultListItemExtensionOptions<\n Component extends (props: any) => JSX.Element | null,\n> = {\n /**\n * The extension name.\n */\n name: string;\n /**\n * The extension component.\n */\n component: () => Promise<Component>;\n /**\n * When an extension defines a predicate, it returns true if the result should be rendered by that extension.\n * Defaults to a predicate that returns true, which means it renders all sorts of results.\n */\n predicate?: (result: SearchResult) => boolean;\n};\n\n/**\n * @public\n * Creates a search result item extension.\n * @param options - The extension options, see {@link SearchResultListItemExtensionOptions} for more details.\n */\nexport const createSearchResultListItemExtension = <\n Component extends (props: any) => JSX.Element | null,\n>(\n options: SearchResultListItemExtensionOptions<Component>,\n): Extension<Component> => {\n const { name, component, predicate = () => true } = options;\n\n return createReactExtension<Component>({\n name,\n component: {\n lazy: () =>\n component().then(\n type =>\n (props => (\n <SearchResultListItemExtension\n rank={props.rank}\n result={props.result}\n noTrack={props.noTrack}\n >\n {createElement(type, props)}\n </SearchResultListItemExtension>\n )) as Component,\n ),\n },\n data: {\n [SEARCH_RESULT_LIST_ITEM_EXTENSION]: predicate,\n },\n });\n};\n\n/**\n * @public\n * Returns a function that renders a result using extensions.\n */\nexport const useSearchResultListItemExtensions = (children: ReactNode) => {\n const elements = useElementFilter(\n children,\n collection => {\n return collection\n .selectByComponentData({\n key: SEARCH_RESULT_LIST_ITEM_EXTENSION,\n })\n .getElements();\n },\n [children],\n );\n\n return useCallback(\n (result: SearchResult, key?: number) => {\n const element = findSearchResultListItemExtensionElement(\n elements,\n result,\n );\n\n return (\n <Fragment key={key}>\n {element ?? (\n <SearchResultListItemExtension\n rank={result.rank}\n result={result.document}\n >\n <DefaultResultListItem\n rank={result.rank}\n highlight={result.highlight}\n result={result.document}\n />\n </SearchResultListItemExtension>\n )}\n </Fragment>\n );\n },\n [elements],\n );\n};\n\n/**\n * @public\n * Props for {@link SearchResultListItemExtensions}\n */\nexport type SearchResultListItemExtensionsProps = Omit<ListProps, 'results'> & {\n /**\n * Search result list.\n */\n results: SearchResult[];\n};\n\n/**\n * @public\n * Render results using search extensions.\n * @param props - see {@link SearchResultListItemExtensionsProps}\n */\nexport const SearchResultListItemExtensions = (\n props: SearchResultListItemExtensionsProps,\n) => {\n const { results, children, ...rest } = props;\n const render = useSearchResultListItemExtensions(children);\n return <List {...rest}>{results.map(render)}</List>;\n};\n"],"names":["DefaultResultListItem"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
2
- import { Extension } from '@backstage/core-plugin-api';
1
+ import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
3
2
  import { SearchQuery, SearchResultSet, SearchDocument, SearchResult as SearchResult$1, ResultHighlight } from '@backstage/plugin-search-common';
4
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
4
  import * as react from 'react';
6
5
  import { PropsWithChildren, ReactNode, ReactElement, Dispatch, SetStateAction, DispatchWithoutAction } from 'react';
6
+ import { Extension } from '@backstage/core-plugin-api';
7
7
  import { ListProps } from '@material-ui/core/List';
8
8
  import { ListItemProps } from '@material-ui/core/ListItem';
9
9
  import { TextFieldProps } from '@material-ui/core/TextField';
@@ -17,7 +17,7 @@ import { LinkProps } from '@backstage/core-components';
17
17
  /**
18
18
  * @public
19
19
  */
20
- declare const searchApiRef: _backstage_core_plugin_api.ApiRef<SearchApi>;
20
+ declare const searchApiRef: _backstage_frontend_plugin_api.ApiRef<SearchApi>;
21
21
  /**
22
22
  * @public
23
23
  */
@@ -769,4 +769,5 @@ type SearchContextProviderProps = PropsWithChildren<{
769
769
  */
770
770
  declare const SearchContextProvider: (props: SearchContextProviderProps) => react_jsx_runtime.JSX.Element;
771
771
 
772
- export { AutocompleteFilter, CheckboxFilter, HigherOrderDefaultResultListItem as DefaultResultListItem, type DefaultResultListItemProps, type FilterValue, type FilterValueWithLabel, HighlightedSearchResultText, type HighlightedSearchResultTextClassKey, type HighlightedSearchResultTextProps, MockSearchApi, type SearchApi, SearchAutocomplete, type SearchAutocompleteComponent, SearchAutocompleteDefaultOption, type SearchAutocompleteDefaultOptionProps, type SearchAutocompleteFilterProps, type SearchAutocompleteProps, SearchBar, SearchBarBase, type SearchBarBaseProps, type SearchBarProps, SearchContextProvider, type SearchContextProviderProps, type SearchContextState, type SearchContextValue, SearchFilter, type SearchFilterComponentProps, type SearchFilterWrapperProps, SearchPagination, SearchPaginationBase, type SearchPaginationBaseProps, type SearchPaginationLimitOption, type SearchPaginationLimitText, type SearchPaginationProps, SearchResult, SearchResultApi, type SearchResultApiProps, SearchResultComponent, SearchResultContext, type SearchResultContextProps, SearchResultGroup, SearchResultGroupFilterFieldLayout, type SearchResultGroupFilterFieldLayoutProps, type SearchResultGroupFilterFieldPropsWith, SearchResultGroupLayout, type SearchResultGroupLayoutProps, type SearchResultGroupProps, SearchResultGroupSelectFilterField, type SearchResultGroupSelectFilterFieldProps, SearchResultGroupTextFilterField, type SearchResultGroupTextFilterFieldProps, SearchResultList, type SearchResultListItemExtensionOptions, type SearchResultListItemExtensionProps, SearchResultListItemExtensions, type SearchResultListItemExtensionsProps, SearchResultListLayout, type SearchResultListLayoutProps, type SearchResultListProps, SearchResultPager, type SearchResultProps, SearchResultState, type SearchResultStateProps, SelectFilter, createSearchResultListItemExtension, searchApiRef, useSearch, useSearchContextCheck, useSearchResultListItemExtensions };
772
+ 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 };
773
+ export type { DefaultResultListItemProps, FilterValue, FilterValueWithLabel, HighlightedSearchResultTextClassKey, HighlightedSearchResultTextProps, SearchApi, SearchAutocompleteComponent, SearchAutocompleteDefaultOptionProps, SearchAutocompleteFilterProps, SearchAutocompleteProps, SearchBarBaseProps, SearchBarProps, SearchContextProviderProps, SearchContextState, SearchContextValue, SearchFilterComponentProps, SearchFilterWrapperProps, SearchPaginationBaseProps, SearchPaginationLimitOption, SearchPaginationLimitText, SearchPaginationProps, SearchResultApiProps, SearchResultContextProps, SearchResultGroupFilterFieldLayoutProps, SearchResultGroupFilterFieldPropsWith, SearchResultGroupLayoutProps, SearchResultGroupProps, SearchResultGroupSelectFilterFieldProps, SearchResultGroupTextFilterFieldProps, SearchResultListItemExtensionOptions, SearchResultListItemExtensionProps, SearchResultListItemExtensionsProps, SearchResultListLayoutProps, SearchResultListProps, SearchResultProps, SearchResultStateProps };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-search-react",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "backstage": {
5
5
  "role": "web-library",
6
6
  "pluginId": "search",
@@ -64,11 +64,11 @@
64
64
  "test": "backstage-cli package test"
65
65
  },
66
66
  "dependencies": {
67
- "@backstage/core-components": "^0.18.3",
68
- "@backstage/core-plugin-api": "^1.12.0",
69
- "@backstage/frontend-plugin-api": "^0.13.0",
67
+ "@backstage/core-components": "^0.18.4",
68
+ "@backstage/core-plugin-api": "^1.12.1",
69
+ "@backstage/frontend-plugin-api": "^0.13.2",
70
70
  "@backstage/plugin-search-common": "^1.2.21",
71
- "@backstage/theme": "^0.7.0",
71
+ "@backstage/theme": "^0.7.1",
72
72
  "@backstage/types": "^1.2.2",
73
73
  "@backstage/version-bridge": "^1.0.11",
74
74
  "@material-ui/core": "^4.12.2",
@@ -80,11 +80,11 @@
80
80
  "uuid": "^11.0.2"
81
81
  },
82
82
  "devDependencies": {
83
- "@backstage/cli": "^0.34.5",
84
- "@backstage/core-app-api": "^1.19.2",
85
- "@backstage/frontend-app-api": "^0.13.2",
86
- "@backstage/frontend-test-utils": "^0.4.1",
87
- "@backstage/test-utils": "^1.7.13",
83
+ "@backstage/cli": "^0.35.0",
84
+ "@backstage/core-app-api": "^1.19.3",
85
+ "@backstage/frontend-app-api": "^0.13.3",
86
+ "@backstage/frontend-test-utils": "^0.4.2",
87
+ "@backstage/test-utils": "^1.7.14",
88
88
  "@testing-library/dom": "^10.0.0",
89
89
  "@testing-library/jest-dom": "^6.0.0",
90
90
  "@testing-library/react": "^16.0.0",