@backstage/plugin-search-react 1.9.3-next.1 → 1.9.4-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.
Files changed (28) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/alpha/blueprints/SearchFilterBlueprint.esm.js.map +1 -1
  3. package/dist/alpha/blueprints/SearchFilterResultTypeBlueprint.esm.js.map +1 -1
  4. package/dist/alpha/blueprints/SearchResultListItemBlueprint.esm.js.map +1 -1
  5. package/dist/alpha/blueprints/types.esm.js.map +1 -1
  6. package/dist/api.esm.js.map +1 -1
  7. package/dist/components/DefaultResultListItem/DefaultResultListItem.esm.js.map +1 -1
  8. package/dist/components/HighlightedSearchResultText/HighlightedSearchResultText.esm.js.map +1 -1
  9. package/dist/components/SearchAutocomplete/SearchAutocomplete.esm.js.map +1 -1
  10. package/dist/components/SearchAutocomplete/SearchAutocompleteDefaultOption.esm.js.map +1 -1
  11. package/dist/components/SearchBar/SearchBar.esm.js.map +1 -1
  12. package/dist/components/SearchFilter/SearchFilter.Autocomplete.esm.js.map +1 -1
  13. package/dist/components/SearchFilter/SearchFilter.esm.js.map +1 -1
  14. package/dist/components/SearchFilter/hooks.esm.js +1 -1
  15. package/dist/components/SearchFilter/hooks.esm.js.map +1 -1
  16. package/dist/components/SearchFilter/types.esm.js.map +1 -1
  17. package/dist/components/SearchPagination/SearchPagination.esm.js.map +1 -1
  18. package/dist/components/SearchResult/SearchResult.esm.js +1 -1
  19. package/dist/components/SearchResult/SearchResult.esm.js.map +1 -1
  20. package/dist/components/SearchResultGroup/SearchResultGroup.esm.js +1 -1
  21. package/dist/components/SearchResultGroup/SearchResultGroup.esm.js.map +1 -1
  22. package/dist/components/SearchResultList/SearchResultList.esm.js.map +1 -1
  23. package/dist/components/SearchResultPager/SearchResultPager.esm.js.map +1 -1
  24. package/dist/context/SearchContext.esm.js.map +1 -1
  25. package/dist/extensions.esm.js.map +1 -1
  26. package/dist/index.d.ts +0 -7
  27. package/dist/translation.esm.js.map +1 -1
  28. package/package.json +8 -8
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @backstage/plugin-search-react
2
2
 
3
+ ## 1.9.4-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/frontend-plugin-api@0.11.1-next.0
9
+ - @backstage/core-components@0.17.6-next.0
10
+
11
+ ## 1.9.3
12
+
13
+ ### Patch Changes
14
+
15
+ - e4ddf22: Internal update to align with new blueprint parameter naming in the new frontend system.
16
+ - Updated dependencies
17
+ - @backstage/core-components@0.17.5
18
+ - @backstage/frontend-plugin-api@0.11.0
19
+ - @backstage/theme@0.6.8
20
+
3
21
  ## 1.9.3-next.1
4
22
 
5
23
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"SearchFilterBlueprint.esm.js","sources":["../../../src/alpha/blueprints/SearchFilterBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { createExtensionBlueprint } from '@backstage/frontend-plugin-api';\nimport { searchFilterDataRef, SearchFilterExtensionComponent } from './types';\n\n/** @alpha */\nexport interface SearchFilterBlueprintParams {\n component: SearchFilterExtensionComponent;\n}\n\n/**\n * @alpha\n */\nexport const SearchFilterBlueprint = createExtensionBlueprint({\n kind: 'search-filter',\n attachTo: {\n id: 'page:search',\n input: 'searchFilters',\n },\n output: [searchFilterDataRef],\n dataRefs: {\n searchFilters: searchFilterDataRef,\n },\n *factory(params: SearchFilterBlueprintParams) {\n yield searchFilterDataRef({\n component: params.component,\n });\n },\n});\n"],"names":[],"mappings":";;;AA2BO,MAAM,wBAAwB,wBAAyB,CAAA;AAAA,EAC5D,IAAM,EAAA,eAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACR,EAAI,EAAA,aAAA;AAAA,IACJ,KAAO,EAAA;AAAA,GACT;AAAA,EACA,MAAA,EAAQ,CAAC,mBAAmB,CAAA;AAAA,EAC5B,QAAU,EAAA;AAAA,IACR,aAAe,EAAA;AAAA,GACjB;AAAA,EACA,CAAC,QAAQ,MAAqC,EAAA;AAC5C,IAAA,MAAM,mBAAoB,CAAA;AAAA,MACxB,WAAW,MAAO,CAAA;AAAA,KACnB,CAAA;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"SearchFilterBlueprint.esm.js","sources":["../../../src/alpha/blueprints/SearchFilterBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { createExtensionBlueprint } from '@backstage/frontend-plugin-api';\nimport { searchFilterDataRef, SearchFilterExtensionComponent } from './types';\n\n/** @alpha */\nexport interface SearchFilterBlueprintParams {\n component: SearchFilterExtensionComponent;\n}\n\n/**\n * @alpha\n */\nexport const SearchFilterBlueprint = createExtensionBlueprint({\n kind: 'search-filter',\n attachTo: {\n id: 'page:search',\n input: 'searchFilters',\n },\n output: [searchFilterDataRef],\n dataRefs: {\n searchFilters: searchFilterDataRef,\n },\n *factory(params: SearchFilterBlueprintParams) {\n yield searchFilterDataRef({\n component: params.component,\n });\n },\n});\n"],"names":[],"mappings":";;;AA2BO,MAAM,wBAAwB,wBAAA,CAAyB;AAAA,EAC5D,IAAA,EAAM,eAAA;AAAA,EACN,QAAA,EAAU;AAAA,IACR,EAAA,EAAI,aAAA;AAAA,IACJ,KAAA,EAAO;AAAA,GACT;AAAA,EACA,MAAA,EAAQ,CAAC,mBAAmB,CAAA;AAAA,EAC5B,QAAA,EAAU;AAAA,IACR,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,CAAC,QAAQ,MAAA,EAAqC;AAC5C,IAAA,MAAM,mBAAA,CAAoB;AAAA,MACxB,WAAW,MAAA,CAAO;AAAA,KACnB,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchFilterResultTypeBlueprint.esm.js","sources":["../../../src/alpha/blueprints/SearchFilterResultTypeBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { createExtensionBlueprint } from '@backstage/frontend-plugin-api';\nimport { searchResultTypeDataRef } from './types';\n\n/** @alpha */\nexport interface SearchFilterResultTypeBlueprintParams {\n /**\n * The value of the result type.\n */\n value: string;\n /**\n * The name of the result type.\n */\n name: string;\n /**\n * The icon of the result type.\n */\n icon: JSX.Element;\n}\n\n/**\n * @alpha\n */\nexport const SearchFilterResultTypeBlueprint = createExtensionBlueprint({\n kind: 'search-filter-result-type',\n attachTo: {\n id: 'page:search',\n input: 'resultTypes',\n },\n output: [searchResultTypeDataRef],\n dataRefs: {\n resultType: searchResultTypeDataRef,\n },\n *factory(params: SearchFilterResultTypeBlueprintParams) {\n yield searchResultTypeDataRef({\n value: params.value,\n name: params.name,\n icon: params.icon,\n });\n },\n});\n"],"names":[],"mappings":";;;AAsCO,MAAM,kCAAkC,wBAAyB,CAAA;AAAA,EACtE,IAAM,EAAA,2BAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACR,EAAI,EAAA,aAAA;AAAA,IACJ,KAAO,EAAA;AAAA,GACT;AAAA,EACA,MAAA,EAAQ,CAAC,uBAAuB,CAAA;AAAA,EAChC,QAAU,EAAA;AAAA,IACR,UAAY,EAAA;AAAA,GACd;AAAA,EACA,CAAC,QAAQ,MAA+C,EAAA;AACtD,IAAA,MAAM,uBAAwB,CAAA;AAAA,MAC5B,OAAO,MAAO,CAAA,KAAA;AAAA,MACd,MAAM,MAAO,CAAA,IAAA;AAAA,MACb,MAAM,MAAO,CAAA;AAAA,KACd,CAAA;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"SearchFilterResultTypeBlueprint.esm.js","sources":["../../../src/alpha/blueprints/SearchFilterResultTypeBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2025 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 { createExtensionBlueprint } from '@backstage/frontend-plugin-api';\nimport { searchResultTypeDataRef } from './types';\n\n/** @alpha */\nexport interface SearchFilterResultTypeBlueprintParams {\n /**\n * The value of the result type.\n */\n value: string;\n /**\n * The name of the result type.\n */\n name: string;\n /**\n * The icon of the result type.\n */\n icon: JSX.Element;\n}\n\n/**\n * @alpha\n */\nexport const SearchFilterResultTypeBlueprint = createExtensionBlueprint({\n kind: 'search-filter-result-type',\n attachTo: {\n id: 'page:search',\n input: 'resultTypes',\n },\n output: [searchResultTypeDataRef],\n dataRefs: {\n resultType: searchResultTypeDataRef,\n },\n *factory(params: SearchFilterResultTypeBlueprintParams) {\n yield searchResultTypeDataRef({\n value: params.value,\n name: params.name,\n icon: params.icon,\n });\n },\n});\n"],"names":[],"mappings":";;;AAsCO,MAAM,kCAAkC,wBAAA,CAAyB;AAAA,EACtE,IAAA,EAAM,2BAAA;AAAA,EACN,QAAA,EAAU;AAAA,IACR,EAAA,EAAI,aAAA;AAAA,IACJ,KAAA,EAAO;AAAA,GACT;AAAA,EACA,MAAA,EAAQ,CAAC,uBAAuB,CAAA;AAAA,EAChC,QAAA,EAAU;AAAA,IACR,UAAA,EAAY;AAAA,GACd;AAAA,EACA,CAAC,QAAQ,MAAA,EAA+C;AACtD,IAAA,MAAM,uBAAA,CAAwB;AAAA,MAC5B,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,MAAM,MAAA,CAAO;AAAA,KACd,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResultListItemBlueprint.esm.js","sources":["../../../src/alpha/blueprints/SearchResultListItemBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { lazy } from 'react';\nimport {\n createExtensionBlueprint,\n ExtensionBoundary,\n} from '@backstage/frontend-plugin-api';\nimport {\n SearchResultItemExtensionComponent,\n SearchResultItemExtensionPredicate,\n searchResultListItemDataRef,\n} from './types';\nimport {\n SearchResultListItemExtension,\n SearchResultListItemExtensionProps,\n} from '../../extensions';\n\n/** @alpha */\nexport interface SearchResultListItemBlueprintParams {\n /**\n * The extension component.\n */\n component: (options: {\n config: { noTrack?: boolean };\n }) => Promise<SearchResultItemExtensionComponent>;\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?: SearchResultItemExtensionPredicate;\n}\n\n/**\n * @alpha\n * Creates SearchResultListItem extensions\n */\nexport const SearchResultListItemBlueprint = createExtensionBlueprint({\n kind: 'search-result-list-item',\n attachTo: {\n id: 'page:search',\n input: 'items',\n },\n config: {\n schema: {\n noTrack: z => z.boolean().default(false),\n },\n },\n output: [searchResultListItemDataRef],\n dataRefs: {\n item: searchResultListItemDataRef,\n },\n *factory(params: SearchResultListItemBlueprintParams, { config, node }) {\n const ExtensionComponent = lazy(() =>\n params.component({ config }).then(component => ({ default: component })),\n );\n\n yield searchResultListItemDataRef({\n predicate: params.predicate,\n component: (props: SearchResultListItemExtensionProps) => (\n <ExtensionBoundary node={node}>\n <SearchResultListItemExtension\n rank={props.rank}\n result={props.result}\n noTrack={config.noTrack}\n >\n <ExtensionComponent {...props} />\n </SearchResultListItemExtension>\n </ExtensionBoundary>\n ),\n });\n },\n});\n"],"names":[],"mappings":";;;;;;AAkDO,MAAM,gCAAgC,wBAAyB,CAAA;AAAA,EACpE,IAAM,EAAA,yBAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACR,EAAI,EAAA,aAAA;AAAA,IACJ,KAAO,EAAA;AAAA,GACT;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,MAAQ,EAAA;AAAA,MACN,SAAS,CAAK,CAAA,KAAA,CAAA,CAAE,OAAQ,EAAA,CAAE,QAAQ,KAAK;AAAA;AACzC,GACF;AAAA,EACA,MAAA,EAAQ,CAAC,2BAA2B,CAAA;AAAA,EACpC,QAAU,EAAA;AAAA,IACR,IAAM,EAAA;AAAA,GACR;AAAA,EACA,CAAC,OAAQ,CAAA,MAAA,EAA6C,EAAE,MAAA,EAAQ,MAAQ,EAAA;AACtE,IAAA,MAAM,kBAAqB,GAAA,IAAA;AAAA,MAAK,MAC9B,MAAA,CAAO,SAAU,CAAA,EAAE,MAAO,EAAC,CAAE,CAAA,IAAA,CAAK,CAAc,SAAA,MAAA,EAAE,OAAS,EAAA,SAAA,EAAY,CAAA;AAAA,KACzE;AAEA,IAAA,MAAM,2BAA4B,CAAA;AAAA,MAChC,WAAW,MAAO,CAAA,SAAA;AAAA,MAClB,SAAW,EAAA,CAAC,KACV,qBAAA,GAAA,CAAC,qBAAkB,IACjB,EAAA,QAAA,kBAAA,GAAA;AAAA,QAAC,6BAAA;AAAA,QAAA;AAAA,UACC,MAAM,KAAM,CAAA,IAAA;AAAA,UACZ,QAAQ,KAAM,CAAA,MAAA;AAAA,UACd,SAAS,MAAO,CAAA,OAAA;AAAA,UAEhB,QAAA,kBAAA,GAAA,CAAC,kBAAoB,EAAA,EAAA,GAAG,KAAO,EAAA;AAAA;AAAA,OAEnC,EAAA;AAAA,KAEH,CAAA;AAAA;AAEL,CAAC;;;;"}
1
+ {"version":3,"file":"SearchResultListItemBlueprint.esm.js","sources":["../../../src/alpha/blueprints/SearchResultListItemBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 { lazy } from 'react';\nimport {\n createExtensionBlueprint,\n ExtensionBoundary,\n} from '@backstage/frontend-plugin-api';\nimport {\n SearchResultItemExtensionComponent,\n SearchResultItemExtensionPredicate,\n searchResultListItemDataRef,\n} from './types';\nimport {\n SearchResultListItemExtension,\n SearchResultListItemExtensionProps,\n} from '../../extensions';\n\n/** @alpha */\nexport interface SearchResultListItemBlueprintParams {\n /**\n * The extension component.\n */\n component: (options: {\n config: { noTrack?: boolean };\n }) => Promise<SearchResultItemExtensionComponent>;\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?: SearchResultItemExtensionPredicate;\n}\n\n/**\n * @alpha\n * Creates SearchResultListItem extensions\n */\nexport const SearchResultListItemBlueprint = createExtensionBlueprint({\n kind: 'search-result-list-item',\n attachTo: {\n id: 'page:search',\n input: 'items',\n },\n config: {\n schema: {\n noTrack: z => z.boolean().default(false),\n },\n },\n output: [searchResultListItemDataRef],\n dataRefs: {\n item: searchResultListItemDataRef,\n },\n *factory(params: SearchResultListItemBlueprintParams, { config, node }) {\n const ExtensionComponent = lazy(() =>\n params.component({ config }).then(component => ({ default: component })),\n );\n\n yield searchResultListItemDataRef({\n predicate: params.predicate,\n component: (props: SearchResultListItemExtensionProps) => (\n <ExtensionBoundary node={node}>\n <SearchResultListItemExtension\n rank={props.rank}\n result={props.result}\n noTrack={config.noTrack}\n >\n <ExtensionComponent {...props} />\n </SearchResultListItemExtension>\n </ExtensionBoundary>\n ),\n });\n },\n});\n"],"names":[],"mappings":";;;;;;AAkDO,MAAM,gCAAgC,wBAAA,CAAyB;AAAA,EACpE,IAAA,EAAM,yBAAA;AAAA,EACN,QAAA,EAAU;AAAA,IACR,EAAA,EAAI,aAAA;AAAA,IACJ,KAAA,EAAO;AAAA,GACT;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,MAAA,EAAQ;AAAA,MACN,SAAS,CAAA,CAAA,KAAK,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAQ,KAAK;AAAA;AACzC,GACF;AAAA,EACA,MAAA,EAAQ,CAAC,2BAA2B,CAAA;AAAA,EACpC,QAAA,EAAU;AAAA,IACR,IAAA,EAAM;AAAA,GACR;AAAA,EACA,CAAC,OAAA,CAAQ,MAAA,EAA6C,EAAE,MAAA,EAAQ,MAAK,EAAG;AACtE,IAAA,MAAM,kBAAA,GAAqB,IAAA;AAAA,MAAK,MAC9B,MAAA,CAAO,SAAA,CAAU,EAAE,MAAA,EAAQ,CAAA,CAAE,IAAA,CAAK,CAAA,SAAA,MAAc,EAAE,OAAA,EAAS,SAAA,EAAU,CAAE;AAAA,KACzE;AAEA,IAAA,MAAM,2BAAA,CAA4B;AAAA,MAChC,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,SAAA,EAAW,CAAC,KAAA,qBACV,GAAA,CAAC,qBAAkB,IAAA,EACjB,QAAA,kBAAA,GAAA;AAAA,QAAC,6BAAA;AAAA,QAAA;AAAA,UACC,MAAM,KAAA,CAAM,IAAA;AAAA,UACZ,QAAQ,KAAA,CAAM,MAAA;AAAA,UACd,SAAS,MAAA,CAAO,OAAA;AAAA,UAEhB,QAAA,kBAAA,GAAA,CAAC,kBAAA,EAAA,EAAoB,GAAG,KAAA,EAAO;AAAA;AAAA,OACjC,EACF;AAAA,KAEH,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.esm.js","sources":["../../../src/alpha/blueprints/types.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { ListItemProps } from '@material-ui/core/ListItem';\nimport { SearchDocument, SearchResult } from '@backstage/plugin-search-common';\nimport { createExtensionDataRef } from '@backstage/frontend-plugin-api';\n\n/** @alpha */\nexport type BaseSearchResultListItemProps<T = {}> = T & {\n rank?: number;\n result?: SearchDocument;\n} & Omit<ListItemProps, 'button'>;\n\n/** @alpha */\nexport type SearchResultItemExtensionComponent = <\n P extends BaseSearchResultListItemProps,\n>(\n props: P,\n) => JSX.Element | null;\n\n/** @alpha */\nexport type SearchResultItemExtensionPredicate = (\n result: SearchResult,\n) => boolean;\n\n/** @alpha */\nexport const searchResultListItemDataRef = createExtensionDataRef<{\n predicate?: SearchResultItemExtensionPredicate;\n component: SearchResultItemExtensionComponent;\n}>().with({ id: 'search.search-result-list-item.item' });\n\n/** @alpha */\nexport const searchResultTypeDataRef = createExtensionDataRef<{\n value: string;\n name: string;\n icon: JSX.Element;\n}>().with({ id: 'search.filters.result-types.type' });\n\n/** @alpha */\nexport type SearchFilterExtensionComponentProps = {\n className: string;\n};\n\n/** @alpha */\nexport type SearchFilterExtensionComponent = (\n props: SearchFilterExtensionComponentProps,\n) => JSX.Element;\n\n/** @alpha */\nexport const searchFilterDataRef = createExtensionDataRef<{\n component: SearchFilterExtensionComponent;\n}>().with({ id: 'search.filters.filter' });\n"],"names":[],"mappings":";;AAuCO,MAAM,8BAA8B,sBAGxC,EAAA,CAAE,KAAK,EAAE,EAAA,EAAI,uCAAuC;AAGhD,MAAM,0BAA0B,sBAIpC,EAAA,CAAE,KAAK,EAAE,EAAA,EAAI,oCAAoC;AAa7C,MAAM,sBAAsB,sBAEhC,EAAA,CAAE,KAAK,EAAE,EAAA,EAAI,yBAAyB;;;;"}
1
+ {"version":3,"file":"types.esm.js","sources":["../../../src/alpha/blueprints/types.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { ListItemProps } from '@material-ui/core/ListItem';\nimport { SearchDocument, SearchResult } from '@backstage/plugin-search-common';\nimport { createExtensionDataRef } from '@backstage/frontend-plugin-api';\n\n/** @alpha */\nexport type BaseSearchResultListItemProps<T = {}> = T & {\n rank?: number;\n result?: SearchDocument;\n} & Omit<ListItemProps, 'button'>;\n\n/** @alpha */\nexport type SearchResultItemExtensionComponent = <\n P extends BaseSearchResultListItemProps,\n>(\n props: P,\n) => JSX.Element | null;\n\n/** @alpha */\nexport type SearchResultItemExtensionPredicate = (\n result: SearchResult,\n) => boolean;\n\n/** @alpha */\nexport const searchResultListItemDataRef = createExtensionDataRef<{\n predicate?: SearchResultItemExtensionPredicate;\n component: SearchResultItemExtensionComponent;\n}>().with({ id: 'search.search-result-list-item.item' });\n\n/** @alpha */\nexport const searchResultTypeDataRef = createExtensionDataRef<{\n value: string;\n name: string;\n icon: JSX.Element;\n}>().with({ id: 'search.filters.result-types.type' });\n\n/** @alpha */\nexport type SearchFilterExtensionComponentProps = {\n className: string;\n};\n\n/** @alpha */\nexport type SearchFilterExtensionComponent = (\n props: SearchFilterExtensionComponentProps,\n) => JSX.Element;\n\n/** @alpha */\nexport const searchFilterDataRef = createExtensionDataRef<{\n component: SearchFilterExtensionComponent;\n}>().with({ id: 'search.filters.filter' });\n"],"names":[],"mappings":";;AAuCO,MAAM,8BAA8B,sBAAA,EAGxC,CAAE,KAAK,EAAE,EAAA,EAAI,uCAAuC;AAGhD,MAAM,0BAA0B,sBAAA,EAIpC,CAAE,KAAK,EAAE,EAAA,EAAI,oCAAoC;AAa7C,MAAM,sBAAsB,sBAAA,EAEhC,CAAE,KAAK,EAAE,EAAA,EAAI,yBAAyB;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"api.esm.js","sources":["../src/api.ts"],"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 { SearchQuery, SearchResultSet } from '@backstage/plugin-search-common';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\n/**\n * @public\n */\nexport const searchApiRef = createApiRef<SearchApi>({\n id: 'plugin.search.queryservice',\n});\n\n/**\n * @public\n */\nexport interface SearchApi {\n query(query: SearchQuery): Promise<SearchResultSet>;\n}\n\n/**\n * @public\n *\n * Search Api Mock that can be used in tests and storybooks\n */\nexport class MockSearchApi implements SearchApi {\n constructor(public mockedResults?: SearchResultSet) {}\n\n query(): Promise<SearchResultSet> {\n return Promise.resolve(this.mockedResults || { results: [] });\n }\n}\n"],"names":[],"mappings":";;AAsBO,MAAM,eAAe,YAAwB,CAAA;AAAA,EAClD,EAAI,EAAA;AACN,CAAC;AAcM,MAAM,aAAmC,CAAA;AAAA,EAC9C,YAAmB,aAAiC,EAAA;AAAjC,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AAAA;AAAkC,EAErD,KAAkC,GAAA;AAChC,IAAO,OAAA,OAAA,CAAQ,QAAQ,IAAK,CAAA,aAAA,IAAiB,EAAE,OAAS,EAAA,IAAI,CAAA;AAAA;AAEhE;;;;"}
1
+ {"version":3,"file":"api.esm.js","sources":["../src/api.ts"],"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 { SearchQuery, SearchResultSet } from '@backstage/plugin-search-common';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\n/**\n * @public\n */\nexport const searchApiRef = createApiRef<SearchApi>({\n id: 'plugin.search.queryservice',\n});\n\n/**\n * @public\n */\nexport interface SearchApi {\n query(query: SearchQuery): Promise<SearchResultSet>;\n}\n\n/**\n * @public\n *\n * Search Api Mock that can be used in tests and storybooks\n */\nexport class MockSearchApi implements SearchApi {\n constructor(public mockedResults?: SearchResultSet) {}\n\n query(): Promise<SearchResultSet> {\n return Promise.resolve(this.mockedResults || { results: [] });\n }\n}\n"],"names":[],"mappings":";;AAsBO,MAAM,eAAe,YAAA,CAAwB;AAAA,EAClD,EAAA,EAAI;AACN,CAAC;AAcM,MAAM,aAAA,CAAmC;AAAA,EAC9C,YAAmB,aAAA,EAAiC;AAAjC,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AAAA,EAAkC;AAAA,EAErD,KAAA,GAAkC;AAChC,IAAA,OAAO,OAAA,CAAQ,QAAQ,IAAA,CAAK,aAAA,IAAiB,EAAE,OAAA,EAAS,IAAI,CAAA;AAAA,EAC9D;AACF;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultResultListItem.esm.js","sources":["../../../src/components/DefaultResultListItem/DefaultResultListItem.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 { ReactNode } from 'react';\nimport { AnalyticsContext } from '@backstage/core-plugin-api';\nimport {\n ResultHighlight,\n SearchDocument,\n} from '@backstage/plugin-search-common';\nimport { HighlightedSearchResultText } from '../HighlightedSearchResultText';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport { Link } from '@backstage/core-components';\n\n/**\n * Props for {@link DefaultResultListItem}\n *\n * @public\n */\nexport type DefaultResultListItemProps = {\n icon?: ReactNode;\n secondaryAction?: ReactNode;\n result?: SearchDocument;\n highlight?: ResultHighlight;\n rank?: number;\n lineClamp?: number;\n toggleModal?: () => void;\n};\n\n/**\n * A default result list item.\n *\n * @public\n */\nexport const DefaultResultListItemComponent = ({\n result,\n highlight,\n icon,\n secondaryAction,\n lineClamp = 5,\n}: DefaultResultListItemProps) => {\n if (!result) return null;\n\n return (\n <>\n {icon && <ListItemIcon>{icon}</ListItemIcon>}\n <ListItemText\n primaryTypographyProps={{ variant: 'h6' }}\n primary={\n <Link noTrack to={result.location}>\n {highlight?.fields.title ? (\n <HighlightedSearchResultText\n text={highlight?.fields.title || ''}\n preTag={highlight?.preTag || ''}\n postTag={highlight?.postTag || ''}\n />\n ) : (\n result.title\n )}\n </Link>\n }\n secondary={\n <Typography\n component=\"span\"\n style={{\n display: '-webkit-box',\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: lineClamp,\n overflow: 'hidden',\n }}\n color=\"textSecondary\"\n variant=\"body2\"\n >\n {highlight?.fields.text ? (\n <HighlightedSearchResultText\n text={highlight.fields.text}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.text\n )}\n </Typography>\n }\n />\n {secondaryAction && <Box alignItems=\"flex-end\">{secondaryAction}</Box>}\n </>\n );\n};\n\n/**\n * @public\n */\nconst HigherOrderDefaultResultListItem = (\n props: DefaultResultListItemProps,\n) => {\n return (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'DefaultResultListItem',\n }}\n >\n <DefaultResultListItemComponent {...props} />\n </AnalyticsContext>\n );\n};\n\nexport { HigherOrderDefaultResultListItem as DefaultResultListItem };\n"],"names":[],"mappings":";;;;;;;;;AAiDO,MAAM,iCAAiC,CAAC;AAAA,EAC7C,MAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAY,GAAA;AACd,CAAkC,KAAA;AAChC,EAAI,IAAA,CAAC,QAAe,OAAA,IAAA;AAEpB,EAAA,uBAEK,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,IAAQ,IAAA,oBAAA,GAAA,CAAC,gBAAc,QAAK,EAAA,IAAA,EAAA,CAAA;AAAA,oBAC7B,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,sBAAA,EAAwB,EAAE,OAAA,EAAS,IAAK,EAAA;AAAA,QACxC,OAAA,kBACG,GAAA,CAAA,IAAA,EAAA,EAAK,OAAO,EAAA,IAAA,EAAC,IAAI,MAAO,CAAA,QAAA,EACtB,QAAW,EAAA,SAAA,EAAA,MAAA,CAAO,KACjB,mBAAA,GAAA;AAAA,UAAC,2BAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAM,SAAW,EAAA,MAAA,CAAO,KAAS,IAAA,EAAA;AAAA,YACjC,MAAA,EAAQ,WAAW,MAAU,IAAA,EAAA;AAAA,YAC7B,OAAA,EAAS,WAAW,OAAW,IAAA;AAAA;AAAA,SACjC,GAEA,OAAO,KAEX,EAAA,CAAA;AAAA,QAEF,SACE,kBAAA,GAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,SAAU,EAAA,MAAA;AAAA,YACV,KAAO,EAAA;AAAA,cACL,OAAS,EAAA,aAAA;AAAA,cACT,eAAiB,EAAA,UAAA;AAAA,cACjB,eAAiB,EAAA,SAAA;AAAA,cACjB,QAAU,EAAA;AAAA,aACZ;AAAA,YACA,KAAM,EAAA,eAAA;AAAA,YACN,OAAQ,EAAA,OAAA;AAAA,YAEP,QAAA,EAAA,SAAA,EAAW,OAAO,IACjB,mBAAA,GAAA;AAAA,cAAC,2BAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAM,UAAU,MAAO,CAAA,IAAA;AAAA,gBACvB,QAAQ,SAAU,CAAA,MAAA;AAAA,gBAClB,SAAS,SAAU,CAAA;AAAA;AAAA,gBAGrB,MAAO,CAAA;AAAA;AAAA;AAEX;AAAA,KAEJ;AAAA,IACC,eAAmB,oBAAA,GAAA,CAAC,GAAI,EAAA,EAAA,UAAA,EAAW,YAAY,QAAgB,EAAA,eAAA,EAAA;AAAA,GAClE,EAAA,CAAA;AAEJ;AAKM,MAAA,gCAAA,GAAmC,CACvC,KACG,KAAA;AACH,EACE,uBAAA,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,UAAY,EAAA;AAAA,QACV,QAAU,EAAA,QAAA;AAAA,QACV,SAAW,EAAA;AAAA,OACb;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,8BAAgC,EAAA,EAAA,GAAG,KAAO,EAAA;AAAA;AAAA,GAC7C;AAEJ;;;;"}
1
+ {"version":3,"file":"DefaultResultListItem.esm.js","sources":["../../../src/components/DefaultResultListItem/DefaultResultListItem.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 { ReactNode } from 'react';\nimport { AnalyticsContext } from '@backstage/core-plugin-api';\nimport {\n ResultHighlight,\n SearchDocument,\n} from '@backstage/plugin-search-common';\nimport { HighlightedSearchResultText } from '../HighlightedSearchResultText';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport Box from '@material-ui/core/Box';\nimport Typography from '@material-ui/core/Typography';\nimport { Link } from '@backstage/core-components';\n\n/**\n * Props for {@link DefaultResultListItem}\n *\n * @public\n */\nexport type DefaultResultListItemProps = {\n icon?: ReactNode;\n secondaryAction?: ReactNode;\n result?: SearchDocument;\n highlight?: ResultHighlight;\n rank?: number;\n lineClamp?: number;\n toggleModal?: () => void;\n};\n\n/**\n * A default result list item.\n *\n * @public\n */\nexport const DefaultResultListItemComponent = ({\n result,\n highlight,\n icon,\n secondaryAction,\n lineClamp = 5,\n}: DefaultResultListItemProps) => {\n if (!result) return null;\n\n return (\n <>\n {icon && <ListItemIcon>{icon}</ListItemIcon>}\n <ListItemText\n primaryTypographyProps={{ variant: 'h6' }}\n primary={\n <Link noTrack to={result.location}>\n {highlight?.fields.title ? (\n <HighlightedSearchResultText\n text={highlight?.fields.title || ''}\n preTag={highlight?.preTag || ''}\n postTag={highlight?.postTag || ''}\n />\n ) : (\n result.title\n )}\n </Link>\n }\n secondary={\n <Typography\n component=\"span\"\n style={{\n display: '-webkit-box',\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: lineClamp,\n overflow: 'hidden',\n }}\n color=\"textSecondary\"\n variant=\"body2\"\n >\n {highlight?.fields.text ? (\n <HighlightedSearchResultText\n text={highlight.fields.text}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.text\n )}\n </Typography>\n }\n />\n {secondaryAction && <Box alignItems=\"flex-end\">{secondaryAction}</Box>}\n </>\n );\n};\n\n/**\n * @public\n */\nconst HigherOrderDefaultResultListItem = (\n props: DefaultResultListItemProps,\n) => {\n return (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'DefaultResultListItem',\n }}\n >\n <DefaultResultListItemComponent {...props} />\n </AnalyticsContext>\n );\n};\n\nexport { HigherOrderDefaultResultListItem as DefaultResultListItem };\n"],"names":[],"mappings":";;;;;;;;;AAiDO,MAAM,iCAAiC,CAAC;AAAA,EAC7C,MAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,KAAkC;AAChC,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,IAAA,oBAAQ,GAAA,CAAC,gBAAc,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,oBAC7B,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,sBAAA,EAAwB,EAAE,OAAA,EAAS,IAAA,EAAK;AAAA,QACxC,OAAA,kBACE,GAAA,CAAC,IAAA,EAAA,EAAK,OAAA,EAAO,IAAA,EAAC,IAAI,MAAA,CAAO,QAAA,EACtB,QAAA,EAAA,SAAA,EAAW,MAAA,CAAO,KAAA,mBACjB,GAAA;AAAA,UAAC,2BAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAM,SAAA,EAAW,MAAA,CAAO,KAAA,IAAS,EAAA;AAAA,YACjC,MAAA,EAAQ,WAAW,MAAA,IAAU,EAAA;AAAA,YAC7B,OAAA,EAAS,WAAW,OAAA,IAAW;AAAA;AAAA,SACjC,GAEA,OAAO,KAAA,EAEX,CAAA;AAAA,QAEF,SAAA,kBACE,GAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,MAAA;AAAA,YACV,KAAA,EAAO;AAAA,cACL,OAAA,EAAS,aAAA;AAAA,cACT,eAAA,EAAiB,UAAA;AAAA,cACjB,eAAA,EAAiB,SAAA;AAAA,cACjB,QAAA,EAAU;AAAA,aACZ;AAAA,YACA,KAAA,EAAM,eAAA;AAAA,YACN,OAAA,EAAQ,OAAA;AAAA,YAEP,QAAA,EAAA,SAAA,EAAW,OAAO,IAAA,mBACjB,GAAA;AAAA,cAAC,2BAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAM,UAAU,MAAA,CAAO,IAAA;AAAA,gBACvB,QAAQ,SAAA,CAAU,MAAA;AAAA,gBAClB,SAAS,SAAA,CAAU;AAAA;AAAA,gBAGrB,MAAA,CAAO;AAAA;AAAA;AAEX;AAAA,KAEJ;AAAA,IACC,eAAA,oBAAmB,GAAA,CAAC,GAAA,EAAA,EAAI,UAAA,EAAW,YAAY,QAAA,EAAA,eAAA,EAAgB;AAAA,GAAA,EAClE,CAAA;AAEJ;AAKA,MAAM,gCAAA,GAAmC,CACvC,KAAA,KACG;AACH,EAAA,uBACE,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,QAAA;AAAA,QACV,SAAA,EAAW;AAAA,OACb;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,8BAAA,EAAA,EAAgC,GAAG,KAAA,EAAO;AAAA;AAAA,GAC7C;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"HighlightedSearchResultText.esm.js","sources":["../../../src/components/HighlightedSearchResultText/HighlightedSearchResultText.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 { useMemo } from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\n\n/** @public */\nexport type HighlightedSearchResultTextClassKey = 'highlight';\n\nconst useStyles = makeStyles(\n () => ({\n highlight: {},\n }),\n { name: 'BackstageHighlightedSearchResultText' },\n);\n\n/**\n * Props for {@link HighlightedSearchResultText}.\n *\n * @public\n */\nexport type HighlightedSearchResultTextProps = {\n text: string;\n preTag: string;\n postTag: string;\n};\n\n/**\n * @public\n */\nexport const HighlightedSearchResultText = (\n props: HighlightedSearchResultTextProps,\n) => {\n const { text, preTag, postTag } = props;\n\n const classes = useStyles();\n const terms = useMemo(\n () => text.split(new RegExp(`(${preTag}.+?${postTag})`)),\n [postTag, preTag, text],\n );\n\n return (\n <>\n {terms.map((t, idx) =>\n t.includes(preTag) ? (\n <mark className={classes.highlight} key={idx}>\n {t.replace(new RegExp(`${preTag}|${postTag}`, 'g'), '')}\n </mark>\n ) : (\n t\n ),\n )}\n </>\n );\n};\n"],"names":[],"mappings":";;;;AAsBA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB,OAAO;AAAA,IACL,WAAW;AAAC,GACd,CAAA;AAAA,EACA,EAAE,MAAM,sCAAuC;AACjD,CAAA;AAgBa,MAAA,2BAAA,GAA8B,CACzC,KACG,KAAA;AACH,EAAA,MAAM,EAAE,IAAA,EAAM,MAAQ,EAAA,OAAA,EAAY,GAAA,KAAA;AAElC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAA,MAAM,KAAQ,GAAA,OAAA;AAAA,IACZ,MAAM,IAAK,CAAA,KAAA,CAAM,IAAI,MAAA,CAAO,IAAI,MAAM,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,CAAG,CAAC,CAAA;AAAA,IACvD,CAAC,OAAS,EAAA,MAAA,EAAQ,IAAI;AAAA,GACxB;AAEA,EAAA,uCAEK,QAAM,EAAA,KAAA,CAAA,GAAA;AAAA,IAAI,CAAC,CAAG,EAAA,GAAA,KACb,CAAE,CAAA,QAAA,CAAS,MAAM,CAAA,mBACd,GAAA,CAAA,MAAA,EAAA,EAAK,SAAW,EAAA,OAAA,CAAQ,SACtB,EAAA,QAAA,EAAA,CAAA,CAAE,QAAQ,IAAI,MAAA,CAAO,CAAG,EAAA,MAAM,CAAI,CAAA,EAAA,OAAO,CAAI,CAAA,EAAA,GAAG,CAAG,EAAA,EAAE,CADf,EAAA,EAAA,GAEzC,CAEA,GAAA;AAAA,GAGN,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"HighlightedSearchResultText.esm.js","sources":["../../../src/components/HighlightedSearchResultText/HighlightedSearchResultText.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 { useMemo } from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\n\n/** @public */\nexport type HighlightedSearchResultTextClassKey = 'highlight';\n\nconst useStyles = makeStyles(\n () => ({\n highlight: {},\n }),\n { name: 'BackstageHighlightedSearchResultText' },\n);\n\n/**\n * Props for {@link HighlightedSearchResultText}.\n *\n * @public\n */\nexport type HighlightedSearchResultTextProps = {\n text: string;\n preTag: string;\n postTag: string;\n};\n\n/**\n * @public\n */\nexport const HighlightedSearchResultText = (\n props: HighlightedSearchResultTextProps,\n) => {\n const { text, preTag, postTag } = props;\n\n const classes = useStyles();\n const terms = useMemo(\n () => text.split(new RegExp(`(${preTag}.+?${postTag})`)),\n [postTag, preTag, text],\n );\n\n return (\n <>\n {terms.map((t, idx) =>\n t.includes(preTag) ? (\n <mark className={classes.highlight} key={idx}>\n {t.replace(new RegExp(`${preTag}|${postTag}`, 'g'), '')}\n </mark>\n ) : (\n t\n ),\n )}\n </>\n );\n};\n"],"names":[],"mappings":";;;;AAsBA,MAAM,SAAA,GAAY,UAAA;AAAA,EAChB,OAAO;AAAA,IACL,WAAW;AAAC,GACd,CAAA;AAAA,EACA,EAAE,MAAM,sCAAA;AACV,CAAA;AAgBO,MAAM,2BAAA,GAA8B,CACzC,KAAA,KACG;AACH,EAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAQ,GAAI,KAAA;AAElC,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,KAAA,GAAQ,OAAA;AAAA,IACZ,MAAM,IAAA,CAAK,KAAA,CAAM,IAAI,MAAA,CAAO,IAAI,MAAM,CAAA,GAAA,EAAM,OAAO,CAAA,CAAA,CAAG,CAAC,CAAA;AAAA,IACvD,CAAC,OAAA,EAAS,MAAA,EAAQ,IAAI;AAAA,GACxB;AAEA,EAAA,uCAEK,QAAA,EAAA,KAAA,CAAM,GAAA;AAAA,IAAI,CAAC,CAAA,EAAG,GAAA,KACb,CAAA,CAAE,QAAA,CAAS,MAAM,CAAA,mBACf,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,OAAA,CAAQ,SAAA,EACtB,QAAA,EAAA,CAAA,CAAE,QAAQ,IAAI,MAAA,CAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,EAAI,GAAG,CAAA,EAAG,EAAE,CAAA,EAAA,EADf,GAEzC,CAAA,GAEA;AAAA,GAEJ,EACF,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchAutocomplete.esm.js","sources":["../../../src/components/SearchAutocomplete/SearchAutocomplete.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 { ChangeEvent, useCallback, useMemo } from 'react';\n\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport {\n AutocompleteChangeDetails,\n AutocompleteChangeReason,\n} from '@material-ui/lab/useAutocomplete';\n\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { SearchBar, SearchBarProps } from '../SearchBar';\n\nconst useStyles = makeStyles(theme => ({\n loading: {\n right: theme.spacing(1),\n position: 'absolute',\n },\n}));\n\n/**\n * Props for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteProps<Option> = Omit<\n AutocompleteProps<Option, undefined, undefined, boolean>,\n 'renderInput' | 'disableClearable' | 'multiple'\n> & {\n 'data-testid'?: string;\n inputPlaceholder?: SearchBarProps['placeholder'];\n inputDebounceTime?: SearchBarProps['debounceTime'];\n};\n\n/**\n * Type for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteComponent = <Option>(\n props: SearchAutocompleteProps<Option>,\n) => JSX.Element;\n\nconst withContext = (\n Component: SearchAutocompleteComponent,\n): SearchAutocompleteComponent => {\n return props => (\n <SearchContextProvider inheritParentContextIfAvailable>\n <Component {...props} />\n </SearchContextProvider>\n );\n};\n\nconst SearchAutocompleteLoadingAdornment = () => {\n const classes = useStyles();\n return (\n <CircularProgress\n className={classes.loading}\n data-testid=\"search-autocomplete-progressbar\"\n color=\"inherit\"\n size={20}\n />\n );\n};\n\n/**\n * Recommended search autocomplete when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchAutocomplete = withContext(\n function SearchAutocompleteComponent<Option>(\n props: SearchAutocompleteProps<Option>,\n ) {\n const {\n loading,\n value,\n onChange = () => {},\n options = [],\n getOptionLabel = (option: Option) => String(option),\n inputPlaceholder,\n inputDebounceTime,\n freeSolo = true,\n fullWidth = true,\n clearOnBlur = false,\n 'data-testid': dataTestId = 'search-autocomplete',\n ...rest\n } = props;\n\n const { setTerm } = useSearch();\n\n const getInputValue = useCallback(\n (option?: null | string | Option) => {\n if (!option) return '';\n if (typeof option === 'string') return option;\n return getOptionLabel(option);\n },\n [getOptionLabel],\n );\n\n const inputValue = useMemo(\n () => getInputValue(value),\n [value, getInputValue],\n );\n\n const handleChange = useCallback(\n (\n event: ChangeEvent<{}>,\n option: null | string | Option,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<Option>,\n ) => {\n setTerm(getInputValue(option));\n onChange(event, option, reason, details);\n },\n [getInputValue, setTerm, onChange],\n );\n\n const renderInput = useCallback(\n ({\n InputProps: { ref, className, endAdornment },\n InputLabelProps,\n ...params\n }: AutocompleteRenderInputParams) => (\n <SearchBar\n {...params}\n ref={ref}\n clearButton={false}\n value={inputValue}\n placeholder={inputPlaceholder}\n debounceTime={inputDebounceTime}\n endAdornment={\n loading ? <SearchAutocompleteLoadingAdornment /> : endAdornment\n }\n InputProps={{ className }}\n />\n ),\n [loading, inputValue, inputPlaceholder, inputDebounceTime],\n );\n\n return (\n <Autocomplete\n {...rest}\n data-testid={dataTestId}\n value={value}\n onChange={handleChange}\n options={options}\n getOptionLabel={getOptionLabel}\n renderInput={renderInput}\n freeSolo={freeSolo}\n fullWidth={fullWidth}\n clearOnBlur={clearOnBlur}\n />\n );\n },\n);\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SearchAutocomplete.esm.js","sources":["../../../src/components/SearchAutocomplete/SearchAutocomplete.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 { ChangeEvent, useCallback, useMemo } from 'react';\n\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport {\n AutocompleteChangeDetails,\n AutocompleteChangeReason,\n} from '@material-ui/lab/useAutocomplete';\n\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { SearchBar, SearchBarProps } from '../SearchBar';\n\nconst useStyles = makeStyles(theme => ({\n loading: {\n right: theme.spacing(1),\n position: 'absolute',\n },\n}));\n\n/**\n * Props for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteProps<Option> = Omit<\n AutocompleteProps<Option, undefined, undefined, boolean>,\n 'renderInput' | 'disableClearable' | 'multiple'\n> & {\n 'data-testid'?: string;\n inputPlaceholder?: SearchBarProps['placeholder'];\n inputDebounceTime?: SearchBarProps['debounceTime'];\n};\n\n/**\n * Type for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteComponent = <Option>(\n props: SearchAutocompleteProps<Option>,\n) => JSX.Element;\n\nconst withContext = (\n Component: SearchAutocompleteComponent,\n): SearchAutocompleteComponent => {\n return props => (\n <SearchContextProvider inheritParentContextIfAvailable>\n <Component {...props} />\n </SearchContextProvider>\n );\n};\n\nconst SearchAutocompleteLoadingAdornment = () => {\n const classes = useStyles();\n return (\n <CircularProgress\n className={classes.loading}\n data-testid=\"search-autocomplete-progressbar\"\n color=\"inherit\"\n size={20}\n />\n );\n};\n\n/**\n * Recommended search autocomplete when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchAutocomplete = withContext(\n function SearchAutocompleteComponent<Option>(\n props: SearchAutocompleteProps<Option>,\n ) {\n const {\n loading,\n value,\n onChange = () => {},\n options = [],\n getOptionLabel = (option: Option) => String(option),\n inputPlaceholder,\n inputDebounceTime,\n freeSolo = true,\n fullWidth = true,\n clearOnBlur = false,\n 'data-testid': dataTestId = 'search-autocomplete',\n ...rest\n } = props;\n\n const { setTerm } = useSearch();\n\n const getInputValue = useCallback(\n (option?: null | string | Option) => {\n if (!option) return '';\n if (typeof option === 'string') return option;\n return getOptionLabel(option);\n },\n [getOptionLabel],\n );\n\n const inputValue = useMemo(\n () => getInputValue(value),\n [value, getInputValue],\n );\n\n const handleChange = useCallback(\n (\n event: ChangeEvent<{}>,\n option: null | string | Option,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<Option>,\n ) => {\n setTerm(getInputValue(option));\n onChange(event, option, reason, details);\n },\n [getInputValue, setTerm, onChange],\n );\n\n const renderInput = useCallback(\n ({\n InputProps: { ref, className, endAdornment },\n InputLabelProps,\n ...params\n }: AutocompleteRenderInputParams) => (\n <SearchBar\n {...params}\n ref={ref}\n clearButton={false}\n value={inputValue}\n placeholder={inputPlaceholder}\n debounceTime={inputDebounceTime}\n endAdornment={\n loading ? <SearchAutocompleteLoadingAdornment /> : endAdornment\n }\n InputProps={{ className }}\n />\n ),\n [loading, inputValue, inputPlaceholder, inputDebounceTime],\n );\n\n return (\n <Autocomplete\n {...rest}\n data-testid={dataTestId}\n value={value}\n onChange={handleChange}\n options={options}\n getOptionLabel={getOptionLabel}\n renderInput={renderInput}\n freeSolo={freeSolo}\n fullWidth={fullWidth}\n clearOnBlur={clearOnBlur}\n />\n );\n },\n);\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchAutocompleteDefaultOption.esm.js","sources":["../../../src/components/SearchAutocomplete/SearchAutocompleteDefaultOption.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 { ReactNode } from 'react';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText, {\n ListItemTextProps,\n} from '@material-ui/core/ListItemText';\n\n/**\n * Props for {@link SearchAutocompleteDefaultOption}.\n *\n * @public\n */\nexport type SearchAutocompleteDefaultOptionProps = {\n icon?: ReactNode;\n primaryText: ListItemTextProps['primary'];\n primaryTextTypographyProps?: ListItemTextProps['primaryTypographyProps'];\n secondaryText?: ListItemTextProps['secondary'];\n secondaryTextTypographyProps?: ListItemTextProps['secondaryTypographyProps'];\n disableTextTypography?: ListItemTextProps['disableTypography'];\n};\n\n/**\n * A default search autocomplete option component.\n *\n * @public\n */\nexport const SearchAutocompleteDefaultOption = (\n props: SearchAutocompleteDefaultOptionProps,\n) => {\n const {\n icon,\n primaryText,\n primaryTextTypographyProps,\n secondaryText,\n secondaryTextTypographyProps,\n disableTextTypography,\n } = props;\n\n return (\n <>\n {icon ? <ListItemIcon>{icon}</ListItemIcon> : null}\n <ListItemText\n primary={primaryText}\n primaryTypographyProps={primaryTextTypographyProps}\n secondary={secondaryText}\n secondaryTypographyProps={secondaryTextTypographyProps}\n disableTypography={disableTextTypography}\n />\n </>\n );\n};\n"],"names":[],"mappings":";;;;AAyCa,MAAA,+BAAA,GAAkC,CAC7C,KACG,KAAA;AACH,EAAM,MAAA;AAAA,IACJ,IAAA;AAAA,IACA,WAAA;AAAA,IACA,0BAAA;AAAA,IACA,aAAA;AAAA,IACA,4BAAA;AAAA,IACA;AAAA,GACE,GAAA,KAAA;AAEJ,EAAA,uBAEK,IAAA,CAAA,QAAA,EAAA,EAAA,QAAA,EAAA;AAAA,IAAO,IAAA,mBAAA,GAAA,CAAC,YAAc,EAAA,EAAA,QAAA,EAAA,IAAA,EAAK,CAAkB,GAAA,IAAA;AAAA,oBAC9C,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,OAAS,EAAA,WAAA;AAAA,QACT,sBAAwB,EAAA,0BAAA;AAAA,QACxB,SAAW,EAAA,aAAA;AAAA,QACX,wBAA0B,EAAA,4BAAA;AAAA,QAC1B,iBAAmB,EAAA;AAAA;AAAA;AACrB,GACF,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"SearchAutocompleteDefaultOption.esm.js","sources":["../../../src/components/SearchAutocomplete/SearchAutocompleteDefaultOption.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 { ReactNode } from 'react';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText, {\n ListItemTextProps,\n} from '@material-ui/core/ListItemText';\n\n/**\n * Props for {@link SearchAutocompleteDefaultOption}.\n *\n * @public\n */\nexport type SearchAutocompleteDefaultOptionProps = {\n icon?: ReactNode;\n primaryText: ListItemTextProps['primary'];\n primaryTextTypographyProps?: ListItemTextProps['primaryTypographyProps'];\n secondaryText?: ListItemTextProps['secondary'];\n secondaryTextTypographyProps?: ListItemTextProps['secondaryTypographyProps'];\n disableTextTypography?: ListItemTextProps['disableTypography'];\n};\n\n/**\n * A default search autocomplete option component.\n *\n * @public\n */\nexport const SearchAutocompleteDefaultOption = (\n props: SearchAutocompleteDefaultOptionProps,\n) => {\n const {\n icon,\n primaryText,\n primaryTextTypographyProps,\n secondaryText,\n secondaryTextTypographyProps,\n disableTextTypography,\n } = props;\n\n return (\n <>\n {icon ? <ListItemIcon>{icon}</ListItemIcon> : null}\n <ListItemText\n primary={primaryText}\n primaryTypographyProps={primaryTextTypographyProps}\n secondary={secondaryText}\n secondaryTypographyProps={secondaryTextTypographyProps}\n disableTypography={disableTextTypography}\n />\n </>\n );\n};\n"],"names":[],"mappings":";;;;AAyCO,MAAM,+BAAA,GAAkC,CAC7C,KAAA,KACG;AACH,EAAA,MAAM;AAAA,IACJ,IAAA;AAAA,IACA,WAAA;AAAA,IACA,0BAAA;AAAA,IACA,aAAA;AAAA,IACA,4BAAA;AAAA,IACA;AAAA,GACF,GAAI,KAAA;AAEJ,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,IAAA,mBAAO,GAAA,CAAC,YAAA,EAAA,EAAc,QAAA,EAAA,IAAA,EAAK,CAAA,GAAkB,IAAA;AAAA,oBAC9C,GAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,WAAA;AAAA,QACT,sBAAA,EAAwB,0BAAA;AAAA,QACxB,SAAA,EAAW,aAAA;AAAA,QACX,wBAAA,EAA0B,4BAAA;AAAA,QAC1B,iBAAA,EAAmB;AAAA;AAAA;AACrB,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchBar.esm.js","sources":["../../../src/components/SearchBar/SearchBar.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 {\n AnalyticsContext,\n configApiRef,\n useApi,\n useApp,\n} from '@backstage/core-plugin-api';\nimport IconButton from '@material-ui/core/IconButton';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '@material-ui/core/Button';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport DefaultSearchIcon from '@material-ui/icons/Search';\nimport {\n ReactNode,\n ChangeEvent,\n forwardRef,\n KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchBarBase}.\n *\n * @public\n */\nexport type SearchBarBaseProps = Omit<TextFieldProps, 'onChange'> & {\n debounceTime?: number;\n clearButton?: boolean;\n onClear?: () => void;\n onSubmit?: () => void;\n onChange: (value: string) => void;\n endAdornment?: ReactNode;\n};\n\n/**\n * All search boxes exported by the search plugin are based on the <SearchBarBase />,\n * and this one is based on the <InputBase /> component from Material UI.\n * Recommended if you don't use Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBarBase = forwardRef((props: SearchBarBaseProps, ref) => {\n const {\n onChange,\n onKeyDown = () => {},\n onClear = () => {},\n onSubmit = () => {},\n debounceTime = 200,\n clearButton = true,\n fullWidth = true,\n value: defaultValue,\n label,\n placeholder,\n inputProps = {},\n InputProps = {},\n endAdornment,\n ...rest\n } = props;\n\n const configApi = useApi(configApiRef);\n const [value, setValue] = useState<string>('');\n const forwardedValueRef = useRef<string>('');\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n useEffect(() => {\n setValue(prevValue => {\n // We only update the value if our current value is the same as it was\n // for the most recent onChange call. Otherwise it means that the users\n // has continued typing and we should not replace their input.\n if (prevValue === forwardedValueRef.current) {\n return String(defaultValue);\n }\n return prevValue;\n });\n }, [defaultValue, forwardedValueRef]);\n\n useDebounce(\n () => {\n forwardedValueRef.current = value;\n onChange(value);\n },\n debounceTime,\n [value],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setValue(e.target.value);\n },\n [setValue],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (onKeyDown) onKeyDown(e);\n if (onSubmit && e.key === 'Enter') {\n onSubmit();\n }\n },\n [onKeyDown, onSubmit],\n );\n\n const handleClear = useCallback(() => {\n forwardedValueRef.current = '';\n onChange('');\n setValue('');\n if (onClear) {\n onClear();\n }\n }, [onChange, onClear]);\n\n const ariaLabel: string | undefined = label\n ? undefined\n : t('searchBar.title');\n\n const inputPlaceholder =\n placeholder ??\n t('searchBar.placeholder', {\n org: configApi.getOptionalString('app.title') || 'Backstage',\n });\n const SearchIcon = useApp().getSystemIcon('search') || DefaultSearchIcon;\n\n const startAdornment = (\n <InputAdornment position=\"start\">\n <IconButton aria-label=\"Query\" size=\"small\" disabled>\n <SearchIcon />\n </IconButton>\n </InputAdornment>\n );\n\n const clearButtonEndAdornment = (\n <InputAdornment position=\"end\">\n <Button\n aria-label={t('searchBar.clearButtonTitle')}\n size=\"small\"\n onClick={handleClear}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n // write your functionality here\n event.stopPropagation();\n }\n }}\n >\n {t('searchBar.clearButtonTitle')}\n </Button>\n </InputAdornment>\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <TextField\n id=\"search-bar-text-field\"\n data-testid=\"search-bar-next\"\n variant=\"outlined\"\n margin=\"normal\"\n inputRef={ref}\n value={value}\n label={label}\n placeholder={inputPlaceholder}\n InputProps={{\n startAdornment,\n endAdornment: clearButton ? clearButtonEndAdornment : endAdornment,\n ...InputProps,\n }}\n inputProps={{\n 'aria-label': ariaLabel,\n ...inputProps,\n }}\n fullWidth={fullWidth}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n </SearchContextProvider>\n );\n});\n\n/**\n * Props for {@link SearchBar}.\n *\n * @public\n */\nexport type SearchBarProps = Partial<SearchBarBaseProps>;\n\n/**\n * Recommended search bar when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBar = forwardRef((props: SearchBarProps, ref) => {\n const { value: initialValue = '', onChange, ...rest } = props;\n\n const { term, setTerm } = useSearch();\n\n useEffect(() => {\n if (initialValue) {\n setTerm(String(initialValue));\n }\n }, [initialValue, setTerm]);\n\n const handleChange = useCallback(\n (newValue: string) => {\n if (onChange) {\n onChange(newValue);\n } else {\n setTerm(newValue);\n }\n },\n [onChange, setTerm],\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <AnalyticsContext\n attributes={{ pluginId: 'search', extension: 'SearchBar' }}\n >\n <SearchBarBase\n {...rest}\n ref={ref}\n value={term}\n onChange={handleChange}\n />\n </AnalyticsContext>\n </SearchContextProvider>\n );\n});\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SearchBar.esm.js","sources":["../../../src/components/SearchBar/SearchBar.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 {\n AnalyticsContext,\n configApiRef,\n useApi,\n useApp,\n} from '@backstage/core-plugin-api';\nimport IconButton from '@material-ui/core/IconButton';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '@material-ui/core/Button';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport DefaultSearchIcon from '@material-ui/icons/Search';\nimport {\n ReactNode,\n ChangeEvent,\n forwardRef,\n KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchBarBase}.\n *\n * @public\n */\nexport type SearchBarBaseProps = Omit<TextFieldProps, 'onChange'> & {\n debounceTime?: number;\n clearButton?: boolean;\n onClear?: () => void;\n onSubmit?: () => void;\n onChange: (value: string) => void;\n endAdornment?: ReactNode;\n};\n\n/**\n * All search boxes exported by the search plugin are based on the <SearchBarBase />,\n * and this one is based on the <InputBase /> component from Material UI.\n * Recommended if you don't use Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBarBase = forwardRef((props: SearchBarBaseProps, ref) => {\n const {\n onChange,\n onKeyDown = () => {},\n onClear = () => {},\n onSubmit = () => {},\n debounceTime = 200,\n clearButton = true,\n fullWidth = true,\n value: defaultValue,\n label,\n placeholder,\n inputProps = {},\n InputProps = {},\n endAdornment,\n ...rest\n } = props;\n\n const configApi = useApi(configApiRef);\n const [value, setValue] = useState<string>('');\n const forwardedValueRef = useRef<string>('');\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n useEffect(() => {\n setValue(prevValue => {\n // We only update the value if our current value is the same as it was\n // for the most recent onChange call. Otherwise it means that the users\n // has continued typing and we should not replace their input.\n if (prevValue === forwardedValueRef.current) {\n return String(defaultValue);\n }\n return prevValue;\n });\n }, [defaultValue, forwardedValueRef]);\n\n useDebounce(\n () => {\n forwardedValueRef.current = value;\n onChange(value);\n },\n debounceTime,\n [value],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setValue(e.target.value);\n },\n [setValue],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (onKeyDown) onKeyDown(e);\n if (onSubmit && e.key === 'Enter') {\n onSubmit();\n }\n },\n [onKeyDown, onSubmit],\n );\n\n const handleClear = useCallback(() => {\n forwardedValueRef.current = '';\n onChange('');\n setValue('');\n if (onClear) {\n onClear();\n }\n }, [onChange, onClear]);\n\n const ariaLabel: string | undefined = label\n ? undefined\n : t('searchBar.title');\n\n const inputPlaceholder =\n placeholder ??\n t('searchBar.placeholder', {\n org: configApi.getOptionalString('app.title') || 'Backstage',\n });\n const SearchIcon = useApp().getSystemIcon('search') || DefaultSearchIcon;\n\n const startAdornment = (\n <InputAdornment position=\"start\">\n <IconButton aria-label=\"Query\" size=\"small\" disabled>\n <SearchIcon />\n </IconButton>\n </InputAdornment>\n );\n\n const clearButtonEndAdornment = (\n <InputAdornment position=\"end\">\n <Button\n aria-label={t('searchBar.clearButtonTitle')}\n size=\"small\"\n onClick={handleClear}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n // write your functionality here\n event.stopPropagation();\n }\n }}\n >\n {t('searchBar.clearButtonTitle')}\n </Button>\n </InputAdornment>\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <TextField\n id=\"search-bar-text-field\"\n data-testid=\"search-bar-next\"\n variant=\"outlined\"\n margin=\"normal\"\n inputRef={ref}\n value={value}\n label={label}\n placeholder={inputPlaceholder}\n InputProps={{\n startAdornment,\n endAdornment: clearButton ? clearButtonEndAdornment : endAdornment,\n ...InputProps,\n }}\n inputProps={{\n 'aria-label': ariaLabel,\n ...inputProps,\n }}\n fullWidth={fullWidth}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n </SearchContextProvider>\n );\n});\n\n/**\n * Props for {@link SearchBar}.\n *\n * @public\n */\nexport type SearchBarProps = Partial<SearchBarBaseProps>;\n\n/**\n * Recommended search bar when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBar = forwardRef((props: SearchBarProps, ref) => {\n const { value: initialValue = '', onChange, ...rest } = props;\n\n const { term, setTerm } = useSearch();\n\n useEffect(() => {\n if (initialValue) {\n setTerm(String(initialValue));\n }\n }, [initialValue, setTerm]);\n\n const handleChange = useCallback(\n (newValue: string) => {\n if (onChange) {\n onChange(newValue);\n } else {\n setTerm(newValue);\n }\n },\n [onChange, setTerm],\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <AnalyticsContext\n attributes={{ pluginId: 'search', extension: 'SearchBar' }}\n >\n <SearchBarBase\n {...rest}\n ref={ref}\n value={term}\n onChange={handleChange}\n />\n </AnalyticsContext>\n </SearchContextProvider>\n );\n});\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchFilter.Autocomplete.esm.js","sources":["../../../src/components/SearchFilter/SearchFilter.Autocomplete.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 { ChangeEvent, useState, useMemo } from 'react';\nimport Chip from '@material-ui/core/Chip';\nimport TextField from '@material-ui/core/TextField';\nimport Autocomplete, {\n AutocompleteGetTagProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\n\nimport { useSearch } from '../../context';\nimport { useAsyncFilterValues, useDefaultFilterValue } from './hooks';\nimport { SearchFilterComponentProps } from './SearchFilter';\nimport { ensureFilterValueWithLabel, FilterValueWithLabel } from './types';\n\n/**\n * @public\n */\nexport type SearchAutocompleteFilterProps = SearchFilterComponentProps & {\n filterSelectedOptions?: boolean;\n limitTags?: number;\n multiple?: boolean;\n};\n\n/**\n * @public\n */\nexport const AutocompleteFilter = (props: SearchAutocompleteFilterProps) => {\n const {\n className,\n defaultValue,\n name,\n values: givenValues,\n valuesDebounceMs,\n label,\n filterSelectedOptions,\n limitTags,\n multiple,\n } = props;\n const [inputValue, setInputValue] = useState<string>('');\n useDefaultFilterValue(name, defaultValue);\n const asyncValues =\n typeof givenValues === 'function' ? givenValues : undefined;\n const defaultValues =\n typeof givenValues === 'function'\n ? undefined\n : givenValues?.map(v => ensureFilterValueWithLabel(v));\n const { value: values, loading } = useAsyncFilterValues(\n asyncValues,\n inputValue,\n defaultValues,\n valuesDebounceMs,\n );\n const { filters, setFilters } = useSearch();\n const filterValueWithLabel = ensureFilterValueWithLabel(\n filters[name] as string | string[] | undefined,\n );\n const filterValue = useMemo(\n () => filterValueWithLabel || (multiple ? [] : null),\n [filterValueWithLabel, multiple],\n );\n\n // Set new filter values on input change.\n const handleChange = (\n _: ChangeEvent<{}>,\n newValue: FilterValueWithLabel | FilterValueWithLabel[] | null,\n ) => {\n setFilters(prevState => {\n const { [name]: filter, ...others } = prevState;\n\n if (newValue) {\n return {\n ...others,\n [name]: Array.isArray(newValue)\n ? newValue.map(v => v.value)\n : newValue.value,\n };\n }\n return { ...others };\n });\n };\n\n // Provide the input field.\n const renderInput = (params: AutocompleteRenderInputParams) => (\n <TextField\n {...params}\n name=\"search\"\n variant=\"outlined\"\n label={label}\n fullWidth\n />\n );\n\n // Render tags as primary-colored chips.\n const renderTags = (\n tagValue: FilterValueWithLabel[],\n getTagProps: AutocompleteGetTagProps,\n ) =>\n tagValue.map((option, index: number) => (\n <Chip label={option.label} color=\"primary\" {...getTagProps({ index })} />\n ));\n\n return (\n <Autocomplete\n filterSelectedOptions={filterSelectedOptions}\n limitTags={limitTags}\n multiple={multiple}\n className={className}\n id={`${multiple ? 'multi-' : ''}select-filter-${name}--select`}\n options={values || []}\n loading={loading}\n value={filterValue}\n onChange={handleChange}\n onInputChange={(_, newValue) => setInputValue(newValue)}\n getOptionLabel={option => option.label}\n renderInput={renderInput}\n renderTags={renderTags}\n />\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SearchFilter.Autocomplete.esm.js","sources":["../../../src/components/SearchFilter/SearchFilter.Autocomplete.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 { ChangeEvent, useState, useMemo } from 'react';\nimport Chip from '@material-ui/core/Chip';\nimport TextField from '@material-ui/core/TextField';\nimport Autocomplete, {\n AutocompleteGetTagProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\n\nimport { useSearch } from '../../context';\nimport { useAsyncFilterValues, useDefaultFilterValue } from './hooks';\nimport { SearchFilterComponentProps } from './SearchFilter';\nimport { ensureFilterValueWithLabel, FilterValueWithLabel } from './types';\n\n/**\n * @public\n */\nexport type SearchAutocompleteFilterProps = SearchFilterComponentProps & {\n filterSelectedOptions?: boolean;\n limitTags?: number;\n multiple?: boolean;\n};\n\n/**\n * @public\n */\nexport const AutocompleteFilter = (props: SearchAutocompleteFilterProps) => {\n const {\n className,\n defaultValue,\n name,\n values: givenValues,\n valuesDebounceMs,\n label,\n filterSelectedOptions,\n limitTags,\n multiple,\n } = props;\n const [inputValue, setInputValue] = useState<string>('');\n useDefaultFilterValue(name, defaultValue);\n const asyncValues =\n typeof givenValues === 'function' ? givenValues : undefined;\n const defaultValues =\n typeof givenValues === 'function'\n ? undefined\n : givenValues?.map(v => ensureFilterValueWithLabel(v));\n const { value: values, loading } = useAsyncFilterValues(\n asyncValues,\n inputValue,\n defaultValues,\n valuesDebounceMs,\n );\n const { filters, setFilters } = useSearch();\n const filterValueWithLabel = ensureFilterValueWithLabel(\n filters[name] as string | string[] | undefined,\n );\n const filterValue = useMemo(\n () => filterValueWithLabel || (multiple ? [] : null),\n [filterValueWithLabel, multiple],\n );\n\n // Set new filter values on input change.\n const handleChange = (\n _: ChangeEvent<{}>,\n newValue: FilterValueWithLabel | FilterValueWithLabel[] | null,\n ) => {\n setFilters(prevState => {\n const { [name]: filter, ...others } = prevState;\n\n if (newValue) {\n return {\n ...others,\n [name]: Array.isArray(newValue)\n ? newValue.map(v => v.value)\n : newValue.value,\n };\n }\n return { ...others };\n });\n };\n\n // Provide the input field.\n const renderInput = (params: AutocompleteRenderInputParams) => (\n <TextField\n {...params}\n name=\"search\"\n variant=\"outlined\"\n label={label}\n fullWidth\n />\n );\n\n // Render tags as primary-colored chips.\n const renderTags = (\n tagValue: FilterValueWithLabel[],\n getTagProps: AutocompleteGetTagProps,\n ) =>\n tagValue.map((option, index: number) => (\n <Chip label={option.label} color=\"primary\" {...getTagProps({ index })} />\n ));\n\n return (\n <Autocomplete\n filterSelectedOptions={filterSelectedOptions}\n limitTags={limitTags}\n multiple={multiple}\n className={className}\n id={`${multiple ? 'multi-' : ''}select-filter-${name}--select`}\n options={values || []}\n loading={loading}\n value={filterValue}\n onChange={handleChange}\n onInputChange={(_, newValue) => setInputValue(newValue)}\n getOptionLabel={option => option.label}\n renderInput={renderInput}\n renderTags={renderTags}\n />\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchFilter.esm.js","sources":["../../../src/components/SearchFilter/SearchFilter.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 { ReactElement, ChangeEvent, useRef } from 'react';\nimport { capitalize } from 'lodash';\nimport { v4 as uuid } from 'uuid';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormLabel from '@material-ui/core/FormLabel';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { Select, SelectedItems } from '@backstage/core-components';\n\nimport { useSearch } from '../../context';\nimport {\n AutocompleteFilter,\n SearchAutocompleteFilterProps,\n} from './SearchFilter.Autocomplete';\nimport { useAsyncFilterValues, useDefaultFilterValue } from './hooks';\nimport { ensureFilterValueWithLabel, FilterValue } from './types';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\nconst useStyles = makeStyles({\n label: {\n textTransform: 'capitalize',\n },\n checkboxWrapper: {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n },\n textWrapper: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n});\n\n/**\n * @public\n */\nexport type SearchFilterComponentProps = {\n className?: string;\n name: string;\n label?: string;\n /**\n * Either an array of values directly, or an async function to return a list\n * of values to be used in the filter. In the autocomplete filter, the last\n * input value is provided as an input to allow values to be filtered. This\n * function is debounced and values cached.\n */\n values?: FilterValue[] | ((partial: string) => Promise<FilterValue[]>);\n defaultValue?: string[] | string | null;\n /**\n * Debounce time in milliseconds, used when values is an async callback.\n * Defaults to 250ms.\n */\n valuesDebounceMs?: number;\n};\n\n/**\n * @public\n */\nexport type SearchFilterWrapperProps = SearchFilterComponentProps & {\n component: (props: SearchFilterComponentProps) => ReactElement;\n debug?: boolean;\n};\n\n/**\n * @public\n */\nexport const CheckboxFilter = (props: SearchFilterComponentProps) => {\n const {\n className,\n defaultValue,\n label: formLabel,\n name,\n values: givenValues = [],\n valuesDebounceMs,\n } = props;\n const classes = useStyles();\n const { filters, setFilters } = useSearch();\n useDefaultFilterValue(name, defaultValue);\n const asyncValues =\n typeof givenValues === 'function' ? givenValues : undefined;\n const defaultValues =\n typeof givenValues === 'function'\n ? undefined\n : givenValues.map(v => ensureFilterValueWithLabel(v));\n const { value: values = [], loading } = useAsyncFilterValues(\n asyncValues,\n '',\n defaultValues,\n valuesDebounceMs,\n );\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n const {\n target: { value, checked },\n } = e;\n\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n const rest = ((filter as string[]) || []).filter(i => i !== value);\n const items = checked ? [...rest, value] : rest;\n return items.length ? { ...others, [name]: items } : others;\n });\n };\n\n return (\n <FormControl\n className={className}\n disabled={loading}\n fullWidth\n data-testid=\"search-checkboxfilter-next\"\n >\n {!!formLabel && (\n <FormLabel className={classes.label}>{formLabel}</FormLabel>\n )}\n {values.map(({ value, label }) => (\n <FormControlLabel\n key={value}\n classes={{\n root: classes.checkboxWrapper,\n label: classes.textWrapper,\n }}\n label={label}\n control={\n <Checkbox\n color=\"primary\"\n inputProps={{ 'aria-labelledby': label }}\n value={value}\n name={label}\n onChange={handleChange}\n checked={((filters[name] as string[]) ?? []).includes(value)}\n />\n }\n />\n ))}\n </FormControl>\n );\n};\n\n/**\n * @public\n */\nexport const SelectFilter = (props: SearchFilterComponentProps) => {\n const {\n className,\n defaultValue,\n label,\n name,\n values: givenValues,\n valuesDebounceMs,\n } = props;\n const { t } = useTranslationRef(searchReactTranslationRef);\n useDefaultFilterValue(name, defaultValue);\n const asyncValues =\n typeof givenValues === 'function' ? givenValues : undefined;\n const defaultValues =\n typeof givenValues === 'function'\n ? undefined\n : givenValues?.map(v => ensureFilterValueWithLabel(v));\n const { value: values = [], loading } = useAsyncFilterValues(\n asyncValues,\n '',\n defaultValues,\n valuesDebounceMs,\n );\n const allOptionValue = useRef(uuid());\n const allOption = {\n value: allOptionValue.current,\n label: t('searchFilter.allOptionTitle'),\n };\n const { filters, setFilters } = useSearch();\n\n const handleChange = (value: SelectedItems) => {\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n return value !== allOptionValue.current\n ? { ...others, [name]: value as string }\n : others;\n });\n };\n\n const items = [allOption, ...values];\n\n return (\n <FormControl\n disabled={loading}\n className={className}\n variant=\"filled\"\n fullWidth\n data-testid=\"search-selectfilter-next\"\n >\n <Select\n label={label ?? capitalize(name)}\n selected={(filters[name] || allOptionValue.current) as string}\n onChange={handleChange}\n items={items}\n />\n </FormControl>\n );\n};\n\n/**\n * @public\n */\nconst SearchFilter = (props: SearchFilterWrapperProps) => {\n const { component: Element, ...elementProps } = props;\n return <Element {...elementProps} />;\n};\n\nSearchFilter.Checkbox = (\n props: Omit<SearchFilterWrapperProps, 'component'> &\n SearchFilterComponentProps,\n) => <SearchFilter {...props} component={CheckboxFilter} />;\n\nSearchFilter.Select = (\n props: Omit<SearchFilterWrapperProps, 'component'> &\n SearchFilterComponentProps,\n) => <SearchFilter {...props} component={SelectFilter} />;\n\n/**\n * A control surface for a given filter field name, rendered as an autocomplete\n * textfield. A hard-coded list of values may be provided, or an async function\n * which returns values may be provided instead.\n *\n * @public\n */\nSearchFilter.Autocomplete = (props: SearchAutocompleteFilterProps) => (\n <SearchFilter {...props} component={AutocompleteFilter} />\n);\n\nexport { SearchFilter };\n"],"names":["uuid"],"mappings":"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"}
1
+ {"version":3,"file":"SearchFilter.esm.js","sources":["../../../src/components/SearchFilter/SearchFilter.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 { ReactElement, ChangeEvent, useRef } from 'react';\nimport { capitalize } from 'lodash';\nimport { v4 as uuid } from 'uuid';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormLabel from '@material-ui/core/FormLabel';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { Select, SelectedItems } from '@backstage/core-components';\n\nimport { useSearch } from '../../context';\nimport {\n AutocompleteFilter,\n SearchAutocompleteFilterProps,\n} from './SearchFilter.Autocomplete';\nimport { useAsyncFilterValues, useDefaultFilterValue } from './hooks';\nimport { ensureFilterValueWithLabel, FilterValue } from './types';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\nconst useStyles = makeStyles({\n label: {\n textTransform: 'capitalize',\n },\n checkboxWrapper: {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n },\n textWrapper: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n },\n});\n\n/**\n * @public\n */\nexport type SearchFilterComponentProps = {\n className?: string;\n name: string;\n label?: string;\n /**\n * Either an array of values directly, or an async function to return a list\n * of values to be used in the filter. In the autocomplete filter, the last\n * input value is provided as an input to allow values to be filtered. This\n * function is debounced and values cached.\n */\n values?: FilterValue[] | ((partial: string) => Promise<FilterValue[]>);\n defaultValue?: string[] | string | null;\n /**\n * Debounce time in milliseconds, used when values is an async callback.\n * Defaults to 250ms.\n */\n valuesDebounceMs?: number;\n};\n\n/**\n * @public\n */\nexport type SearchFilterWrapperProps = SearchFilterComponentProps & {\n component: (props: SearchFilterComponentProps) => ReactElement;\n debug?: boolean;\n};\n\n/**\n * @public\n */\nexport const CheckboxFilter = (props: SearchFilterComponentProps) => {\n const {\n className,\n defaultValue,\n label: formLabel,\n name,\n values: givenValues = [],\n valuesDebounceMs,\n } = props;\n const classes = useStyles();\n const { filters, setFilters } = useSearch();\n useDefaultFilterValue(name, defaultValue);\n const asyncValues =\n typeof givenValues === 'function' ? givenValues : undefined;\n const defaultValues =\n typeof givenValues === 'function'\n ? undefined\n : givenValues.map(v => ensureFilterValueWithLabel(v));\n const { value: values = [], loading } = useAsyncFilterValues(\n asyncValues,\n '',\n defaultValues,\n valuesDebounceMs,\n );\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n const {\n target: { value, checked },\n } = e;\n\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n const rest = ((filter as string[]) || []).filter(i => i !== value);\n const items = checked ? [...rest, value] : rest;\n return items.length ? { ...others, [name]: items } : others;\n });\n };\n\n return (\n <FormControl\n className={className}\n disabled={loading}\n fullWidth\n data-testid=\"search-checkboxfilter-next\"\n >\n {!!formLabel && (\n <FormLabel className={classes.label}>{formLabel}</FormLabel>\n )}\n {values.map(({ value, label }) => (\n <FormControlLabel\n key={value}\n classes={{\n root: classes.checkboxWrapper,\n label: classes.textWrapper,\n }}\n label={label}\n control={\n <Checkbox\n color=\"primary\"\n inputProps={{ 'aria-labelledby': label }}\n value={value}\n name={label}\n onChange={handleChange}\n checked={((filters[name] as string[]) ?? []).includes(value)}\n />\n }\n />\n ))}\n </FormControl>\n );\n};\n\n/**\n * @public\n */\nexport const SelectFilter = (props: SearchFilterComponentProps) => {\n const {\n className,\n defaultValue,\n label,\n name,\n values: givenValues,\n valuesDebounceMs,\n } = props;\n const { t } = useTranslationRef(searchReactTranslationRef);\n useDefaultFilterValue(name, defaultValue);\n const asyncValues =\n typeof givenValues === 'function' ? givenValues : undefined;\n const defaultValues =\n typeof givenValues === 'function'\n ? undefined\n : givenValues?.map(v => ensureFilterValueWithLabel(v));\n const { value: values = [], loading } = useAsyncFilterValues(\n asyncValues,\n '',\n defaultValues,\n valuesDebounceMs,\n );\n const allOptionValue = useRef(uuid());\n const allOption = {\n value: allOptionValue.current,\n label: t('searchFilter.allOptionTitle'),\n };\n const { filters, setFilters } = useSearch();\n\n const handleChange = (value: SelectedItems) => {\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n return value !== allOptionValue.current\n ? { ...others, [name]: value as string }\n : others;\n });\n };\n\n const items = [allOption, ...values];\n\n return (\n <FormControl\n disabled={loading}\n className={className}\n variant=\"filled\"\n fullWidth\n data-testid=\"search-selectfilter-next\"\n >\n <Select\n label={label ?? capitalize(name)}\n selected={(filters[name] || allOptionValue.current) as string}\n onChange={handleChange}\n items={items}\n />\n </FormControl>\n );\n};\n\n/**\n * @public\n */\nconst SearchFilter = (props: SearchFilterWrapperProps) => {\n const { component: Element, ...elementProps } = props;\n return <Element {...elementProps} />;\n};\n\nSearchFilter.Checkbox = (\n props: Omit<SearchFilterWrapperProps, 'component'> &\n SearchFilterComponentProps,\n) => <SearchFilter {...props} component={CheckboxFilter} />;\n\nSearchFilter.Select = (\n props: Omit<SearchFilterWrapperProps, 'component'> &\n SearchFilterComponentProps,\n) => <SearchFilter {...props} component={SelectFilter} />;\n\n/**\n * A control surface for a given filter field name, rendered as an autocomplete\n * textfield. A hard-coded list of values may be provided, or an async function\n * which returns values may be provided instead.\n *\n * @public\n */\nSearchFilter.Autocomplete = (props: SearchAutocompleteFilterProps) => (\n <SearchFilter {...props} component={AutocompleteFilter} />\n);\n\nexport { SearchFilter };\n"],"names":["uuid"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { useRef, useCallback, useEffect } from 'react';
1
+ import { useEffect, useRef, useCallback } from 'react';
2
2
  import useAsyncFn from 'react-use/esm/useAsyncFn';
3
3
  import useDebounce from 'react-use/esm/useDebounce';
4
4
  import { useSearch } from '../../context/SearchContext.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.esm.js","sources":["../../../src/components/SearchFilter/hooks.ts"],"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 { useCallback, useEffect, useRef } from 'react';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDebounce from 'react-use/esm/useDebounce';\n\nimport { useSearch } from '../../context';\nimport {\n ensureFilterValueWithLabel,\n FilterValue,\n FilterValueWithLabel,\n} from './types';\n\n/**\n * Utility hook for either asynchronously loading filter values from a given\n * function or synchronously providing a given list of default values.\n *\n * @public\n */\nexport const useAsyncFilterValues = (\n fn: ((partial: string) => Promise<FilterValue[]>) | undefined,\n inputValue: string,\n defaultValues: FilterValueWithLabel[] = [],\n debounce: number = 250,\n) => {\n const valuesMemo = useRef<\n Record<string, FilterValueWithLabel[] | Promise<FilterValueWithLabel[]>>\n >({});\n const definiteFn = useCallback(\n async (partial: string) => {\n return (\n (await fn?.(partial))?.map(v => ensureFilterValueWithLabel(v)) || []\n );\n },\n [fn],\n );\n\n const [state, callback] = useAsyncFn(definiteFn, [inputValue], {\n loading: true,\n });\n\n // Do not invoke the given function more than necessary.\n useDebounce(\n () => {\n // Performance optimization: only invoke the callback once per inputValue\n // for the lifetime of the hook/component.\n if (valuesMemo.current[inputValue] === undefined) {\n valuesMemo.current[inputValue] = callback(inputValue).then(values => {\n // Override the value for future immediate returns.\n valuesMemo.current[inputValue] = values;\n return values;\n });\n }\n },\n debounce,\n [callback, inputValue],\n );\n\n // Immediately return the default values if they are provided.\n if (defaultValues.length) {\n return {\n loading: false,\n value: defaultValues,\n };\n }\n\n // Immediately return a memoized value if it is set (and not a promise).\n const possibleValue = valuesMemo.current[inputValue];\n if (Array.isArray(possibleValue)) {\n return {\n loading: false,\n value: possibleValue,\n };\n }\n\n return state;\n};\n\n/**\n * Utility hook for applying a given default value to the search context.\n *\n * @public\n */\nexport const useDefaultFilterValue = (\n name: string,\n defaultValue?: string | string[] | null,\n) => {\n const { setFilters } = useSearch();\n\n useEffect(() => {\n if (defaultValue && [defaultValue].flat().length > 0) {\n setFilters(prevFilters => ({\n ...prevFilters,\n [name]: defaultValue,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n};\n"],"names":[],"mappings":";;;;;;AAiCa,MAAA,oBAAA,GAAuB,CAClC,EACA,EAAA,UAAA,EACA,gBAAwC,EAAC,EACzC,WAAmB,GAChB,KAAA;AACH,EAAM,MAAA,UAAA,GAAa,MAEjB,CAAA,EAAE,CAAA;AACJ,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACjB,OAAO,OAAoB,KAAA;AACzB,MACG,OAAA,CAAA,MAAM,EAAK,GAAA,OAAO,CAAI,GAAA,GAAA,CAAI,OAAK,0BAA2B,CAAA,CAAC,CAAC,CAAA,IAAK,EAAC;AAAA,KAEvE;AAAA,IACA,CAAC,EAAE;AAAA,GACL;AAEA,EAAM,MAAA,CAAC,OAAO,QAAQ,CAAA,GAAI,WAAW,UAAY,EAAA,CAAC,UAAU,CAAG,EAAA;AAAA,IAC7D,OAAS,EAAA;AAAA,GACV,CAAA;AAGD,EAAA,WAAA;AAAA,IACE,MAAM;AAGJ,MAAA,IAAI,UAAW,CAAA,OAAA,CAAQ,UAAU,CAAA,KAAM,KAAW,CAAA,EAAA;AAChD,QAAA,UAAA,CAAW,QAAQ,UAAU,CAAA,GAAI,SAAS,UAAU,CAAA,CAAE,KAAK,CAAU,MAAA,KAAA;AAEnE,UAAW,UAAA,CAAA,OAAA,CAAQ,UAAU,CAAI,GAAA,MAAA;AACjC,UAAO,OAAA,MAAA;AAAA,SACR,CAAA;AAAA;AACH,KACF;AAAA,IACA,QAAA;AAAA,IACA,CAAC,UAAU,UAAU;AAAA,GACvB;AAGA,EAAA,IAAI,cAAc,MAAQ,EAAA;AACxB,IAAO,OAAA;AAAA,MACL,OAAS,EAAA,KAAA;AAAA,MACT,KAAO,EAAA;AAAA,KACT;AAAA;AAIF,EAAM,MAAA,aAAA,GAAgB,UAAW,CAAA,OAAA,CAAQ,UAAU,CAAA;AACnD,EAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,aAAa,CAAG,EAAA;AAChC,IAAO,OAAA;AAAA,MACL,OAAS,EAAA,KAAA;AAAA,MACT,KAAO,EAAA;AAAA,KACT;AAAA;AAGF,EAAO,OAAA,KAAA;AACT;AAOa,MAAA,qBAAA,GAAwB,CACnC,IAAA,EACA,YACG,KAAA;AACH,EAAM,MAAA,EAAE,UAAW,EAAA,GAAI,SAAU,EAAA;AAEjC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,gBAAgB,CAAC,YAAY,EAAE,IAAK,EAAA,CAAE,SAAS,CAAG,EAAA;AACpD,MAAA,UAAA,CAAW,CAAgB,WAAA,MAAA;AAAA,QACzB,GAAG,WAAA;AAAA,QACH,CAAC,IAAI,GAAG;AAAA,OACR,CAAA,CAAA;AAAA;AACJ,GAEF,EAAG,EAAE,CAAA;AACP;;;;"}
1
+ {"version":3,"file":"hooks.esm.js","sources":["../../../src/components/SearchFilter/hooks.ts"],"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 { useCallback, useEffect, useRef } from 'react';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDebounce from 'react-use/esm/useDebounce';\n\nimport { useSearch } from '../../context';\nimport {\n ensureFilterValueWithLabel,\n FilterValue,\n FilterValueWithLabel,\n} from './types';\n\n/**\n * Utility hook for either asynchronously loading filter values from a given\n * function or synchronously providing a given list of default values.\n *\n * @public\n */\nexport const useAsyncFilterValues = (\n fn: ((partial: string) => Promise<FilterValue[]>) | undefined,\n inputValue: string,\n defaultValues: FilterValueWithLabel[] = [],\n debounce: number = 250,\n) => {\n const valuesMemo = useRef<\n Record<string, FilterValueWithLabel[] | Promise<FilterValueWithLabel[]>>\n >({});\n const definiteFn = useCallback(\n async (partial: string) => {\n return (\n (await fn?.(partial))?.map(v => ensureFilterValueWithLabel(v)) || []\n );\n },\n [fn],\n );\n\n const [state, callback] = useAsyncFn(definiteFn, [inputValue], {\n loading: true,\n });\n\n // Do not invoke the given function more than necessary.\n useDebounce(\n () => {\n // Performance optimization: only invoke the callback once per inputValue\n // for the lifetime of the hook/component.\n if (valuesMemo.current[inputValue] === undefined) {\n valuesMemo.current[inputValue] = callback(inputValue).then(values => {\n // Override the value for future immediate returns.\n valuesMemo.current[inputValue] = values;\n return values;\n });\n }\n },\n debounce,\n [callback, inputValue],\n );\n\n // Immediately return the default values if they are provided.\n if (defaultValues.length) {\n return {\n loading: false,\n value: defaultValues,\n };\n }\n\n // Immediately return a memoized value if it is set (and not a promise).\n const possibleValue = valuesMemo.current[inputValue];\n if (Array.isArray(possibleValue)) {\n return {\n loading: false,\n value: possibleValue,\n };\n }\n\n return state;\n};\n\n/**\n * Utility hook for applying a given default value to the search context.\n *\n * @public\n */\nexport const useDefaultFilterValue = (\n name: string,\n defaultValue?: string | string[] | null,\n) => {\n const { setFilters } = useSearch();\n\n useEffect(() => {\n if (defaultValue && [defaultValue].flat().length > 0) {\n setFilters(prevFilters => ({\n ...prevFilters,\n [name]: defaultValue,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n};\n"],"names":[],"mappings":";;;;;;AAiCO,MAAM,oBAAA,GAAuB,CAClC,EAAA,EACA,UAAA,EACA,gBAAwC,EAAC,EACzC,WAAmB,GAAA,KAChB;AACH,EAAA,MAAM,UAAA,GAAa,MAAA,CAEjB,EAAE,CAAA;AACJ,EAAA,MAAM,UAAA,GAAa,WAAA;AAAA,IACjB,OAAO,OAAA,KAAoB;AACzB,MAAA,OAAA,CACG,MAAM,EAAA,GAAK,OAAO,CAAA,GAAI,GAAA,CAAI,OAAK,0BAAA,CAA2B,CAAC,CAAC,CAAA,IAAK,EAAC;AAAA,IAEvE,CAAA;AAAA,IACA,CAAC,EAAE;AAAA,GACL;AAEA,EAAA,MAAM,CAAC,OAAO,QAAQ,CAAA,GAAI,WAAW,UAAA,EAAY,CAAC,UAAU,CAAA,EAAG;AAAA,IAC7D,OAAA,EAAS;AAAA,GACV,CAAA;AAGD,EAAA,WAAA;AAAA,IACE,MAAM;AAGJ,MAAA,IAAI,UAAA,CAAW,OAAA,CAAQ,UAAU,CAAA,KAAM,MAAA,EAAW;AAChD,QAAA,UAAA,CAAW,QAAQ,UAAU,CAAA,GAAI,SAAS,UAAU,CAAA,CAAE,KAAK,CAAA,MAAA,KAAU;AAEnE,UAAA,UAAA,CAAW,OAAA,CAAQ,UAAU,CAAA,GAAI,MAAA;AACjC,UAAA,OAAO,MAAA;AAAA,QACT,CAAC,CAAA;AAAA,MACH;AAAA,IACF,CAAA;AAAA,IACA,QAAA;AAAA,IACA,CAAC,UAAU,UAAU;AAAA,GACvB;AAGA,EAAA,IAAI,cAAc,MAAA,EAAQ;AACxB,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,KAAA,EAAO;AAAA,KACT;AAAA,EACF;AAGA,EAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,OAAA,CAAQ,UAAU,CAAA;AACnD,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,aAAa,CAAA,EAAG;AAChC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,KAAA,EAAO;AAAA,KACT;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;AAOO,MAAM,qBAAA,GAAwB,CACnC,IAAA,EACA,YAAA,KACG;AACH,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,SAAA,EAAU;AAEjC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,gBAAgB,CAAC,YAAY,EAAE,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AACpD,MAAA,UAAA,CAAW,CAAA,WAAA,MAAgB;AAAA,QACzB,GAAG,WAAA;AAAA,QACH,CAAC,IAAI,GAAG;AAAA,OACV,CAAE,CAAA;AAAA,IACJ;AAAA,EAEF,CAAA,EAAG,EAAE,CAAA;AACP;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.esm.js","sources":["../../../src/components/SearchFilter/types.ts"],"sourcesContent":["/*\n * Copyright 2025 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\n/**\n * @public\n */\nexport type FilterValueWithLabel = { value: string; label: string };\n\n/**\n * @public\n */\nexport type FilterValue = string | FilterValueWithLabel;\n\n/**\n * Ensure a value is on object form, with a label.\n * Accepts undefined, a single value, or an array of values and returns the\n * expected result - a filter value/label or an array of such, if any.\n */\nexport function ensureFilterValueWithLabel<T extends FilterValue>(\n value: T | T[] | undefined,\n): typeof value extends undefined\n ? undefined\n : typeof value extends ArrayLike<any>\n ? FilterValueWithLabel[]\n : FilterValueWithLabel {\n if (value === undefined) {\n return undefined as any;\n }\n\n if (Array.isArray(value)) {\n return value.map(\n v => ensureFilterValueWithLabel(v) as FilterValueWithLabel,\n ) as any;\n }\n\n if (typeof value === 'string') {\n return { value, label: value } as FilterValueWithLabel as any;\n }\n return value as FilterValueWithLabel as any;\n}\n"],"names":[],"mappings":"AA+BO,SAAS,2BACd,KAKuB,EAAA;AACvB,EAAA,IAAI,UAAU,KAAW,CAAA,EAAA;AACvB,IAAO,OAAA,KAAA,CAAA;AAAA;AAGT,EAAI,IAAA,KAAA,CAAM,OAAQ,CAAA,KAAK,CAAG,EAAA;AACxB,IAAA,OAAO,KAAM,CAAA,GAAA;AAAA,MACX,CAAA,CAAA,KAAK,2BAA2B,CAAC;AAAA,KACnC;AAAA;AAGF,EAAI,IAAA,OAAO,UAAU,QAAU,EAAA;AAC7B,IAAO,OAAA,EAAE,KAAO,EAAA,KAAA,EAAO,KAAM,EAAA;AAAA;AAE/B,EAAO,OAAA,KAAA;AACT;;;;"}
1
+ {"version":3,"file":"types.esm.js","sources":["../../../src/components/SearchFilter/types.ts"],"sourcesContent":["/*\n * Copyright 2025 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\n/**\n * @public\n */\nexport type FilterValueWithLabel = { value: string; label: string };\n\n/**\n * @public\n */\nexport type FilterValue = string | FilterValueWithLabel;\n\n/**\n * Ensure a value is on object form, with a label.\n * Accepts undefined, a single value, or an array of values and returns the\n * expected result - a filter value/label or an array of such, if any.\n */\nexport function ensureFilterValueWithLabel<T extends FilterValue>(\n value: T | T[] | undefined,\n): typeof value extends undefined\n ? undefined\n : typeof value extends ArrayLike<any>\n ? FilterValueWithLabel[]\n : FilterValueWithLabel {\n if (value === undefined) {\n return undefined as any;\n }\n\n if (Array.isArray(value)) {\n return value.map(\n v => ensureFilterValueWithLabel(v) as FilterValueWithLabel,\n ) as any;\n }\n\n if (typeof value === 'string') {\n return { value, label: value } as FilterValueWithLabel as any;\n }\n return value as FilterValueWithLabel as any;\n}\n"],"names":[],"mappings":"AA+BO,SAAS,2BACd,KAAA,EAKuB;AACvB,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,KAAA,CAAM,GAAA;AAAA,MACX,CAAA,CAAA,KAAK,2BAA2B,CAAC;AAAA,KACnC;AAAA,EACF;AAEA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAM;AAAA,EAC/B;AACA,EAAA,OAAO,KAAA;AACT;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchPagination.esm.js","sources":["../../../src/components/SearchPagination/SearchPagination.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 {\n ReactNode,\n ChangeEvent,\n MouseEvent,\n useCallback,\n useMemo,\n} from 'react';\nimport TablePagination from '@material-ui/core/TablePagination';\nimport { useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\nconst encodePageCursor = (pageCursor: number): string => {\n return Buffer.from(pageCursor.toString(), 'utf-8').toString('base64');\n};\n\nconst decodePageCursor = (pageCursor?: string): number => {\n if (!pageCursor) return 0;\n return Number(Buffer.from(pageCursor, 'base64').toString('utf-8'));\n};\n\n/**\n * A page limit option, this value must not be greater than 100.\n * @public\n */\nexport type SearchPaginationLimitOption<\n Current extends number = 101,\n Accumulator extends number[] = [],\n> = Accumulator['length'] extends Current\n ? Accumulator[number]\n : SearchPaginationLimitOption<\n Current,\n [...Accumulator, Accumulator['length']]\n >;\n\n/**\n * A page limit text, this function is called with a \"\\{ from, to, page, count \\}\" object.\n * @public\n */\nexport type SearchPaginationLimitText = (params: {\n from: number;\n to: number;\n page: number;\n count: number;\n}) => ReactNode;\n\n/**\n * Props for {@link SearchPaginationBase}.\n * @public\n */\nexport type SearchPaginationBaseProps = {\n /**\n * The component class name.\n */\n className?: string;\n /**\n * The total number of results.\n * For an unknown number of items, provide -1.\n * Defaults to -1.\n */\n total?: number;\n /**\n * The cursor for the current page.\n */\n cursor?: string;\n /**\n * Whether a next page exists\n */\n hasNextPage?: boolean;\n /**\n * Callback fired when the current page cursor is changed.\n */\n onCursorChange?: (pageCursor: string) => void;\n /**\n * The limit of results per page.\n * Set -1 to display all the results.\n */\n limit?: number;\n /**\n * Customize the results per page label.\n * Defaults to \"Results per page:\".\n */\n limitLabel?: ReactNode;\n /**\n * Customize the results per page text.\n * Defaults to \"(\\{ from, to, count \\}) =\\> count \\> 0 ? `of $\\{count\\}` : `$\\{from\\}-$\\{to\\}`\".\n */\n limitText?: SearchPaginationLimitText;\n /**\n * Options for setting how many results show per page.\n * If less than two options are available, no select field will be displayed.\n * Use -1 for the value with a custom label to show all the results.\n * Defaults to [10, 25, 50, 100].\n */\n limitOptions?: SearchPaginationLimitOption[];\n /**\n * Callback fired when the number of results per page is changed.\n */\n onLimitChange?: (value: number) => void;\n};\n\n/**\n * A component with controls for search results pagination.\n * @param props - See {@link SearchPaginationBaseProps}.\n * @public\n */\nexport const SearchPaginationBase = (props: SearchPaginationBaseProps) => {\n const { t } = useTranslationRef(searchReactTranslationRef);\n const {\n total: count = -1,\n cursor: pageCursor,\n hasNextPage,\n onCursorChange: onPageCursorChange,\n limit: rowsPerPage = 25,\n limitLabel: labelRowsPerPage = t('searchPagination.limitLabel'),\n limitText: labelDisplayedRows = ({ from, to }) =>\n count > 0\n ? t('searchPagination.limitText', { num: `${count}` })\n : `${from}-${to}`,\n limitOptions: rowsPerPageOptions,\n onLimitChange: onPageLimitChange,\n ...rest\n } = props;\n\n const page = useMemo(() => decodePageCursor(pageCursor), [pageCursor]);\n\n const handlePageChange = useCallback(\n (_: MouseEvent<HTMLButtonElement> | null, newValue: number) => {\n onPageCursorChange?.(encodePageCursor(newValue));\n },\n [onPageCursorChange],\n );\n\n const handleRowsPerPageChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {\n const newValue = e.target.value;\n onPageLimitChange?.(parseInt(newValue, 10));\n },\n [onPageLimitChange],\n );\n\n return (\n <TablePagination\n {...rest}\n component=\"div\"\n count={count}\n page={page}\n nextIconButtonProps={{\n ...(hasNextPage !== undefined && { disabled: !hasNextPage }),\n }}\n onPageChange={handlePageChange}\n rowsPerPage={rowsPerPage}\n labelRowsPerPage={labelRowsPerPage}\n labelDisplayedRows={labelDisplayedRows}\n rowsPerPageOptions={rowsPerPageOptions}\n onRowsPerPageChange={handleRowsPerPageChange}\n />\n );\n};\n\n/**\n * Props for {@link SearchPagination}.\n * @public\n */\nexport type SearchPaginationProps = Omit<\n SearchPaginationBaseProps,\n | 'pageLimit'\n | 'onLimitChange'\n | 'pageCursor'\n | 'onPageCursorChange'\n | 'hasNextPage'\n>;\n\n/**\n * A component for setting the search context page limit and cursor.\n * @param props - See {@link SearchPaginationProps}.\n * @public\n */\nexport const SearchPagination = (props: SearchPaginationProps) => {\n const { pageLimit, setPageLimit, pageCursor, setPageCursor, fetchNextPage } =\n useSearch();\n\n const handlePageLimitChange = useCallback(\n (newPageLimit: number) => {\n setPageLimit(newPageLimit);\n setPageCursor(undefined);\n },\n [setPageLimit, setPageCursor],\n );\n\n return (\n <SearchPaginationBase\n {...props}\n hasNextPage={!!fetchNextPage}\n limit={pageLimit}\n onLimitChange={handlePageLimitChange}\n cursor={pageCursor}\n onCursorChange={setPageCursor}\n />\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SearchPagination.esm.js","sources":["../../../src/components/SearchPagination/SearchPagination.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 {\n ReactNode,\n ChangeEvent,\n MouseEvent,\n useCallback,\n useMemo,\n} from 'react';\nimport TablePagination from '@material-ui/core/TablePagination';\nimport { useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\nconst encodePageCursor = (pageCursor: number): string => {\n return Buffer.from(pageCursor.toString(), 'utf-8').toString('base64');\n};\n\nconst decodePageCursor = (pageCursor?: string): number => {\n if (!pageCursor) return 0;\n return Number(Buffer.from(pageCursor, 'base64').toString('utf-8'));\n};\n\n/**\n * A page limit option, this value must not be greater than 100.\n * @public\n */\nexport type SearchPaginationLimitOption<\n Current extends number = 101,\n Accumulator extends number[] = [],\n> = Accumulator['length'] extends Current\n ? Accumulator[number]\n : SearchPaginationLimitOption<\n Current,\n [...Accumulator, Accumulator['length']]\n >;\n\n/**\n * A page limit text, this function is called with a \"\\{ from, to, page, count \\}\" object.\n * @public\n */\nexport type SearchPaginationLimitText = (params: {\n from: number;\n to: number;\n page: number;\n count: number;\n}) => ReactNode;\n\n/**\n * Props for {@link SearchPaginationBase}.\n * @public\n */\nexport type SearchPaginationBaseProps = {\n /**\n * The component class name.\n */\n className?: string;\n /**\n * The total number of results.\n * For an unknown number of items, provide -1.\n * Defaults to -1.\n */\n total?: number;\n /**\n * The cursor for the current page.\n */\n cursor?: string;\n /**\n * Whether a next page exists\n */\n hasNextPage?: boolean;\n /**\n * Callback fired when the current page cursor is changed.\n */\n onCursorChange?: (pageCursor: string) => void;\n /**\n * The limit of results per page.\n * Set -1 to display all the results.\n */\n limit?: number;\n /**\n * Customize the results per page label.\n * Defaults to \"Results per page:\".\n */\n limitLabel?: ReactNode;\n /**\n * Customize the results per page text.\n * Defaults to \"(\\{ from, to, count \\}) =\\> count \\> 0 ? `of $\\{count\\}` : `$\\{from\\}-$\\{to\\}`\".\n */\n limitText?: SearchPaginationLimitText;\n /**\n * Options for setting how many results show per page.\n * If less than two options are available, no select field will be displayed.\n * Use -1 for the value with a custom label to show all the results.\n * Defaults to [10, 25, 50, 100].\n */\n limitOptions?: SearchPaginationLimitOption[];\n /**\n * Callback fired when the number of results per page is changed.\n */\n onLimitChange?: (value: number) => void;\n};\n\n/**\n * A component with controls for search results pagination.\n * @param props - See {@link SearchPaginationBaseProps}.\n * @public\n */\nexport const SearchPaginationBase = (props: SearchPaginationBaseProps) => {\n const { t } = useTranslationRef(searchReactTranslationRef);\n const {\n total: count = -1,\n cursor: pageCursor,\n hasNextPage,\n onCursorChange: onPageCursorChange,\n limit: rowsPerPage = 25,\n limitLabel: labelRowsPerPage = t('searchPagination.limitLabel'),\n limitText: labelDisplayedRows = ({ from, to }) =>\n count > 0\n ? t('searchPagination.limitText', { num: `${count}` })\n : `${from}-${to}`,\n limitOptions: rowsPerPageOptions,\n onLimitChange: onPageLimitChange,\n ...rest\n } = props;\n\n const page = useMemo(() => decodePageCursor(pageCursor), [pageCursor]);\n\n const handlePageChange = useCallback(\n (_: MouseEvent<HTMLButtonElement> | null, newValue: number) => {\n onPageCursorChange?.(encodePageCursor(newValue));\n },\n [onPageCursorChange],\n );\n\n const handleRowsPerPageChange = useCallback(\n (e: ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {\n const newValue = e.target.value;\n onPageLimitChange?.(parseInt(newValue, 10));\n },\n [onPageLimitChange],\n );\n\n return (\n <TablePagination\n {...rest}\n component=\"div\"\n count={count}\n page={page}\n nextIconButtonProps={{\n ...(hasNextPage !== undefined && { disabled: !hasNextPage }),\n }}\n onPageChange={handlePageChange}\n rowsPerPage={rowsPerPage}\n labelRowsPerPage={labelRowsPerPage}\n labelDisplayedRows={labelDisplayedRows}\n rowsPerPageOptions={rowsPerPageOptions}\n onRowsPerPageChange={handleRowsPerPageChange}\n />\n );\n};\n\n/**\n * Props for {@link SearchPagination}.\n * @public\n */\nexport type SearchPaginationProps = Omit<\n SearchPaginationBaseProps,\n | 'pageLimit'\n | 'onLimitChange'\n | 'pageCursor'\n | 'onPageCursorChange'\n | 'hasNextPage'\n>;\n\n/**\n * A component for setting the search context page limit and cursor.\n * @param props - See {@link SearchPaginationProps}.\n * @public\n */\nexport const SearchPagination = (props: SearchPaginationProps) => {\n const { pageLimit, setPageLimit, pageCursor, setPageCursor, fetchNextPage } =\n useSearch();\n\n const handlePageLimitChange = useCallback(\n (newPageLimit: number) => {\n setPageLimit(newPageLimit);\n setPageCursor(undefined);\n },\n [setPageLimit, setPageCursor],\n );\n\n return (\n <SearchPaginationBase\n {...props}\n hasNextPage={!!fetchNextPage}\n limit={pageLimit}\n onLimitChange={handlePageLimitChange}\n cursor={pageCursor}\n onCursorChange={setPageCursor}\n />\n );\n};\n"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import useAsync from 'react-use/esm/useAsync';
3
3
  import { isFunction } from 'lodash';
4
4
  import { EmptyState, Progress, ResponseErrorPanel } from '@backstage/core-components';
5
- import { useApi, AnalyticsContext } from '@backstage/core-plugin-api';
5
+ import { AnalyticsContext, useApi } from '@backstage/core-plugin-api';
6
6
  import { searchApiRef } from '../../api.esm.js';
7
7
  import { useSearch } from '../../context/SearchContext.esm.js';
8
8
  import { SearchResultListItemExtensions } from '../../extensions.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResult.esm.js","sources":["../../../src/components/SearchResult/SearchResult.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 { ReactNode } from 'react';\nimport useAsync, { AsyncState } from 'react-use/esm/useAsync';\nimport { isFunction } from 'lodash';\n\nimport {\n Progress,\n EmptyState,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { useApi, AnalyticsContext } from '@backstage/core-plugin-api';\nimport { SearchQuery, SearchResultSet } from '@backstage/plugin-search-common';\n\nimport { searchApiRef } from '../../api';\nimport { useSearch } from '../../context';\nimport {\n SearchResultListItemExtensions,\n SearchResultListItemExtensionsProps,\n} from '../../extensions';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchResultContext}\n * @public\n */\nexport type SearchResultContextProps = {\n /**\n * A child function that receives an asynchronous result set and returns a react element.\n */\n children: (\n state: AsyncState<SearchResultSet>,\n query: Partial<SearchQuery>,\n ) => JSX.Element | null;\n};\n\n/**\n * Provides context-based results to a child function.\n * @param props - see {@link SearchResultContextProps}.\n * @example\n * ```\n * <SearchResultContext>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultContext>\n * ```\n * @public\n */\nexport const SearchResultContext = (props: SearchResultContextProps) => {\n const { children } = props;\n const context = useSearch();\n const { result: state, ...query } = context;\n return children(state, query);\n};\n\n/**\n * Props for {@link SearchResultApi}\n * @public\n */\nexport type SearchResultApiProps = SearchResultContextProps & {\n query: Partial<SearchQuery>;\n};\n\n/**\n * Request results through the search api and provide them to a child function.\n * @param props - see {@link SearchResultApiProps}.\n * @example\n * ```\n * <SearchResultApi>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultApi>\n * ```\n * @public\n */\nexport const SearchResultApi = (props: SearchResultApiProps) => {\n const { query, children } = props;\n const searchApi = useApi(searchApiRef);\n\n const state = useAsync(() => {\n const { term = '', types = [], filters = {}, ...rest } = query;\n return searchApi.query({ ...rest, term, types, filters });\n }, [query]);\n\n return children(state, query);\n};\n\n/**\n * Props for {@link SearchResultState}\n * @public\n */\nexport type SearchResultStateProps = SearchResultContextProps &\n Partial<SearchResultApiProps>;\n\n/**\n * Call a child render function passing a search state as an argument.\n * @remarks By default, results are taken from context, but when a \"query\" prop is set, results are requested from the search api.\n * @param props - see {@link SearchResultStateProps}.\n * @example\n * Consuming results from context:\n * ```\n * <SearchResultState>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultState>\n * ```\n * @example\n * Requesting results using the search api:\n * ```\n * <SearchResultState query={{ term: 'documentation' }}>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultState>\n * ```\n * @public\n */\nexport const SearchResultState = (props: SearchResultStateProps) => {\n const { query, children } = props;\n\n return query ? (\n <SearchResultApi query={query}>{children}</SearchResultApi>\n ) : (\n <SearchResultContext>{children}</SearchResultContext>\n );\n};\n\n/**\n * Props for {@link SearchResult}\n * @public\n */\nexport type SearchResultProps = Pick<SearchResultStateProps, 'query'> &\n Omit<SearchResultListItemExtensionsProps, 'results' | 'children'> & {\n children?: ReactNode | ((resultSet: SearchResultSet) => JSX.Element);\n noResultsComponent?: JSX.Element;\n };\n\n/**\n * Renders results from a parent search context or api.\n * @remarks default components for loading, error and empty variants are returned.\n * @param props - see {@link SearchResultProps}.\n * @public\n */\nexport const SearchResultComponent = (props: SearchResultProps) => {\n const { t } = useTranslationRef(searchReactTranslationRef);\n const {\n query,\n children,\n noResultsComponent = (\n <EmptyState missing=\"data\" title={t('noResultsDescription')} />\n ),\n ...rest\n } = props;\n\n return (\n <SearchResultState query={query}>\n {({ loading, error, value }) => {\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <ResponseErrorPanel\n title=\"Error encountered while fetching search results\"\n error={error}\n />\n );\n }\n\n if (!value?.results.length) {\n return noResultsComponent;\n }\n\n if (isFunction(children)) {\n return children(value);\n }\n\n return (\n <SearchResultListItemExtensions {...rest} results={value.results}>\n {children}\n </SearchResultListItemExtensions>\n );\n }}\n </SearchResultState>\n );\n};\n\n/**\n * A component returning the search result from a parent search context or api.\n * @param props - see {@link SearchResultProps}.\n * @public\n */\nexport const SearchResult = (props: SearchResultProps) => (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'SearchResult',\n }}\n >\n <SearchResultComponent {...props} />\n </AnalyticsContext>\n);\n"],"names":[],"mappings":";;;;;;;;;;;AAuEa,MAAA,mBAAA,GAAsB,CAAC,KAAoC,KAAA;AACtE,EAAM,MAAA,EAAE,UAAa,GAAA,KAAA;AACrB,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAO,EAAA,GAAG,OAAU,GAAA,OAAA;AACpC,EAAO,OAAA,QAAA,CAAS,OAAO,KAAK,CAAA;AAC9B;AA8Ba,MAAA,eAAA,GAAkB,CAAC,KAAgC,KAAA;AAC9D,EAAM,MAAA,EAAE,KAAO,EAAA,QAAA,EAAa,GAAA,KAAA;AAC5B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA;AAErC,EAAM,MAAA,KAAA,GAAQ,SAAS,MAAM;AAC3B,IAAM,MAAA,EAAE,IAAO,GAAA,EAAA,EAAI,KAAQ,GAAA,EAAI,EAAA,OAAA,GAAU,EAAC,EAAG,GAAG,IAAA,EAAS,GAAA,KAAA;AACzD,IAAO,OAAA,SAAA,CAAU,MAAM,EAAE,GAAG,MAAM,IAAM,EAAA,KAAA,EAAO,SAAS,CAAA;AAAA,GAC1D,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAO,OAAA,QAAA,CAAS,OAAO,KAAK,CAAA;AAC9B;AA+Ca,MAAA,iBAAA,GAAoB,CAAC,KAAkC,KAAA;AAClE,EAAM,MAAA,EAAE,KAAO,EAAA,QAAA,EAAa,GAAA,KAAA;AAE5B,EAAO,OAAA,KAAA,uBACJ,eAAgB,EAAA,EAAA,KAAA,EAAe,UAAS,CAEzC,mBAAA,GAAA,CAAC,uBAAqB,QAAS,EAAA,CAAA;AAEnC;AAkBa,MAAA,qBAAA,GAAwB,CAAC,KAA6B,KAAA;AACjE,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,yBAAyB,CAAA;AACzD,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,QAAA;AAAA,IACA,kBAAA,uBACG,UAAW,EAAA,EAAA,OAAA,EAAQ,QAAO,KAAO,EAAA,CAAA,CAAE,sBAAsB,CAAG,EAAA,CAAA;AAAA,IAE/D,GAAG;AAAA,GACD,GAAA,KAAA;AAEJ,EACE,uBAAA,GAAA,CAAC,qBAAkB,KAChB,EAAA,QAAA,EAAA,CAAC,EAAE,OAAS,EAAA,KAAA,EAAO,OAAY,KAAA;AAC9B,IAAA,IAAI,OAAS,EAAA;AACX,MAAA,2BAAQ,QAAS,EAAA,EAAA,CAAA;AAAA;AAGnB,IAAA,IAAI,KAAO,EAAA;AACT,MACE,uBAAA,GAAA;AAAA,QAAC,kBAAA;AAAA,QAAA;AAAA,UACC,KAAM,EAAA,iDAAA;AAAA,UACN;AAAA;AAAA,OACF;AAAA;AAIJ,IAAI,IAAA,CAAC,KAAO,EAAA,OAAA,CAAQ,MAAQ,EAAA;AAC1B,MAAO,OAAA,kBAAA;AAAA;AAGT,IAAI,IAAA,UAAA,CAAW,QAAQ,CAAG,EAAA;AACxB,MAAA,OAAO,SAAS,KAAK,CAAA;AAAA;AAGvB,IAAA,2BACG,8BAAgC,EAAA,EAAA,GAAG,MAAM,OAAS,EAAA,KAAA,CAAM,SACtD,QACH,EAAA,CAAA;AAAA,GAGN,EAAA,CAAA;AAEJ;AAOa,MAAA,YAAA,GAAe,CAAC,KAC3B,qBAAA,GAAA;AAAA,EAAC,gBAAA;AAAA,EAAA;AAAA,IACC,UAAY,EAAA;AAAA,MACV,QAAU,EAAA,QAAA;AAAA,MACV,SAAW,EAAA;AAAA,KACb;AAAA,IAEA,QAAA,kBAAA,GAAA,CAAC,qBAAuB,EAAA,EAAA,GAAG,KAAO,EAAA;AAAA;AACpC;;;;"}
1
+ {"version":3,"file":"SearchResult.esm.js","sources":["../../../src/components/SearchResult/SearchResult.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 { ReactNode } from 'react';\nimport useAsync, { AsyncState } from 'react-use/esm/useAsync';\nimport { isFunction } from 'lodash';\n\nimport {\n Progress,\n EmptyState,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { useApi, AnalyticsContext } from '@backstage/core-plugin-api';\nimport { SearchQuery, SearchResultSet } from '@backstage/plugin-search-common';\n\nimport { searchApiRef } from '../../api';\nimport { useSearch } from '../../context';\nimport {\n SearchResultListItemExtensions,\n SearchResultListItemExtensionsProps,\n} from '../../extensions';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchResultContext}\n * @public\n */\nexport type SearchResultContextProps = {\n /**\n * A child function that receives an asynchronous result set and returns a react element.\n */\n children: (\n state: AsyncState<SearchResultSet>,\n query: Partial<SearchQuery>,\n ) => JSX.Element | null;\n};\n\n/**\n * Provides context-based results to a child function.\n * @param props - see {@link SearchResultContextProps}.\n * @example\n * ```\n * <SearchResultContext>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultContext>\n * ```\n * @public\n */\nexport const SearchResultContext = (props: SearchResultContextProps) => {\n const { children } = props;\n const context = useSearch();\n const { result: state, ...query } = context;\n return children(state, query);\n};\n\n/**\n * Props for {@link SearchResultApi}\n * @public\n */\nexport type SearchResultApiProps = SearchResultContextProps & {\n query: Partial<SearchQuery>;\n};\n\n/**\n * Request results through the search api and provide them to a child function.\n * @param props - see {@link SearchResultApiProps}.\n * @example\n * ```\n * <SearchResultApi>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultApi>\n * ```\n * @public\n */\nexport const SearchResultApi = (props: SearchResultApiProps) => {\n const { query, children } = props;\n const searchApi = useApi(searchApiRef);\n\n const state = useAsync(() => {\n const { term = '', types = [], filters = {}, ...rest } = query;\n return searchApi.query({ ...rest, term, types, filters });\n }, [query]);\n\n return children(state, query);\n};\n\n/**\n * Props for {@link SearchResultState}\n * @public\n */\nexport type SearchResultStateProps = SearchResultContextProps &\n Partial<SearchResultApiProps>;\n\n/**\n * Call a child render function passing a search state as an argument.\n * @remarks By default, results are taken from context, but when a \"query\" prop is set, results are requested from the search api.\n * @param props - see {@link SearchResultStateProps}.\n * @example\n * Consuming results from context:\n * ```\n * <SearchResultState>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultState>\n * ```\n * @example\n * Requesting results using the search api:\n * ```\n * <SearchResultState query={{ term: 'documentation' }}>\n * {({ loading, error, value }) => (\n * <List>\n * {value?.map(({ document }) => (\n * <DefaultSearchResultListItem\n * key={document.location}\n * result={document}\n * />\n * ))}\n * </List>\n * )}\n * </SearchResultState>\n * ```\n * @public\n */\nexport const SearchResultState = (props: SearchResultStateProps) => {\n const { query, children } = props;\n\n return query ? (\n <SearchResultApi query={query}>{children}</SearchResultApi>\n ) : (\n <SearchResultContext>{children}</SearchResultContext>\n );\n};\n\n/**\n * Props for {@link SearchResult}\n * @public\n */\nexport type SearchResultProps = Pick<SearchResultStateProps, 'query'> &\n Omit<SearchResultListItemExtensionsProps, 'results' | 'children'> & {\n children?: ReactNode | ((resultSet: SearchResultSet) => JSX.Element);\n noResultsComponent?: JSX.Element;\n };\n\n/**\n * Renders results from a parent search context or api.\n * @remarks default components for loading, error and empty variants are returned.\n * @param props - see {@link SearchResultProps}.\n * @public\n */\nexport const SearchResultComponent = (props: SearchResultProps) => {\n const { t } = useTranslationRef(searchReactTranslationRef);\n const {\n query,\n children,\n noResultsComponent = (\n <EmptyState missing=\"data\" title={t('noResultsDescription')} />\n ),\n ...rest\n } = props;\n\n return (\n <SearchResultState query={query}>\n {({ loading, error, value }) => {\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <ResponseErrorPanel\n title=\"Error encountered while fetching search results\"\n error={error}\n />\n );\n }\n\n if (!value?.results.length) {\n return noResultsComponent;\n }\n\n if (isFunction(children)) {\n return children(value);\n }\n\n return (\n <SearchResultListItemExtensions {...rest} results={value.results}>\n {children}\n </SearchResultListItemExtensions>\n );\n }}\n </SearchResultState>\n );\n};\n\n/**\n * A component returning the search result from a parent search context or api.\n * @param props - see {@link SearchResultProps}.\n * @public\n */\nexport const SearchResult = (props: SearchResultProps) => (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'SearchResult',\n }}\n >\n <SearchResultComponent {...props} />\n </AnalyticsContext>\n);\n"],"names":[],"mappings":";;;;;;;;;;;AAuEO,MAAM,mBAAA,GAAsB,CAAC,KAAA,KAAoC;AACtE,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AACrB,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAO,GAAG,OAAM,GAAI,OAAA;AACpC,EAAA,OAAO,QAAA,CAAS,OAAO,KAAK,CAAA;AAC9B;AA8BO,MAAM,eAAA,GAAkB,CAAC,KAAA,KAAgC;AAC9D,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,KAAA;AAC5B,EAAA,MAAM,SAAA,GAAY,OAAO,YAAY,CAAA;AAErC,EAAA,MAAM,KAAA,GAAQ,SAAS,MAAM;AAC3B,IAAA,MAAM,EAAE,IAAA,GAAO,EAAA,EAAI,KAAA,GAAQ,EAAC,EAAG,OAAA,GAAU,EAAC,EAAG,GAAG,IAAA,EAAK,GAAI,KAAA;AACzD,IAAA,OAAO,SAAA,CAAU,MAAM,EAAE,GAAG,MAAM,IAAA,EAAM,KAAA,EAAO,SAAS,CAAA;AAAA,EAC1D,CAAA,EAAG,CAAC,KAAK,CAAC,CAAA;AAEV,EAAA,OAAO,QAAA,CAAS,OAAO,KAAK,CAAA;AAC9B;AA+CO,MAAM,iBAAA,GAAoB,CAAC,KAAA,KAAkC;AAClE,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,KAAA;AAE5B,EAAA,OAAO,KAAA,uBACJ,eAAA,EAAA,EAAgB,KAAA,EAAe,UAAS,CAAA,mBAEzC,GAAA,CAAC,uBAAqB,QAAA,EAAS,CAAA;AAEnC;AAkBO,MAAM,qBAAA,GAAwB,CAAC,KAAA,KAA6B;AACjE,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,yBAAyB,CAAA;AACzD,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,QAAA;AAAA,IACA,kBAAA,uBACG,UAAA,EAAA,EAAW,OAAA,EAAQ,QAAO,KAAA,EAAO,CAAA,CAAE,sBAAsB,CAAA,EAAG,CAAA;AAAA,IAE/D,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,uBACE,GAAA,CAAC,qBAAkB,KAAA,EAChB,QAAA,EAAA,CAAC,EAAE,OAAA,EAAS,KAAA,EAAO,OAAM,KAAM;AAC9B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,IACnB;AAEA,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,uBACE,GAAA;AAAA,QAAC,kBAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAM,iDAAA;AAAA,UACN;AAAA;AAAA,OACF;AAAA,IAEJ;AAEA,IAAA,IAAI,CAAC,KAAA,EAAO,OAAA,CAAQ,MAAA,EAAQ;AAC1B,MAAA,OAAO,kBAAA;AAAA,IACT;AAEA,IAAA,IAAI,UAAA,CAAW,QAAQ,CAAA,EAAG;AACxB,MAAA,OAAO,SAAS,KAAK,CAAA;AAAA,IACvB;AAEA,IAAA,2BACG,8BAAA,EAAA,EAAgC,GAAG,MAAM,OAAA,EAAS,KAAA,CAAM,SACtD,QAAA,EACH,CAAA;AAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;AAOO,MAAM,YAAA,GAAe,CAAC,KAAA,qBAC3B,GAAA;AAAA,EAAC,gBAAA;AAAA,EAAA;AAAA,IACC,UAAA,EAAY;AAAA,MACV,QAAA,EAAU,QAAA;AAAA,MACV,SAAA,EAAW;AAAA,KACb;AAAA,IAEA,QAAA,kBAAA,GAAA,CAAC,qBAAA,EAAA,EAAuB,GAAG,KAAA,EAAO;AAAA;AACpC;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { useCallback, useState } from 'react';
2
+ import { useState, useCallback } from 'react';
3
3
  import qs from 'qs';
4
4
  import List from '@material-ui/core/List';
5
5
  import ListSubheader from '@material-ui/core/ListSubheader';
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResultGroup.esm.js","sources":["../../../src/components/SearchResultGroup/SearchResultGroup.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 {\n MouseEvent,\n ChangeEvent,\n PropsWithChildren,\n ReactNode,\n useCallback,\n useState,\n} from 'react';\nimport qs from 'qs';\n\nimport List, { ListProps } from '@material-ui/core/List';\nimport ListSubheader from '@material-ui/core/ListSubheader';\nimport Menu from '@material-ui/core/Menu';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport InputBase from '@material-ui/core/InputBase';\nimport Select from '@material-ui/core/Select';\nimport Chip from '@material-ui/core/Chip';\nimport Typography, { TypographyProps } from '@material-ui/core/Typography';\nimport { makeStyles, Theme } from '@material-ui/core/styles';\nimport AddIcon from '@material-ui/icons/Add';\nimport ArrowRightIcon from '@material-ui/icons/ArrowForwardIos';\n\nimport { JsonValue } from '@backstage/types';\nimport {\n Link,\n LinkProps,\n Progress,\n EmptyState,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { AnalyticsContext } from '@backstage/core-plugin-api';\nimport { SearchResult } from '@backstage/plugin-search-common';\n\nimport { useSearchResultListItemExtensions } from '../../extensions';\n\nimport { DefaultResultListItem } from '../DefaultResultListItem';\nimport { SearchResultState, SearchResultStateProps } from '../SearchResult';\nimport { searchReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n listSubheader: {\n display: 'flex',\n alignItems: 'center',\n },\n listSubheaderName: {\n marginLeft: theme.spacing(1),\n textTransform: 'uppercase',\n },\n listSubheaderChip: {\n color: theme.palette.text.secondary,\n margin: theme.spacing(0, 0, 0, 1.5),\n },\n listSubheaderFilter: {\n display: 'flex',\n color: theme.palette.text.secondary,\n margin: theme.spacing(0, 0, 0, 1.5),\n },\n listSubheaderLink: {\n marginLeft: 'auto',\n display: 'flex',\n alignItems: 'center',\n },\n listSubheaderLinkIcon: {\n fontSize: 'inherit',\n marginLeft: theme.spacing(0.5),\n },\n}));\n\n/**\n * Props for {@link SearchResultGroupFilterFieldLayout}\n * @public\n */\nexport type SearchResultGroupFilterFieldLayoutProps = PropsWithChildren<{\n label: string;\n value?: JsonValue;\n onDelete: () => void;\n}>;\n\n/**\n * Default layout for a search group filter field.\n * @param props - See {@link SearchResultGroupFilterFieldLayoutProps}.\n * @public\n */\nexport const SearchResultGroupFilterFieldLayout = (\n props: SearchResultGroupFilterFieldLayoutProps,\n) => {\n const classes = useStyles();\n const { label, children, ...rest } = props;\n\n return (\n <Chip\n {...rest}\n className={classes.listSubheaderFilter}\n variant=\"outlined\"\n label={\n <>\n {label}: {children}\n </>\n }\n />\n );\n};\n\nconst NullIcon = () => null;\n\n/**\n * Common props for a result group filter field.\n * @public\n */\nexport type SearchResultGroupFilterFieldPropsWith<T> = T &\n SearchResultGroupFilterFieldLayoutProps & {\n onChange: (value: JsonValue) => void;\n };\n\nconst useSearchResultGroupTextFilterStyles = makeStyles((theme: Theme) => ({\n root: {\n fontSize: 'inherit',\n '&:focus': {\n outline: 'none',\n background: theme.palette.common.white,\n },\n '&:not(:focus)': {\n cursor: 'pointer',\n color: theme.palette.primary.main,\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n },\n}));\n\n/**\n * Props for {@link SearchResultGroupTextFilterField}.\n * @public\n */\nexport type SearchResultGroupTextFilterFieldProps =\n SearchResultGroupFilterFieldPropsWith<{}>;\n\n/**\n * A text field that can be used as filter on search result groups.\n * @param props - See {@link SearchResultGroupTextFilterFieldProps}.\n * @example\n * ```\n * <SearchResultGroupTextFilterField\n * id=\"lifecycle\"\n * label=\"Lifecycle\"\n * value={value}\n * onChange={handleChangeFilter}\n * onDelete={handleDeleteFilter}\n * />\n * ```\n * @public\n */\nexport const SearchResultGroupTextFilterField = (\n props: SearchResultGroupTextFilterFieldProps,\n) => {\n const classes = useSearchResultGroupTextFilterStyles();\n const { label, value = 'None', onChange, onDelete } = props;\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.value);\n },\n [onChange],\n );\n\n return (\n <SearchResultGroupFilterFieldLayout label={label} onDelete={onDelete}>\n <Typography\n role=\"textbox\"\n component=\"span\"\n className={classes.root}\n onChange={handleChange}\n contentEditable\n suppressContentEditableWarning\n >\n {value?.toString()}\n </Typography>\n </SearchResultGroupFilterFieldLayout>\n );\n};\n\nconst useSearchResultGroupSelectFilterStyles = makeStyles((theme: Theme) => ({\n root: {\n fontSize: 'inherit',\n '&:not(:focus)': {\n cursor: 'pointer',\n color: theme.palette.primary.main,\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n '&:focus': {\n outline: 'none',\n },\n '&>div:first-child': {\n padding: 0,\n },\n },\n}));\n\n/**\n * Props for {@link SearchResultGroupTextFilterField}.\n * @public\n */\nexport type SearchResultGroupSelectFilterFieldProps =\n SearchResultGroupFilterFieldPropsWith<{\n children: ReactNode;\n }>;\n\n/**\n * A select field that can be used as filter on search result groups.\n * @param props - See {@link SearchResultGroupSelectFilterFieldProps}.\n * @example\n * ```\n * <SearchResultGroupSelectFilterField\n * id=\"lifecycle\"\n * label=\"Lifecycle\"\n * value={filters.lifecycle}\n * onChange={handleChangeFilter}\n * onDelete={handleDeleteFilter}\n * >\n * <MenuItem value=\"experimental\">Experimental</MenuItem>\n * <MenuItem value=\"production\">Production</MenuItem>\n * </SearchResultGroupSelectFilterField>\n * ```\n * @public\n */\nexport const SearchResultGroupSelectFilterField = (\n props: SearchResultGroupSelectFilterFieldProps,\n) => {\n const classes = useSearchResultGroupSelectFilterStyles();\n const { label, value = 'none', onChange, onDelete, children } = props;\n\n const handleChange = useCallback(\n (e: ChangeEvent<{ value: unknown }>) => {\n onChange(e.target.value as JsonValue);\n },\n [onChange],\n );\n\n return (\n <SearchResultGroupFilterFieldLayout label={label} onDelete={onDelete}>\n <Select\n className={classes.root}\n value={value}\n onChange={handleChange}\n input={<InputBase />}\n IconComponent={NullIcon}\n >\n <MenuItem value=\"none\">None</MenuItem>\n {children}\n </Select>\n </SearchResultGroupFilterFieldLayout>\n );\n};\n\n/**\n * Props for {@link SearchResultGroupLayout}\n * @public\n */\nexport type SearchResultGroupLayoutProps<FilterOption> = ListProps & {\n /**\n * If defined, will render a default error panel.\n */\n error?: Error;\n /**\n * If defined, will render a default loading progress.\n */\n loading?: boolean;\n /**\n * Icon that representing a result group.\n */\n icon: JSX.Element;\n /**\n * The results group title content, it could be a text or an element.\n */\n title: ReactNode;\n /**\n * Props for the results group title.\n */\n titleProps?: Partial<TypographyProps>;\n /**\n * The results group link content, it could be a text or an element.\n */\n link?: ReactNode;\n /**\n * Props for the results group link, the \"to\" prop defaults to \"/search\".\n */\n linkProps?: Partial<LinkProps>;\n /**\n * A generic filter options that is rendered on the \"Add filter\" dropdown.\n */\n filterOptions?: FilterOption[];\n /**\n * Function to customize how filter options are rendered.\n * @remarks Defaults to a menu item where its value and label bounds to the option string.\n */\n renderFilterOption?: (\n value: FilterOption,\n index: number,\n array: FilterOption[],\n ) => JSX.Element | null;\n /**\n * A list of search filter keys, also known as filter field names.\n */\n filterFields?: string[];\n /**\n * Function to customize how filter chips are rendered.\n */\n renderFilterField?: (key: string) => JSX.Element | null;\n /**\n * Search results to be rendered as a group.\n */\n resultItems?: SearchResult[];\n /**\n * Function to customize how result items are rendered.\n */\n renderResultItem?: (\n value: SearchResult,\n index: number,\n array: SearchResult[],\n ) => JSX.Element | null;\n /**\n * Optional component to render when no results. Default to <EmptyState /> component.\n */\n noResultsComponent?: ReactNode;\n /**\n * Optional property to provide if component should not render the component when no results are found.\n */\n disableRenderingWithNoResults?: boolean;\n};\n\n/**\n * Default layout for rendering search results in a group.\n * @param props - See {@link SearchResultGroupLayoutProps}.\n * @public\n */\nexport function SearchResultGroupLayout<FilterOption>(\n props: SearchResultGroupLayoutProps<FilterOption>,\n) {\n const classes = useStyles();\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n const {\n error,\n loading,\n icon,\n title,\n titleProps = {},\n link = (\n <>\n {t('searchResultGroup.linkTitle')}\n <ArrowRightIcon className={classes.listSubheaderLinkIcon} />\n </>\n ),\n linkProps = {},\n filterOptions,\n renderFilterOption = filterOption => (\n <MenuItem key={String(filterOption)} value={String(filterOption)}>\n {String(filterOption)}\n </MenuItem>\n ),\n filterFields,\n renderFilterField,\n resultItems,\n renderResultItem = resultItem => (\n <DefaultResultListItem\n key={resultItem.document.location}\n result={resultItem.document}\n />\n ),\n disableRenderingWithNoResults,\n noResultsComponent = disableRenderingWithNoResults ? null : (\n <EmptyState missing=\"data\" title={t('noResultsDescription')} />\n ),\n ...rest\n } = props;\n\n const handleClick = useCallback((e: MouseEvent<HTMLButtonElement>) => {\n setAnchorEl(e.currentTarget);\n }, []);\n\n const handleClose = useCallback(() => {\n setAnchorEl(null);\n }, []);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <ResponseErrorPanel\n title=\"Error encountered while fetching search results\"\n error={error}\n />\n );\n }\n\n if (!resultItems?.length) {\n return <>{noResultsComponent}</>;\n }\n\n return (\n <List {...rest}>\n <ListSubheader className={classes.listSubheader}>\n {icon}\n <Typography\n className={classes.listSubheaderName}\n component=\"strong\"\n {...titleProps}\n >\n {title}\n </Typography>\n {filterOptions ? (\n <Chip\n className={classes.listSubheaderChip}\n component=\"button\"\n icon={<AddIcon />}\n variant=\"outlined\"\n label={t('searchResultGroup.addFilterButtonTitle')}\n aria-controls=\"filters-menu\"\n aria-haspopup=\"true\"\n onClick={handleClick}\n />\n ) : null}\n {filterOptions ? (\n <Menu\n id=\"filters-menu\"\n anchorEl={anchorEl}\n open={Boolean(anchorEl)}\n onClose={handleClose}\n onClick={handleClose}\n keepMounted\n >\n {filterOptions.map(renderFilterOption)}\n </Menu>\n ) : null}\n {filterFields?.map(\n filterField => renderFilterField?.(filterField) ?? null,\n )}\n <Link className={classes.listSubheaderLink} to=\"/search\" {...linkProps}>\n {link}\n </Link>\n </ListSubheader>\n {resultItems.map(renderResultItem)}\n </List>\n );\n}\n\n/**\n * Props for {@link SearchResultGroup}.\n * @public\n */\nexport type SearchResultGroupProps<FilterOption> = Pick<\n SearchResultStateProps,\n 'query'\n> &\n Omit<\n SearchResultGroupLayoutProps<FilterOption>,\n 'loading' | 'error' | 'resultItems' | 'filterFields'\n >;\n\n/**\n * Given a query, search for results and render them as a group.\n * @param props - See {@link SearchResultGroupProps}.\n * @public\n */\nexport function SearchResultGroup<FilterOption>(\n props: SearchResultGroupProps<FilterOption>,\n) {\n const { query, children, renderResultItem, linkProps = {}, ...rest } = props;\n\n const defaultRenderResultItem = useSearchResultListItemExtensions(children);\n\n return (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'SearchResultGroup',\n }}\n >\n <SearchResultState query={query}>\n {(\n { loading, error, value },\n { term, types, pageCursor, filters = {} },\n ) => {\n const to = `/search?${qs.stringify(\n { term, types, filters, pageCursor, query: term },\n { arrayFormat: 'brackets' },\n )}`;\n\n return (\n <SearchResultGroupLayout\n {...rest}\n error={error}\n loading={loading}\n linkProps={{ to, ...linkProps }}\n filterFields={Object.keys(filters)}\n resultItems={value?.results}\n renderResultItem={renderResultItem ?? defaultRenderResultItem}\n />\n );\n }}\n </SearchResultState>\n </AnalyticsContext>\n );\n}\n"],"names":["DefaultResultListItem"],"mappings":"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"}
1
+ {"version":3,"file":"SearchResultGroup.esm.js","sources":["../../../src/components/SearchResultGroup/SearchResultGroup.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 {\n MouseEvent,\n ChangeEvent,\n PropsWithChildren,\n ReactNode,\n useCallback,\n useState,\n} from 'react';\nimport qs from 'qs';\n\nimport List, { ListProps } from '@material-ui/core/List';\nimport ListSubheader from '@material-ui/core/ListSubheader';\nimport Menu from '@material-ui/core/Menu';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport InputBase from '@material-ui/core/InputBase';\nimport Select from '@material-ui/core/Select';\nimport Chip from '@material-ui/core/Chip';\nimport Typography, { TypographyProps } from '@material-ui/core/Typography';\nimport { makeStyles, Theme } from '@material-ui/core/styles';\nimport AddIcon from '@material-ui/icons/Add';\nimport ArrowRightIcon from '@material-ui/icons/ArrowForwardIos';\n\nimport { JsonValue } from '@backstage/types';\nimport {\n Link,\n LinkProps,\n Progress,\n EmptyState,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { AnalyticsContext } from '@backstage/core-plugin-api';\nimport { SearchResult } from '@backstage/plugin-search-common';\n\nimport { useSearchResultListItemExtensions } from '../../extensions';\n\nimport { DefaultResultListItem } from '../DefaultResultListItem';\nimport { SearchResultState, SearchResultStateProps } from '../SearchResult';\nimport { searchReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\n\nconst useStyles = makeStyles((theme: Theme) => ({\n listSubheader: {\n display: 'flex',\n alignItems: 'center',\n },\n listSubheaderName: {\n marginLeft: theme.spacing(1),\n textTransform: 'uppercase',\n },\n listSubheaderChip: {\n color: theme.palette.text.secondary,\n margin: theme.spacing(0, 0, 0, 1.5),\n },\n listSubheaderFilter: {\n display: 'flex',\n color: theme.palette.text.secondary,\n margin: theme.spacing(0, 0, 0, 1.5),\n },\n listSubheaderLink: {\n marginLeft: 'auto',\n display: 'flex',\n alignItems: 'center',\n },\n listSubheaderLinkIcon: {\n fontSize: 'inherit',\n marginLeft: theme.spacing(0.5),\n },\n}));\n\n/**\n * Props for {@link SearchResultGroupFilterFieldLayout}\n * @public\n */\nexport type SearchResultGroupFilterFieldLayoutProps = PropsWithChildren<{\n label: string;\n value?: JsonValue;\n onDelete: () => void;\n}>;\n\n/**\n * Default layout for a search group filter field.\n * @param props - See {@link SearchResultGroupFilterFieldLayoutProps}.\n * @public\n */\nexport const SearchResultGroupFilterFieldLayout = (\n props: SearchResultGroupFilterFieldLayoutProps,\n) => {\n const classes = useStyles();\n const { label, children, ...rest } = props;\n\n return (\n <Chip\n {...rest}\n className={classes.listSubheaderFilter}\n variant=\"outlined\"\n label={\n <>\n {label}: {children}\n </>\n }\n />\n );\n};\n\nconst NullIcon = () => null;\n\n/**\n * Common props for a result group filter field.\n * @public\n */\nexport type SearchResultGroupFilterFieldPropsWith<T> = T &\n SearchResultGroupFilterFieldLayoutProps & {\n onChange: (value: JsonValue) => void;\n };\n\nconst useSearchResultGroupTextFilterStyles = makeStyles((theme: Theme) => ({\n root: {\n fontSize: 'inherit',\n '&:focus': {\n outline: 'none',\n background: theme.palette.common.white,\n },\n '&:not(:focus)': {\n cursor: 'pointer',\n color: theme.palette.primary.main,\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n },\n}));\n\n/**\n * Props for {@link SearchResultGroupTextFilterField}.\n * @public\n */\nexport type SearchResultGroupTextFilterFieldProps =\n SearchResultGroupFilterFieldPropsWith<{}>;\n\n/**\n * A text field that can be used as filter on search result groups.\n * @param props - See {@link SearchResultGroupTextFilterFieldProps}.\n * @example\n * ```\n * <SearchResultGroupTextFilterField\n * id=\"lifecycle\"\n * label=\"Lifecycle\"\n * value={value}\n * onChange={handleChangeFilter}\n * onDelete={handleDeleteFilter}\n * />\n * ```\n * @public\n */\nexport const SearchResultGroupTextFilterField = (\n props: SearchResultGroupTextFilterFieldProps,\n) => {\n const classes = useSearchResultGroupTextFilterStyles();\n const { label, value = 'None', onChange, onDelete } = props;\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n onChange(e.target.value);\n },\n [onChange],\n );\n\n return (\n <SearchResultGroupFilterFieldLayout label={label} onDelete={onDelete}>\n <Typography\n role=\"textbox\"\n component=\"span\"\n className={classes.root}\n onChange={handleChange}\n contentEditable\n suppressContentEditableWarning\n >\n {value?.toString()}\n </Typography>\n </SearchResultGroupFilterFieldLayout>\n );\n};\n\nconst useSearchResultGroupSelectFilterStyles = makeStyles((theme: Theme) => ({\n root: {\n fontSize: 'inherit',\n '&:not(:focus)': {\n cursor: 'pointer',\n color: theme.palette.primary.main,\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n '&:focus': {\n outline: 'none',\n },\n '&>div:first-child': {\n padding: 0,\n },\n },\n}));\n\n/**\n * Props for {@link SearchResultGroupTextFilterField}.\n * @public\n */\nexport type SearchResultGroupSelectFilterFieldProps =\n SearchResultGroupFilterFieldPropsWith<{\n children: ReactNode;\n }>;\n\n/**\n * A select field that can be used as filter on search result groups.\n * @param props - See {@link SearchResultGroupSelectFilterFieldProps}.\n * @example\n * ```\n * <SearchResultGroupSelectFilterField\n * id=\"lifecycle\"\n * label=\"Lifecycle\"\n * value={filters.lifecycle}\n * onChange={handleChangeFilter}\n * onDelete={handleDeleteFilter}\n * >\n * <MenuItem value=\"experimental\">Experimental</MenuItem>\n * <MenuItem value=\"production\">Production</MenuItem>\n * </SearchResultGroupSelectFilterField>\n * ```\n * @public\n */\nexport const SearchResultGroupSelectFilterField = (\n props: SearchResultGroupSelectFilterFieldProps,\n) => {\n const classes = useSearchResultGroupSelectFilterStyles();\n const { label, value = 'none', onChange, onDelete, children } = props;\n\n const handleChange = useCallback(\n (e: ChangeEvent<{ value: unknown }>) => {\n onChange(e.target.value as JsonValue);\n },\n [onChange],\n );\n\n return (\n <SearchResultGroupFilterFieldLayout label={label} onDelete={onDelete}>\n <Select\n className={classes.root}\n value={value}\n onChange={handleChange}\n input={<InputBase />}\n IconComponent={NullIcon}\n >\n <MenuItem value=\"none\">None</MenuItem>\n {children}\n </Select>\n </SearchResultGroupFilterFieldLayout>\n );\n};\n\n/**\n * Props for {@link SearchResultGroupLayout}\n * @public\n */\nexport type SearchResultGroupLayoutProps<FilterOption> = ListProps & {\n /**\n * If defined, will render a default error panel.\n */\n error?: Error;\n /**\n * If defined, will render a default loading progress.\n */\n loading?: boolean;\n /**\n * Icon that representing a result group.\n */\n icon: JSX.Element;\n /**\n * The results group title content, it could be a text or an element.\n */\n title: ReactNode;\n /**\n * Props for the results group title.\n */\n titleProps?: Partial<TypographyProps>;\n /**\n * The results group link content, it could be a text or an element.\n */\n link?: ReactNode;\n /**\n * Props for the results group link, the \"to\" prop defaults to \"/search\".\n */\n linkProps?: Partial<LinkProps>;\n /**\n * A generic filter options that is rendered on the \"Add filter\" dropdown.\n */\n filterOptions?: FilterOption[];\n /**\n * Function to customize how filter options are rendered.\n * @remarks Defaults to a menu item where its value and label bounds to the option string.\n */\n renderFilterOption?: (\n value: FilterOption,\n index: number,\n array: FilterOption[],\n ) => JSX.Element | null;\n /**\n * A list of search filter keys, also known as filter field names.\n */\n filterFields?: string[];\n /**\n * Function to customize how filter chips are rendered.\n */\n renderFilterField?: (key: string) => JSX.Element | null;\n /**\n * Search results to be rendered as a group.\n */\n resultItems?: SearchResult[];\n /**\n * Function to customize how result items are rendered.\n */\n renderResultItem?: (\n value: SearchResult,\n index: number,\n array: SearchResult[],\n ) => JSX.Element | null;\n /**\n * Optional component to render when no results. Default to <EmptyState /> component.\n */\n noResultsComponent?: ReactNode;\n /**\n * Optional property to provide if component should not render the component when no results are found.\n */\n disableRenderingWithNoResults?: boolean;\n};\n\n/**\n * Default layout for rendering search results in a group.\n * @param props - See {@link SearchResultGroupLayoutProps}.\n * @public\n */\nexport function SearchResultGroupLayout<FilterOption>(\n props: SearchResultGroupLayoutProps<FilterOption>,\n) {\n const classes = useStyles();\n const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n const {\n error,\n loading,\n icon,\n title,\n titleProps = {},\n link = (\n <>\n {t('searchResultGroup.linkTitle')}\n <ArrowRightIcon className={classes.listSubheaderLinkIcon} />\n </>\n ),\n linkProps = {},\n filterOptions,\n renderFilterOption = filterOption => (\n <MenuItem key={String(filterOption)} value={String(filterOption)}>\n {String(filterOption)}\n </MenuItem>\n ),\n filterFields,\n renderFilterField,\n resultItems,\n renderResultItem = resultItem => (\n <DefaultResultListItem\n key={resultItem.document.location}\n result={resultItem.document}\n />\n ),\n disableRenderingWithNoResults,\n noResultsComponent = disableRenderingWithNoResults ? null : (\n <EmptyState missing=\"data\" title={t('noResultsDescription')} />\n ),\n ...rest\n } = props;\n\n const handleClick = useCallback((e: MouseEvent<HTMLButtonElement>) => {\n setAnchorEl(e.currentTarget);\n }, []);\n\n const handleClose = useCallback(() => {\n setAnchorEl(null);\n }, []);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <ResponseErrorPanel\n title=\"Error encountered while fetching search results\"\n error={error}\n />\n );\n }\n\n if (!resultItems?.length) {\n return <>{noResultsComponent}</>;\n }\n\n return (\n <List {...rest}>\n <ListSubheader className={classes.listSubheader}>\n {icon}\n <Typography\n className={classes.listSubheaderName}\n component=\"strong\"\n {...titleProps}\n >\n {title}\n </Typography>\n {filterOptions ? (\n <Chip\n className={classes.listSubheaderChip}\n component=\"button\"\n icon={<AddIcon />}\n variant=\"outlined\"\n label={t('searchResultGroup.addFilterButtonTitle')}\n aria-controls=\"filters-menu\"\n aria-haspopup=\"true\"\n onClick={handleClick}\n />\n ) : null}\n {filterOptions ? (\n <Menu\n id=\"filters-menu\"\n anchorEl={anchorEl}\n open={Boolean(anchorEl)}\n onClose={handleClose}\n onClick={handleClose}\n keepMounted\n >\n {filterOptions.map(renderFilterOption)}\n </Menu>\n ) : null}\n {filterFields?.map(\n filterField => renderFilterField?.(filterField) ?? null,\n )}\n <Link className={classes.listSubheaderLink} to=\"/search\" {...linkProps}>\n {link}\n </Link>\n </ListSubheader>\n {resultItems.map(renderResultItem)}\n </List>\n );\n}\n\n/**\n * Props for {@link SearchResultGroup}.\n * @public\n */\nexport type SearchResultGroupProps<FilterOption> = Pick<\n SearchResultStateProps,\n 'query'\n> &\n Omit<\n SearchResultGroupLayoutProps<FilterOption>,\n 'loading' | 'error' | 'resultItems' | 'filterFields'\n >;\n\n/**\n * Given a query, search for results and render them as a group.\n * @param props - See {@link SearchResultGroupProps}.\n * @public\n */\nexport function SearchResultGroup<FilterOption>(\n props: SearchResultGroupProps<FilterOption>,\n) {\n const { query, children, renderResultItem, linkProps = {}, ...rest } = props;\n\n const defaultRenderResultItem = useSearchResultListItemExtensions(children);\n\n return (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'SearchResultGroup',\n }}\n >\n <SearchResultState query={query}>\n {(\n { loading, error, value },\n { term, types, pageCursor, filters = {} },\n ) => {\n const to = `/search?${qs.stringify(\n { term, types, filters, pageCursor, query: term },\n { arrayFormat: 'brackets' },\n )}`;\n\n return (\n <SearchResultGroupLayout\n {...rest}\n error={error}\n loading={loading}\n linkProps={{ to, ...linkProps }}\n filterFields={Object.keys(filters)}\n resultItems={value?.results}\n renderResultItem={renderResultItem ?? defaultRenderResultItem}\n />\n );\n }}\n </SearchResultState>\n </AnalyticsContext>\n );\n}\n"],"names":["DefaultResultListItem"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResultList.esm.js","sources":["../../../src/components/SearchResultList/SearchResultList.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 { ReactNode } from 'react';\n\nimport List, { ListProps } from '@material-ui/core/List';\n\nimport {\n Progress,\n EmptyState,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { AnalyticsContext } from '@backstage/core-plugin-api';\nimport { SearchResult } from '@backstage/plugin-search-common';\n\nimport { useSearchResultListItemExtensions } from '../../extensions';\n\nimport { DefaultResultListItem } from '../DefaultResultListItem';\nimport { SearchResultState, SearchResultStateProps } from '../SearchResult';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchResultListLayout}\n * @public\n */\nexport type SearchResultListLayoutProps = ListProps & {\n /**\n * If defined, will render a default error panel.\n */\n error?: Error;\n /**\n * If defined, will render a default loading progress.\n */\n loading?: boolean;\n /**\n * Search results to be rendered as a list.\n */\n resultItems?: SearchResult[];\n /**\n * Function to customize how result items are rendered.\n */\n renderResultItem?: (\n value: SearchResult,\n index: number,\n array: SearchResult[],\n ) => JSX.Element | null;\n /**\n * Optional component to render when no results. Default to <EmptyState /> component.\n */\n noResultsComponent?: ReactNode;\n /**\n * Optional property to provide if component should not render the component when no results are found.\n */\n disableRenderingWithNoResults?: boolean;\n};\n\n/**\n * Default layout for rendering search results in a list.\n * @param props - See {@link SearchResultListLayoutProps}.\n * @public\n */\nexport const SearchResultListLayout = (props: SearchResultListLayoutProps) => {\n const { t } = useTranslationRef(searchReactTranslationRef);\n const {\n error,\n loading,\n resultItems,\n renderResultItem = resultItem => (\n <DefaultResultListItem\n key={resultItem.document.location}\n result={resultItem.document}\n />\n ),\n disableRenderingWithNoResults,\n noResultsComponent = disableRenderingWithNoResults ? null : (\n <EmptyState missing=\"data\" title={t('noResultsDescription')} />\n ),\n ...rest\n } = props;\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <ResponseErrorPanel\n title=\"Error encountered while fetching search results\"\n error={error}\n />\n );\n }\n\n if (!resultItems?.length) {\n return <>{noResultsComponent}</>;\n }\n\n return <List {...rest}>{resultItems.map(renderResultItem)}</List>;\n};\n\n/**\n * Props for {@link SearchResultList}.\n * @public\n */\nexport type SearchResultListProps = Pick<SearchResultStateProps, 'query'> &\n Omit<SearchResultListLayoutProps, 'loading' | 'error' | 'resultItems'>;\n\n/**\n * Given a query, search for results and render them as a list.\n * @param props - See {@link SearchResultListProps}.\n * @public\n */\nexport const SearchResultList = (props: SearchResultListProps) => {\n const { query, renderResultItem, children, ...rest } = props;\n\n const defaultRenderResultItem = useSearchResultListItemExtensions(children);\n\n return (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'SearchResultList',\n }}\n >\n <SearchResultState query={query}>\n {({ loading, error, value }) => (\n <SearchResultListLayout\n {...rest}\n error={error}\n loading={loading}\n resultItems={value?.results}\n renderResultItem={renderResultItem ?? defaultRenderResultItem}\n />\n )}\n </SearchResultState>\n </AnalyticsContext>\n );\n};\n"],"names":["DefaultResultListItem"],"mappings":";;;;;;;;;;AA2Ea,MAAA,sBAAA,GAAyB,CAAC,KAAuC,KAAA;AAC5E,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,yBAAyB,CAAA;AACzD,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA,mBAAmB,CACjB,UAAA,qBAAA,GAAA;AAAA,MAACA,gCAAA;AAAA,MAAA;AAAA,QAEC,QAAQ,UAAW,CAAA;AAAA,OAAA;AAAA,MADd,WAAW,QAAS,CAAA;AAAA,KAE3B;AAAA,IAEF,6BAAA;AAAA,IACA,kBAAA,GAAqB,6BAAgC,GAAA,IAAA,mBAClD,GAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,MAAO,EAAA,KAAA,EAAO,CAAE,CAAA,sBAAsB,CAAG,EAAA,CAAA;AAAA,IAE/D,GAAG;AAAA,GACD,GAAA,KAAA;AAEJ,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2BAAQ,QAAS,EAAA,EAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,KAAO,EAAA;AACT,IACE,uBAAA,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACC,KAAM,EAAA,iDAAA;AAAA,QACN;AAAA;AAAA,KACF;AAAA;AAIJ,EAAI,IAAA,CAAC,aAAa,MAAQ,EAAA;AACxB,IAAA,uCAAU,QAAmB,EAAA,kBAAA,EAAA,CAAA;AAAA;AAG/B,EAAA,2BAAQ,IAAM,EAAA,EAAA,GAAG,MAAO,QAAY,EAAA,WAAA,CAAA,GAAA,CAAI,gBAAgB,CAAE,EAAA,CAAA;AAC5D;AAca,MAAA,gBAAA,GAAmB,CAAC,KAAiC,KAAA;AAChE,EAAA,MAAM,EAAE,KAAO,EAAA,gBAAA,EAAkB,QAAU,EAAA,GAAG,MAAS,GAAA,KAAA;AAEvD,EAAM,MAAA,uBAAA,GAA0B,kCAAkC,QAAQ,CAAA;AAE1E,EACE,uBAAA,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,UAAY,EAAA;AAAA,QACV,QAAU,EAAA,QAAA;AAAA,QACV,SAAW,EAAA;AAAA,OACb;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,qBAAkB,KAChB,EAAA,QAAA,EAAA,CAAC,EAAE,OAAS,EAAA,KAAA,EAAO,OAClB,qBAAA,GAAA;AAAA,QAAC,sBAAA;AAAA,QAAA;AAAA,UACE,GAAG,IAAA;AAAA,UACJ,KAAA;AAAA,UACA,OAAA;AAAA,UACA,aAAa,KAAO,EAAA,OAAA;AAAA,UACpB,kBAAkB,gBAAoB,IAAA;AAAA;AAAA,OAG5C,EAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
1
+ {"version":3,"file":"SearchResultList.esm.js","sources":["../../../src/components/SearchResultList/SearchResultList.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 { ReactNode } from 'react';\n\nimport List, { ListProps } from '@material-ui/core/List';\n\nimport {\n Progress,\n EmptyState,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { AnalyticsContext } from '@backstage/core-plugin-api';\nimport { SearchResult } from '@backstage/plugin-search-common';\n\nimport { useSearchResultListItemExtensions } from '../../extensions';\n\nimport { DefaultResultListItem } from '../DefaultResultListItem';\nimport { SearchResultState, SearchResultStateProps } from '../SearchResult';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchResultListLayout}\n * @public\n */\nexport type SearchResultListLayoutProps = ListProps & {\n /**\n * If defined, will render a default error panel.\n */\n error?: Error;\n /**\n * If defined, will render a default loading progress.\n */\n loading?: boolean;\n /**\n * Search results to be rendered as a list.\n */\n resultItems?: SearchResult[];\n /**\n * Function to customize how result items are rendered.\n */\n renderResultItem?: (\n value: SearchResult,\n index: number,\n array: SearchResult[],\n ) => JSX.Element | null;\n /**\n * Optional component to render when no results. Default to <EmptyState /> component.\n */\n noResultsComponent?: ReactNode;\n /**\n * Optional property to provide if component should not render the component when no results are found.\n */\n disableRenderingWithNoResults?: boolean;\n};\n\n/**\n * Default layout for rendering search results in a list.\n * @param props - See {@link SearchResultListLayoutProps}.\n * @public\n */\nexport const SearchResultListLayout = (props: SearchResultListLayoutProps) => {\n const { t } = useTranslationRef(searchReactTranslationRef);\n const {\n error,\n loading,\n resultItems,\n renderResultItem = resultItem => (\n <DefaultResultListItem\n key={resultItem.document.location}\n result={resultItem.document}\n />\n ),\n disableRenderingWithNoResults,\n noResultsComponent = disableRenderingWithNoResults ? null : (\n <EmptyState missing=\"data\" title={t('noResultsDescription')} />\n ),\n ...rest\n } = props;\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <ResponseErrorPanel\n title=\"Error encountered while fetching search results\"\n error={error}\n />\n );\n }\n\n if (!resultItems?.length) {\n return <>{noResultsComponent}</>;\n }\n\n return <List {...rest}>{resultItems.map(renderResultItem)}</List>;\n};\n\n/**\n * Props for {@link SearchResultList}.\n * @public\n */\nexport type SearchResultListProps = Pick<SearchResultStateProps, 'query'> &\n Omit<SearchResultListLayoutProps, 'loading' | 'error' | 'resultItems'>;\n\n/**\n * Given a query, search for results and render them as a list.\n * @param props - See {@link SearchResultListProps}.\n * @public\n */\nexport const SearchResultList = (props: SearchResultListProps) => {\n const { query, renderResultItem, children, ...rest } = props;\n\n const defaultRenderResultItem = useSearchResultListItemExtensions(children);\n\n return (\n <AnalyticsContext\n attributes={{\n pluginId: 'search',\n extension: 'SearchResultList',\n }}\n >\n <SearchResultState query={query}>\n {({ loading, error, value }) => (\n <SearchResultListLayout\n {...rest}\n error={error}\n loading={loading}\n resultItems={value?.results}\n renderResultItem={renderResultItem ?? defaultRenderResultItem}\n />\n )}\n </SearchResultState>\n </AnalyticsContext>\n );\n};\n"],"names":["DefaultResultListItem"],"mappings":";;;;;;;;;;AA2EO,MAAM,sBAAA,GAAyB,CAAC,KAAA,KAAuC;AAC5E,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,yBAAyB,CAAA;AACzD,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA,mBAAmB,CAAA,UAAA,qBACjB,GAAA;AAAA,MAACA,gCAAA;AAAA,MAAA;AAAA,QAEC,QAAQ,UAAA,CAAW;AAAA,OAAA;AAAA,MADd,WAAW,QAAA,CAAS;AAAA,KAE3B;AAAA,IAEF,6BAAA;AAAA,IACA,kBAAA,GAAqB,6BAAA,GAAgC,IAAA,mBACnD,GAAA,CAAC,UAAA,EAAA,EAAW,SAAQ,MAAA,EAAO,KAAA,EAAO,CAAA,CAAE,sBAAsB,CAAA,EAAG,CAAA;AAAA,IAE/D,GAAG;AAAA,GACL,GAAI,KAAA;AAEJ,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,2BAAQ,QAAA,EAAA,EAAS,CAAA;AAAA,EACnB;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,uBACE,GAAA;AAAA,MAAC,kBAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAM,iDAAA;AAAA,QACN;AAAA;AAAA,KACF;AAAA,EAEJ;AAEA,EAAA,IAAI,CAAC,aAAa,MAAA,EAAQ;AACxB,IAAA,uCAAU,QAAA,EAAA,kBAAA,EAAmB,CAAA;AAAA,EAC/B;AAEA,EAAA,2BAAQ,IAAA,EAAA,EAAM,GAAG,MAAO,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,gBAAgB,CAAA,EAAE,CAAA;AAC5D;AAcO,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAAiC;AAChE,EAAA,MAAM,EAAE,KAAA,EAAO,gBAAA,EAAkB,QAAA,EAAU,GAAG,MAAK,GAAI,KAAA;AAEvD,EAAA,MAAM,uBAAA,GAA0B,kCAAkC,QAAQ,CAAA;AAE1E,EAAA,uBACE,GAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,UAAA,EAAY;AAAA,QACV,QAAA,EAAU,QAAA;AAAA,QACV,SAAA,EAAW;AAAA,OACb;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,qBAAkB,KAAA,EAChB,QAAA,EAAA,CAAC,EAAE,OAAA,EAAS,KAAA,EAAO,OAAM,qBACxB,GAAA;AAAA,QAAC,sBAAA;AAAA,QAAA;AAAA,UACE,GAAG,IAAA;AAAA,UACJ,KAAA;AAAA,UACA,OAAA;AAAA,UACA,aAAa,KAAA,EAAO,OAAA;AAAA,UACpB,kBAAkB,gBAAA,IAAoB;AAAA;AAAA,OACxC,EAEJ;AAAA;AAAA,GACF;AAEJ;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResultPager.esm.js","sources":["../../../src/components/SearchResultPager/SearchResultPager.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 Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';\nimport ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';\n\nimport { useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n justifyContent: 'space-between',\n gap: theme.spacing(2),\n margin: theme.spacing(2, 0),\n },\n}));\n\n/**\n * @public\n */\nexport const SearchResultPager = () => {\n const { fetchNextPage, fetchPreviousPage } = useSearch();\n const classes = useStyles();\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n if (!fetchNextPage && !fetchPreviousPage) {\n return <></>;\n }\n\n return (\n <nav aria-label=\"pagination navigation\" className={classes.root}>\n <Button\n aria-label=\"previous page\"\n disabled={!fetchPreviousPage}\n onClick={fetchPreviousPage}\n startIcon={<ArrowBackIosIcon />}\n >\n {t('searchResultPager.previous')}\n </Button>\n\n <Button\n aria-label=\"next page\"\n disabled={!fetchNextPage}\n onClick={fetchNextPage}\n endIcon={<ArrowForwardIosIcon />}\n >\n {t('searchResultPager.next')}\n </Button>\n </nav>\n );\n};\n"],"names":["ArrowForwardIosIcon"],"mappings":";;;;;;;;;AAyBA,MAAM,SAAA,GAAY,WAAW,CAAU,KAAA,MAAA;AAAA,EACrC,IAAM,EAAA;AAAA,IACJ,OAAS,EAAA,MAAA;AAAA,IACT,cAAgB,EAAA,eAAA;AAAA,IAChB,GAAA,EAAK,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,MAAQ,EAAA,KAAA,CAAM,OAAQ,CAAA,CAAA,EAAG,CAAC;AAAA;AAE9B,CAAE,CAAA,CAAA;AAKK,MAAM,oBAAoB,MAAM;AACrC,EAAA,MAAM,EAAE,aAAA,EAAe,iBAAkB,EAAA,GAAI,SAAU,EAAA;AACvD,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,yBAAyB,CAAA;AAEzD,EAAI,IAAA,CAAC,aAAiB,IAAA,CAAC,iBAAmB,EAAA;AACxC,IAAA,uBAAS,GAAA,CAAA,QAAA,EAAA,EAAA,CAAA;AAAA;AAGX,EAAA,4BACG,KAAI,EAAA,EAAA,YAAA,EAAW,uBAAwB,EAAA,SAAA,EAAW,QAAQ,IACzD,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,YAAW,EAAA,eAAA;AAAA,QACX,UAAU,CAAC,iBAAA;AAAA,QACX,OAAS,EAAA,iBAAA;AAAA,QACT,SAAA,sBAAY,gBAAiB,EAAA,EAAA,CAAA;AAAA,QAE5B,YAAE,4BAA4B;AAAA;AAAA,KACjC;AAAA,oBAEA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,YAAW,EAAA,WAAA;AAAA,QACX,UAAU,CAAC,aAAA;AAAA,QACX,OAAS,EAAA,aAAA;AAAA,QACT,OAAA,sBAAUA,cAAoB,EAAA,EAAA,CAAA;AAAA,QAE7B,YAAE,wBAAwB;AAAA;AAAA;AAC7B,GACF,EAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"SearchResultPager.esm.js","sources":["../../../src/components/SearchResultPager/SearchResultPager.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 Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';\nimport ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';\n\nimport { useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n justifyContent: 'space-between',\n gap: theme.spacing(2),\n margin: theme.spacing(2, 0),\n },\n}));\n\n/**\n * @public\n */\nexport const SearchResultPager = () => {\n const { fetchNextPage, fetchPreviousPage } = useSearch();\n const classes = useStyles();\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n if (!fetchNextPage && !fetchPreviousPage) {\n return <></>;\n }\n\n return (\n <nav aria-label=\"pagination navigation\" className={classes.root}>\n <Button\n aria-label=\"previous page\"\n disabled={!fetchPreviousPage}\n onClick={fetchPreviousPage}\n startIcon={<ArrowBackIosIcon />}\n >\n {t('searchResultPager.previous')}\n </Button>\n\n <Button\n aria-label=\"next page\"\n disabled={!fetchNextPage}\n onClick={fetchNextPage}\n endIcon={<ArrowForwardIosIcon />}\n >\n {t('searchResultPager.next')}\n </Button>\n </nav>\n );\n};\n"],"names":["ArrowForwardIosIcon"],"mappings":";;;;;;;;;AAyBA,MAAM,SAAA,GAAY,WAAW,CAAA,KAAA,MAAU;AAAA,EACrC,IAAA,EAAM;AAAA,IACJ,OAAA,EAAS,MAAA;AAAA,IACT,cAAA,EAAgB,eAAA;AAAA,IAChB,GAAA,EAAK,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA;AAAA,IACpB,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,CAAA,EAAG,CAAC;AAAA;AAE9B,CAAA,CAAE,CAAA;AAKK,MAAM,oBAAoB,MAAM;AACrC,EAAA,MAAM,EAAE,aAAA,EAAe,iBAAA,EAAkB,GAAI,SAAA,EAAU;AACvD,EAAA,MAAM,UAAU,SAAA,EAAU;AAC1B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,yBAAyB,CAAA;AAEzD,EAAA,IAAI,CAAC,aAAA,IAAiB,CAAC,iBAAA,EAAmB;AACxC,IAAA,uBAAO,GAAA,CAAA,QAAA,EAAA,EAAE,CAAA;AAAA,EACX;AAEA,EAAA,4BACG,KAAA,EAAA,EAAI,YAAA,EAAW,uBAAA,EAAwB,SAAA,EAAW,QAAQ,IAAA,EACzD,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,YAAA,EAAW,eAAA;AAAA,QACX,UAAU,CAAC,iBAAA;AAAA,QACX,OAAA,EAAS,iBAAA;AAAA,QACT,SAAA,sBAAY,gBAAA,EAAA,EAAiB,CAAA;AAAA,QAE5B,YAAE,4BAA4B;AAAA;AAAA,KACjC;AAAA,oBAEA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,YAAA,EAAW,WAAA;AAAA,QACX,UAAU,CAAC,aAAA;AAAA,QACX,OAAA,EAAS,aAAA;AAAA,QACT,OAAA,sBAAUA,cAAA,EAAA,EAAoB,CAAA;AAAA,QAE7B,YAAE,wBAAwB;AAAA;AAAA;AAC7B,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -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 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\n const result = useAsync(async () => {\n const resultSet = await searchApi.query({\n term,\n types,\n filters,\n pageLimit,\n pageCursor,\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 // 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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"}
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 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\n const result = useAsync(async () => {\n const resultSet = await searchApi.query({\n term,\n types,\n filters,\n pageLimit,\n pageCursor,\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 // 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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"}
@@ -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":";;;;;;;AA4CA,MAAM,iCAAA,GACJ,yCAAA;AAQF,MAAM,wCAAA,GAA2C,CAC/C,QAAA,EACA,MAAA,KACG;AACH,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,IAAI,CAAC,cAAA,CAAe,OAAO,CAAA,EAAG;AAC9B,IAAA,MAAM,SAAA,GAAY,gBAAA;AAAA,MAChB,OAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,IAAI,CAAC,SAAA,GAAY,MAAM,CAAA,EAAG;AAC1B,IAAA,OAAO,aAAa,OAAA,EAAS;AAAA,MAC3B,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,QAAQ,MAAA,CAAO,QAAA;AAAA;AAAA,MAEf,GAAG,OAAA,CAAQ;AAAA,KACZ,CAAA;AAAA,EACH;AACA,EAAA,OAAO,IAAA;AACT,CAAA;AAoBO,MAAM,6BAAA,GAAgC,CAC3C,KAAA,KACG;AACH,EAAA,MAAM;AAAA,IACJ,IAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,UAAA,GAAa,YAAA;AAAA,IACb,GAAG;AAAA,GACL,GAAI,KAAA;AACJ,EAAA,MAAM,YAAY,YAAA,EAAa;AAE/B,EAAA,MAAM,kBAAA,GAAqB,YAAY,MAAM;AAC3C,IAAA,IAAI,OAAA,EAAS;AACb,IAAA,IAAI,CAAC,MAAA,EAAQ;AACb,IAAA,SAAA,CAAU,YAAA,CAAa,UAAA,EAAY,MAAA,CAAO,KAAA,EAAO;AAAA,MAC/C,UAAA,EAAY,EAAE,EAAA,EAAI,MAAA,CAAO,QAAA,EAAS;AAAA,MAClC,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH,GAAG,CAAC,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,SAAS,CAAC,CAAA;AAErC,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAO,IAAA;AAAA,MACP,UAAA;AAAA,MACA,cAAA,EAAgB,kBAAA;AAAA,MACf,GAAG,IAAA;AAAA,MAEH;AAAA;AAAA,GACH;AAEJ;AA6BO,MAAM,mCAAA,GAAsC,CAGjD,OAAA,KACyB;AACzB,EAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,SAAA,GAAY,MAAM,MAAK,GAAI,OAAA;AAEpD,EAAA,OAAO,oBAAA,CAAgC;AAAA,IACrC,IAAA;AAAA,IACA,SAAA,EAAW;AAAA,MACT,IAAA,EAAM,MACJ,SAAA,EAAU,CAAE,IAAA;AAAA,QACV,UACG,CAAA,KAAA,qBACC,GAAA;AAAA,UAAC,6BAAA;AAAA,UAAA;AAAA,YACC,MAAM,KAAA,CAAM,IAAA;AAAA,YACZ,QAAQ,KAAA,CAAM,MAAA;AAAA,YACd,SAAS,KAAA,CAAM,OAAA;AAAA,YAEd,QAAA,EAAA,aAAA,CAAc,MAAM,KAAK;AAAA;AAAA;AAC5B;AAEN,KACJ;AAAA,IACA,IAAA,EAAM;AAAA,MACJ,CAAC,iCAAiC,GAAG;AAAA;AACvC,GACD,CAAA;AACH;AAMO,MAAM,iCAAA,GAAoC,CAAC,QAAA,KAAwB;AACxE,EAAA,MAAM,QAAA,GAAW,gBAAA;AAAA,IACf,QAAA;AAAA,IACA,CAAA,UAAA,KAAc;AACZ,MAAA,OAAO,WACJ,qBAAA,CAAsB;AAAA,QACrB,GAAA,EAAK;AAAA,OACN,EACA,WAAA,EAAY;AAAA,IACjB,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AAEA,EAAA,OAAO,WAAA;AAAA,IACL,CAAC,QAAsB,GAAA,KAAiB;AACtC,MAAA,MAAM,OAAA,GAAU,wCAAA;AAAA,QACd,QAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,uBACE,GAAA,CAAC,YACE,QAAA,EAAA,OAAA,oBACC,GAAA;AAAA,QAAC,6BAAA;AAAA,QAAA;AAAA,UACC,MAAM,MAAA,CAAO,IAAA;AAAA,UACb,QAAQ,MAAA,CAAO,QAAA;AAAA,UAEf,QAAA,kBAAA,GAAA;AAAA,YAACA,gCAAA;AAAA,YAAA;AAAA,cACC,MAAM,MAAA,CAAO,IAAA;AAAA,cACb,WAAW,MAAA,CAAO,SAAA;AAAA,cAClB,QAAQ,MAAA,CAAO;AAAA;AAAA;AACjB;AAAA,WAVS,GAaf,CAAA;AAAA,IAEJ,CAAA;AAAA,IACA,CAAC,QAAQ;AAAA,GACX;AACF;AAkBO,MAAM,8BAAA,GAAiC,CAC5C,KAAA,KACG;AACH,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,GAAG,MAAK,GAAI,KAAA;AACvC,EAAA,MAAM,MAAA,GAAS,kCAAkC,QAAQ,CAAA;AACzD,EAAA,2BAAQ,IAAA,EAAA,EAAM,GAAG,MAAO,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,EAAE,CAAA;AAC9C;;;;"}
package/dist/index.d.ts CHANGED
@@ -253,13 +253,6 @@ declare const SearchFilter: {
253
253
  (props: SearchFilterWrapperProps): react_jsx_runtime.JSX.Element;
254
254
  Checkbox(props: Omit<SearchFilterWrapperProps, "component"> & SearchFilterComponentProps): react_jsx_runtime.JSX.Element;
255
255
  Select(props: Omit<SearchFilterWrapperProps, "component"> & SearchFilterComponentProps): react_jsx_runtime.JSX.Element;
256
- /**
257
- * A control surface for a given filter field name, rendered as an autocomplete
258
- * textfield. A hard-coded list of values may be provided, or an async function
259
- * which returns values may be provided instead.
260
- *
261
- * @public
262
- */
263
256
  Autocomplete(props: SearchAutocompleteFilterProps): react_jsx_runtime.JSX.Element;
264
257
  };
265
258
 
@@ -1 +1 @@
1
- {"version":3,"file":"translation.esm.js","sources":["../src/translation.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { createTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/**\n * @alpha\n */\nexport const searchReactTranslationRef = createTranslationRef({\n id: 'search-react',\n messages: {\n searchBar: {\n title: 'Search',\n placeholder: 'Search in {{org}}',\n clearButtonTitle: 'Clear',\n },\n searchFilter: {\n allOptionTitle: 'All',\n },\n searchPagination: {\n limitLabel: 'Results per page:',\n limitText: 'of {{num}}',\n },\n noResultsDescription: 'Sorry, no results were found',\n searchResultGroup: {\n linkTitle: 'See All',\n addFilterButtonTitle: 'Add filter',\n },\n searchResultPager: {\n previous: 'Previous',\n next: 'Next',\n },\n },\n});\n"],"names":[],"mappings":";;AAqBO,MAAM,4BAA4B,oBAAqB,CAAA;AAAA,EAC5D,EAAI,EAAA,cAAA;AAAA,EACJ,QAAU,EAAA;AAAA,IACR,SAAW,EAAA;AAAA,MACT,KAAO,EAAA,QAAA;AAAA,MACP,WAAa,EAAA,mBAAA;AAAA,MACb,gBAAkB,EAAA;AAAA,KACpB;AAAA,IACA,YAAc,EAAA;AAAA,MACZ,cAAgB,EAAA;AAAA,KAClB;AAAA,IACA,gBAAkB,EAAA;AAAA,MAChB,UAAY,EAAA,mBAAA;AAAA,MACZ,SAAW,EAAA;AAAA,KACb;AAAA,IACA,oBAAsB,EAAA,8BAAA;AAAA,IACtB,iBAAmB,EAAA;AAAA,MACjB,SAAW,EAAA,SAAA;AAAA,MACX,oBAAsB,EAAA;AAAA,KACxB;AAAA,IACA,iBAAmB,EAAA;AAAA,MACjB,QAAU,EAAA,UAAA;AAAA,MACV,IAAM,EAAA;AAAA;AACR;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"translation.esm.js","sources":["../src/translation.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { createTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/**\n * @alpha\n */\nexport const searchReactTranslationRef = createTranslationRef({\n id: 'search-react',\n messages: {\n searchBar: {\n title: 'Search',\n placeholder: 'Search in {{org}}',\n clearButtonTitle: 'Clear',\n },\n searchFilter: {\n allOptionTitle: 'All',\n },\n searchPagination: {\n limitLabel: 'Results per page:',\n limitText: 'of {{num}}',\n },\n noResultsDescription: 'Sorry, no results were found',\n searchResultGroup: {\n linkTitle: 'See All',\n addFilterButtonTitle: 'Add filter',\n },\n searchResultPager: {\n previous: 'Previous',\n next: 'Next',\n },\n },\n});\n"],"names":[],"mappings":";;AAqBO,MAAM,4BAA4B,oBAAA,CAAqB;AAAA,EAC5D,EAAA,EAAI,cAAA;AAAA,EACJ,QAAA,EAAU;AAAA,IACR,SAAA,EAAW;AAAA,MACT,KAAA,EAAO,QAAA;AAAA,MACP,WAAA,EAAa,mBAAA;AAAA,MACb,gBAAA,EAAkB;AAAA,KACpB;AAAA,IACA,YAAA,EAAc;AAAA,MACZ,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,gBAAA,EAAkB;AAAA,MAChB,UAAA,EAAY,mBAAA;AAAA,MACZ,SAAA,EAAW;AAAA,KACb;AAAA,IACA,oBAAA,EAAsB,8BAAA;AAAA,IACtB,iBAAA,EAAmB;AAAA,MACjB,SAAA,EAAW,SAAA;AAAA,MACX,oBAAA,EAAsB;AAAA,KACxB;AAAA,IACA,iBAAA,EAAmB;AAAA,MACjB,QAAA,EAAU,UAAA;AAAA,MACV,IAAA,EAAM;AAAA;AACR;AAEJ,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-search-react",
3
- "version": "1.9.3-next.1",
3
+ "version": "1.9.4-next.0",
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.17.5-next.1",
67
+ "@backstage/core-components": "0.17.6-next.0",
68
68
  "@backstage/core-plugin-api": "1.10.9",
69
- "@backstage/frontend-plugin-api": "0.11.0-next.1",
69
+ "@backstage/frontend-plugin-api": "0.11.1-next.0",
70
70
  "@backstage/plugin-search-common": "1.2.19",
71
- "@backstage/theme": "0.6.8-next.0",
71
+ "@backstage/theme": "0.6.8",
72
72
  "@backstage/types": "1.2.1",
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.0-next.1",
83
+ "@backstage/cli": "0.34.2-next.1",
84
84
  "@backstage/core-app-api": "1.18.0",
85
- "@backstage/frontend-app-api": "0.12.0-next.2",
86
- "@backstage/frontend-test-utils": "0.3.5-next.2",
87
- "@backstage/test-utils": "1.7.11-next.0",
85
+ "@backstage/frontend-app-api": "0.12.1-next.0",
86
+ "@backstage/frontend-test-utils": "0.3.6-next.0",
87
+ "@backstage/test-utils": "1.7.11",
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",