@backstage/plugin-search-react 1.8.8-next.0 → 1.8.8-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/alpha/blueprints/SearchResultListItemBlueprint.esm.js +7 -6
  3. package/dist/alpha/blueprints/SearchResultListItemBlueprint.esm.js.map +1 -1
  4. package/dist/components/DefaultResultListItem/DefaultResultListItem.esm.js +42 -38
  5. package/dist/components/DefaultResultListItem/DefaultResultListItem.esm.js.map +1 -1
  6. package/dist/components/HighlightedSearchResultText/HighlightedSearchResultText.esm.js +5 -4
  7. package/dist/components/HighlightedSearchResultText/HighlightedSearchResultText.esm.js.map +1 -1
  8. package/dist/components/SearchAutocomplete/SearchAutocomplete.esm.js +7 -6
  9. package/dist/components/SearchAutocomplete/SearchAutocomplete.esm.js.map +1 -1
  10. package/dist/components/SearchAutocomplete/SearchAutocompleteDefaultOption.esm.js +14 -11
  11. package/dist/components/SearchAutocomplete/SearchAutocompleteDefaultOption.esm.js.map +1 -1
  12. package/dist/components/SearchBar/SearchBar.esm.js +23 -22
  13. package/dist/components/SearchBar/SearchBar.esm.js.map +1 -1
  14. package/dist/components/SearchFilter/SearchFilter.Autocomplete.esm.js +5 -4
  15. package/dist/components/SearchFilter/SearchFilter.Autocomplete.esm.js.map +1 -1
  16. package/dist/components/SearchFilter/SearchFilter.esm.js +45 -42
  17. package/dist/components/SearchFilter/SearchFilter.esm.js.map +1 -1
  18. package/dist/components/SearchPagination/SearchPagination.esm.js +4 -3
  19. package/dist/components/SearchPagination/SearchPagination.esm.js.map +1 -1
  20. package/dist/components/SearchResult/SearchResult.esm.js +12 -12
  21. package/dist/components/SearchResult/SearchResult.esm.js.map +1 -1
  22. package/dist/components/SearchResultGroup/SearchResultGroup.esm.js +99 -79
  23. package/dist/components/SearchResultGroup/SearchResultGroup.esm.js.map +1 -1
  24. package/dist/components/SearchResultList/SearchResultList.esm.js +22 -22
  25. package/dist/components/SearchResultList/SearchResultList.esm.js.map +1 -1
  26. package/dist/components/SearchResultPager/SearchResultPager.esm.js +24 -21
  27. package/dist/components/SearchResultPager/SearchResultPager.esm.js.map +1 -1
  28. package/dist/context/SearchContext.esm.js +7 -6
  29. package/dist/context/SearchContext.esm.js.map +1 -1
  30. package/dist/extensions.esm.js +23 -22
  31. package/dist/extensions.esm.js.map +1 -1
  32. package/dist/index.d.ts +39 -37
  33. package/package.json +13 -13
@@ -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 React, {\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';\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\n const {\n error,\n loading,\n icon,\n title,\n titleProps = {},\n link = (\n <>\n See all\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=\"Sorry, no results were found\" />\n ),\n ...rest\n } = props;\n\n const handleClick = useCallback((e: React.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=\"Add filter\"\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';\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\n const {\n error,\n loading,\n icon,\n title,\n titleProps = {},\n link = (\n <>\n See all\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=\"Sorry, no results were found\" />\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=\"Add filter\"\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,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx, Fragment } from 'react/jsx-runtime';
2
2
  import List from '@material-ui/core/List';
3
3
  import { Progress, ResponseErrorPanel, EmptyState } from '@backstage/core-components';
4
4
  import { AnalyticsContext } from '@backstage/core-plugin-api';
@@ -11,22 +11,22 @@ const SearchResultListLayout = (props) => {
11
11
  error,
12
12
  loading,
13
13
  resultItems,
14
- renderResultItem = (resultItem) => /* @__PURE__ */ React.createElement(
14
+ renderResultItem = (resultItem) => /* @__PURE__ */ jsx(
15
15
  HigherOrderDefaultResultListItem,
16
16
  {
17
- key: resultItem.document.location,
18
17
  result: resultItem.document
19
- }
18
+ },
19
+ resultItem.document.location
20
20
  ),
21
21
  disableRenderingWithNoResults,
22
- noResultsComponent = disableRenderingWithNoResults ? null : /* @__PURE__ */ React.createElement(EmptyState, { missing: "data", title: "Sorry, no results were found" }),
22
+ noResultsComponent = disableRenderingWithNoResults ? null : /* @__PURE__ */ jsx(EmptyState, { missing: "data", title: "Sorry, no results were found" }),
23
23
  ...rest
24
24
  } = props;
25
25
  if (loading) {
26
- return /* @__PURE__ */ React.createElement(Progress, null);
26
+ return /* @__PURE__ */ jsx(Progress, {});
27
27
  }
28
28
  if (error) {
29
- return /* @__PURE__ */ React.createElement(
29
+ return /* @__PURE__ */ jsx(
30
30
  ResponseErrorPanel,
31
31
  {
32
32
  title: "Error encountered while fetching search results",
@@ -35,31 +35,31 @@ const SearchResultListLayout = (props) => {
35
35
  );
36
36
  }
37
37
  if (!resultItems?.length) {
38
- return /* @__PURE__ */ React.createElement(React.Fragment, null, noResultsComponent);
38
+ return /* @__PURE__ */ jsx(Fragment, { children: noResultsComponent });
39
39
  }
40
- return /* @__PURE__ */ React.createElement(List, { ...rest }, resultItems.map(renderResultItem));
40
+ return /* @__PURE__ */ jsx(List, { ...rest, children: resultItems.map(renderResultItem) });
41
41
  };
42
42
  const SearchResultList = (props) => {
43
43
  const { query, renderResultItem, children, ...rest } = props;
44
44
  const defaultRenderResultItem = useSearchResultListItemExtensions(children);
45
- return /* @__PURE__ */ React.createElement(
45
+ return /* @__PURE__ */ jsx(
46
46
  AnalyticsContext,
47
47
  {
48
48
  attributes: {
49
49
  pluginId: "search",
50
50
  extension: "SearchResultList"
51
- }
52
- },
53
- /* @__PURE__ */ React.createElement(SearchResultState, { query }, ({ loading, error, value }) => /* @__PURE__ */ React.createElement(
54
- SearchResultListLayout,
55
- {
56
- ...rest,
57
- error,
58
- loading,
59
- resultItems: value?.results,
60
- renderResultItem: renderResultItem ?? defaultRenderResultItem
61
- }
62
- ))
51
+ },
52
+ children: /* @__PURE__ */ jsx(SearchResultState, { query, children: ({ loading, error, value }) => /* @__PURE__ */ jsx(
53
+ SearchResultListLayout,
54
+ {
55
+ ...rest,
56
+ error,
57
+ loading,
58
+ resultItems: value?.results,
59
+ renderResultItem: renderResultItem ?? defaultRenderResultItem
60
+ }
61
+ ) })
62
+ }
63
63
  );
64
64
  };
65
65
 
@@ -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 React, { 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';\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 {\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=\"Sorry, no results were found\" />\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":";;;;;;;;AAyEa,MAAA,sBAAA,GAAyB,CAAC,KAAuC,KAAA;AAC5E,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,OAAA;AAAA,IACA,WAAA;AAAA,IACA,mBAAmB,CACjB,UAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,MAACA,gCAAA;AAAA,MAAA;AAAA,QACC,GAAA,EAAK,WAAW,QAAS,CAAA,QAAA;AAAA,QACzB,QAAQ,UAAW,CAAA;AAAA;AAAA,KACrB;AAAA,IAEF,6BAAA;AAAA,IACA,kBAAA,GAAqB,gCAAgC,IACnD,mBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,MAAA,EAAO,OAAM,8BAA+B,EAAA,CAAA;AAAA,IAElE,GAAG;AAAA,GACD,GAAA,KAAA;AAEJ,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,KAAO,EAAA;AACT,IACE,uBAAA,KAAA,CAAA,aAAA;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,iEAAU,kBAAmB,CAAA;AAAA;AAG/B,EAAA,2CAAQ,IAAM,EAAA,EAAA,GAAG,QAAO,WAAY,CAAA,GAAA,CAAI,gBAAgB,CAAE,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,KAAA,CAAA,aAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,UAAY,EAAA;AAAA,QACV,QAAU,EAAA,QAAA;AAAA,QACV,SAAW,EAAA;AAAA;AACb,KAAA;AAAA,oBAEA,KAAA,CAAA,aAAA,CAAC,qBAAkB,KAChB,EAAA,EAAA,CAAC,EAAE,OAAS,EAAA,KAAA,EAAO,OAClB,qBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,sBAAA;AAAA,MAAA;AAAA,QACE,GAAG,IAAA;AAAA,QACJ,KAAA;AAAA,QACA,OAAA;AAAA,QACA,aAAa,KAAO,EAAA,OAAA;AAAA,QACpB,kBAAkB,gBAAoB,IAAA;AAAA;AAAA,KAG5C;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';\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 {\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=\"Sorry, no results were found\" />\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":";;;;;;;;AAyEa,MAAA,sBAAA,GAAyB,CAAC,KAAuC,KAAA;AAC5E,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,gCAAgC,IACnD,mBAAA,GAAA,CAAC,cAAW,OAAQ,EAAA,MAAA,EAAO,OAAM,8BAA+B,EAAA,CAAA;AAAA,IAElE,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,4 +1,4 @@
1
- import React from 'react';
1
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
2
2
  import Button from '@material-ui/core/Button';
3
3
  import { makeStyles } from '@material-ui/core/styles';
4
4
  import ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';
@@ -17,27 +17,30 @@ const SearchResultPager = () => {
17
17
  const { fetchNextPage, fetchPreviousPage } = useSearch();
18
18
  const classes = useStyles();
19
19
  if (!fetchNextPage && !fetchPreviousPage) {
20
- return /* @__PURE__ */ React.createElement(React.Fragment, null);
20
+ return /* @__PURE__ */ jsx(Fragment, {});
21
21
  }
22
- return /* @__PURE__ */ React.createElement("nav", { "aria-label": "pagination navigation", className: classes.root }, /* @__PURE__ */ React.createElement(
23
- Button,
24
- {
25
- "aria-label": "previous page",
26
- disabled: !fetchPreviousPage,
27
- onClick: fetchPreviousPage,
28
- startIcon: /* @__PURE__ */ React.createElement(ArrowBackIosIcon, null)
29
- },
30
- "Previous"
31
- ), /* @__PURE__ */ React.createElement(
32
- Button,
33
- {
34
- "aria-label": "next page",
35
- disabled: !fetchNextPage,
36
- onClick: fetchNextPage,
37
- endIcon: /* @__PURE__ */ React.createElement(ArrowRightIcon, null)
38
- },
39
- "Next"
40
- ));
22
+ return /* @__PURE__ */ jsxs("nav", { "aria-label": "pagination navigation", className: classes.root, children: [
23
+ /* @__PURE__ */ jsx(
24
+ Button,
25
+ {
26
+ "aria-label": "previous page",
27
+ disabled: !fetchPreviousPage,
28
+ onClick: fetchPreviousPage,
29
+ startIcon: /* @__PURE__ */ jsx(ArrowBackIosIcon, {}),
30
+ children: "Previous"
31
+ }
32
+ ),
33
+ /* @__PURE__ */ jsx(
34
+ Button,
35
+ {
36
+ "aria-label": "next page",
37
+ disabled: !fetchNextPage,
38
+ onClick: fetchNextPage,
39
+ endIcon: /* @__PURE__ */ jsx(ArrowRightIcon, {}),
40
+ children: "Next"
41
+ }
42
+ )
43
+ ] });
41
44
  };
42
45
 
43
46
  export { SearchResultPager };
@@ -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 React from 'react';\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';\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\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 Previous\n </Button>\n\n <Button\n aria-label=\"next page\"\n disabled={!fetchNextPage}\n onClick={fetchNextPage}\n endIcon={<ArrowForwardIosIcon />}\n >\n 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;AAE1B,EAAI,IAAA,CAAC,aAAiB,IAAA,CAAC,iBAAmB,EAAA;AACxC,IAAA,uBAAS,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,CAAA;AAAA;AAGX,EAAA,2CACG,KAAI,EAAA,EAAA,YAAA,EAAW,uBAAwB,EAAA,SAAA,EAAW,QAAQ,IACzD,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,YAAW,EAAA,eAAA;AAAA,MACX,UAAU,CAAC,iBAAA;AAAA,MACX,OAAS,EAAA,iBAAA;AAAA,MACT,SAAA,sCAAY,gBAAiB,EAAA,IAAA;AAAA,KAAA;AAAA,IAC9B;AAAA,GAID,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,YAAW,EAAA,WAAA;AAAA,MACX,UAAU,CAAC,aAAA;AAAA,MACX,OAAS,EAAA,aAAA;AAAA,MACT,OAAA,sCAAUA,cAAoB,EAAA,IAAA;AAAA,KAAA;AAAA,IAC/B;AAAA,GAGH,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';\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\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 Previous\n </Button>\n\n <Button\n aria-label=\"next page\"\n disabled={!fetchNextPage}\n onClick={fetchNextPage}\n endIcon={<ArrowForwardIosIcon />}\n >\n Next\n </Button>\n </nav>\n );\n};\n"],"names":["ArrowForwardIosIcon"],"mappings":";;;;;;;AAuBA,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;AAE1B,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,QAC9B,QAAA,EAAA;AAAA;AAAA,KAED;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,QAC/B,QAAA,EAAA;AAAA;AAAA;AAED,GACF,EAAA,CAAA;AAEJ;;;;"}
@@ -1,5 +1,6 @@
1
+ import { jsx, Fragment } from 'react/jsx-runtime';
1
2
  import { isEqual } from 'lodash';
2
- import React, { useContext, useState, useCallback, useEffect } from 'react';
3
+ import { useContext, useState, useCallback, useEffect } from 'react';
3
4
  import useAsync from 'react-use/esm/useAsync';
4
5
  import usePrevious from 'react-use/esm/usePrevious';
5
6
  import { createVersionedContext, createVersionedValueMap } from '@backstage/version-bridge';
@@ -96,12 +97,12 @@ const useSearchContextValue = (initialValue = defaultInitialSearchState) => {
96
97
  const LocalSearchContext = (props) => {
97
98
  const { initialState, children } = props;
98
99
  const value = useSearchContextValue(initialState);
99
- return /* @__PURE__ */ React.createElement(
100
+ return /* @__PURE__ */ jsx(
100
101
  AnalyticsContext,
101
102
  {
102
- attributes: { searchTypes: value.types.sort().join(",") }
103
- },
104
- /* @__PURE__ */ React.createElement(SearchContext.Provider, { value: createVersionedValueMap({ 1: value }) }, children)
103
+ attributes: { searchTypes: value.types.sort().join(",") },
104
+ children: /* @__PURE__ */ jsx(SearchContext.Provider, { value: createVersionedValueMap({ 1: value }), children })
105
+ }
105
106
  );
106
107
  };
107
108
  const SearchContextProvider = (props) => {
@@ -115,7 +116,7 @@ const SearchContextProvider = (props) => {
115
116
  ...propsInitialSearchState,
116
117
  ...configInitialSearchState
117
118
  };
118
- return hasParentContext && inheritParentContextIfAvailable ? /* @__PURE__ */ React.createElement(React.Fragment, null, children) : /* @__PURE__ */ React.createElement(LocalSearchContext, { initialState: searchContextInitialState }, children);
119
+ return hasParentContext && inheritParentContextIfAvailable ? /* @__PURE__ */ jsx(Fragment, { children }) : /* @__PURE__ */ jsx(LocalSearchContext, { initialState: searchContextInitialState, children });
119
120
  };
120
121
 
121
122
  export { SearchContextProvider, useSearch, useSearchContextCheck };
@@ -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 React, {\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: React.Dispatch<React.SetStateAction<string>>;\n setTypes: React.Dispatch<React.SetStateAction<string[]>>;\n setFilters: React.Dispatch<React.SetStateAction<JsonObject>>;\n setPageLimit: React.Dispatch<React.SetStateAction<number | undefined>>;\n setPageCursor: React.Dispatch<React.SetStateAction<string | undefined>>;\n fetchNextPage?: React.DispatchWithoutAction;\n fetchPreviousPage?: React.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,4 +1,5 @@
1
- import React, { useCallback, createElement, Fragment, isValidElement, cloneElement } from 'react';
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useCallback, createElement, Fragment, isValidElement, cloneElement } from 'react';
2
3
  import { useAnalytics, createReactExtension, useElementFilter, getComponentData } from '@backstage/core-plugin-api';
3
4
  import List from '@material-ui/core/List';
4
5
  import ListItem from '@material-ui/core/ListItem';
@@ -41,15 +42,15 @@ const SearchResultListItemExtension = (props) => {
41
42
  value: rank
42
43
  });
43
44
  }, [rank, result, noTrack, analytics]);
44
- return /* @__PURE__ */ React.createElement(
45
+ return /* @__PURE__ */ jsx(
45
46
  ListItem,
46
47
  {
47
48
  divider: true,
48
49
  alignItems,
49
50
  onClickCapture: handleClickCapture,
50
- ...rest
51
- },
52
- children
51
+ ...rest,
52
+ children
53
+ }
53
54
  );
54
55
  };
55
56
  const createSearchResultListItemExtension = (options) => {
@@ -58,14 +59,14 @@ const createSearchResultListItemExtension = (options) => {
58
59
  name,
59
60
  component: {
60
61
  lazy: () => component().then(
61
- (type) => (props) => /* @__PURE__ */ React.createElement(
62
+ (type) => (props) => /* @__PURE__ */ jsx(
62
63
  SearchResultListItemExtension,
63
64
  {
64
65
  rank: props.rank,
65
66
  result: props.result,
66
- noTrack: props.noTrack
67
- },
68
- createElement(type, props)
67
+ noTrack: props.noTrack,
68
+ children: createElement(type, props)
69
+ }
69
70
  )
70
71
  )
71
72
  },
@@ -90,21 +91,21 @@ const useSearchResultListItemExtensions = (children) => {
90
91
  elements,
91
92
  result
92
93
  );
93
- return /* @__PURE__ */ React.createElement(Fragment, { key }, element ?? /* @__PURE__ */ React.createElement(
94
+ return /* @__PURE__ */ jsx(Fragment, { children: element ?? /* @__PURE__ */ jsx(
94
95
  SearchResultListItemExtension,
95
96
  {
96
97
  rank: result.rank,
97
- result: result.document
98
- },
99
- /* @__PURE__ */ React.createElement(
100
- HigherOrderDefaultResultListItem,
101
- {
102
- rank: result.rank,
103
- highlight: result.highlight,
104
- result: result.document
105
- }
106
- )
107
- ));
98
+ result: result.document,
99
+ children: /* @__PURE__ */ jsx(
100
+ HigherOrderDefaultResultListItem,
101
+ {
102
+ rank: result.rank,
103
+ highlight: result.highlight,
104
+ result: result.document
105
+ }
106
+ )
107
+ }
108
+ ) }, key);
108
109
  },
109
110
  [elements]
110
111
  );
@@ -112,7 +113,7 @@ const useSearchResultListItemExtensions = (children) => {
112
113
  const SearchResultListItemExtensions = (props) => {
113
114
  const { results, children, ...rest } = props;
114
115
  const render = useSearchResultListItemExtensions(children);
115
- return /* @__PURE__ */ React.createElement(List, { ...rest }, results.map(render));
116
+ return /* @__PURE__ */ jsx(List, { ...rest, children: results.map(render) });
116
117
  };
117
118
 
118
119
  export { SearchResultListItemExtension, SearchResultListItemExtensions, createSearchResultListItemExtension, useSearchResultListItemExtensions };
@@ -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 React, {\n Fragment,\n ReactNode,\n PropsWithChildren,\n isValidElement,\n createElement,\n cloneElement,\n useCallback,\n} from 'react';\n\nimport {\n getComponentData,\n useElementFilter,\n Extension,\n createReactExtension,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchDocument, SearchResult } from '@backstage/plugin-search-common';\n\nimport List, { ListProps } from '@material-ui/core/List';\nimport ListItem, { ListItemProps } from '@material-ui/core/ListItem';\n\nimport { DefaultResultListItem } from './components/DefaultResultListItem';\n\n/**\n * @internal\n * Key for result extensions.\n */\nconst SEARCH_RESULT_LIST_ITEM_EXTENSION =\n 'search.results.list.items.extensions.v1';\n\n/**\n * @internal\n * Returns the first extension element found for a given result, and null otherwise.\n * @param elements - All extension elements.\n * @param result - The search result.\n */\nconst findSearchResultListItemExtensionElement = (\n elements: ReactNode[],\n result: SearchResult,\n) => {\n for (const element of elements) {\n if (!isValidElement(element)) continue;\n const predicate = getComponentData<(result: SearchResult) => boolean>(\n element,\n SEARCH_RESULT_LIST_ITEM_EXTENSION,\n );\n if (!predicate?.(result)) continue;\n return cloneElement(element, {\n rank: result.rank,\n highlight: result.highlight,\n result: result.document,\n // Use props in situations where a consumer is manually rendering the extension\n ...element.props,\n });\n }\n return null;\n};\n\n/**\n * @public\n * Extends props for any search result list item extension\n */\nexport type SearchResultListItemExtensionProps<Props extends {} = {}> = Props &\n PropsWithChildren<\n {\n rank?: number;\n result?: SearchDocument;\n noTrack?: boolean;\n } & Omit<ListItemProps, 'button'>\n >;\n\n/**\n * @internal\n * Extends children with extension capabilities.\n * @param props - see {@link SearchResultListItemExtensionProps}.\n */\nexport const SearchResultListItemExtension = (\n props: SearchResultListItemExtensionProps,\n) => {\n const {\n rank,\n result,\n noTrack,\n children,\n alignItems = 'flex-start',\n ...rest\n } = props;\n const analytics = useAnalytics();\n\n const handleClickCapture = useCallback(() => {\n if (noTrack) return;\n if (!result) return;\n analytics.captureEvent('discover', result.title, {\n attributes: { to: result.location },\n value: rank,\n });\n }, [rank, result, noTrack, analytics]);\n\n return (\n <ListItem\n divider\n alignItems={alignItems}\n onClickCapture={handleClickCapture}\n {...rest}\n >\n {children}\n </ListItem>\n );\n};\n\n/**\n * @public\n * Options for {@link createSearchResultListItemExtension}.\n */\nexport type SearchResultListItemExtensionOptions<\n Component extends (props: any) => JSX.Element | null,\n> = {\n /**\n * The extension name.\n */\n name: string;\n /**\n * The extension component.\n */\n component: () => Promise<Component>;\n /**\n * When an extension defines a predicate, it returns true if the result should be rendered by that extension.\n * Defaults to a predicate that returns true, which means it renders all sorts of results.\n */\n predicate?: (result: SearchResult) => boolean;\n};\n\n/**\n * @public\n * Creates a search result item extension.\n * @param options - The extension options, see {@link SearchResultListItemExtensionOptions} for more details.\n */\nexport const createSearchResultListItemExtension = <\n Component extends (props: any) => JSX.Element | null,\n>(\n options: SearchResultListItemExtensionOptions<Component>,\n): Extension<Component> => {\n const { name, component, predicate = () => true } = options;\n\n return createReactExtension<Component>({\n name,\n component: {\n lazy: () =>\n component().then(\n type =>\n (props => (\n <SearchResultListItemExtension\n rank={props.rank}\n result={props.result}\n noTrack={props.noTrack}\n >\n {createElement(type, props)}\n </SearchResultListItemExtension>\n )) as Component,\n ),\n },\n data: {\n [SEARCH_RESULT_LIST_ITEM_EXTENSION]: predicate,\n },\n });\n};\n\n/**\n * @public\n * Returns a function that renders a result using extensions.\n */\nexport const useSearchResultListItemExtensions = (children: ReactNode) => {\n const elements = useElementFilter(\n children,\n collection => {\n return collection\n .selectByComponentData({\n key: SEARCH_RESULT_LIST_ITEM_EXTENSION,\n })\n .getElements();\n },\n [children],\n );\n\n return useCallback(\n (result: SearchResult, key?: number) => {\n const element = findSearchResultListItemExtensionElement(\n elements,\n result,\n );\n\n return (\n <Fragment key={key}>\n {element ?? (\n <SearchResultListItemExtension\n rank={result.rank}\n result={result.document}\n >\n <DefaultResultListItem\n rank={result.rank}\n highlight={result.highlight}\n result={result.document}\n />\n </SearchResultListItemExtension>\n )}\n </Fragment>\n );\n },\n [elements],\n );\n};\n\n/**\n * @public\n * Props for {@link SearchResultListItemExtensions}\n */\nexport type SearchResultListItemExtensionsProps = Omit<ListProps, 'results'> & {\n /**\n * Search result list.\n */\n results: SearchResult[];\n};\n\n/**\n * @public\n * Render results using search extensions.\n * @param props - see {@link SearchResultListItemExtensionsProps}\n */\nexport const SearchResultListItemExtensions = (\n props: SearchResultListItemExtensionsProps,\n) => {\n const { results, children, ...rest } = props;\n const render = useSearchResultListItemExtensions(children);\n return <List {...rest}>{results.map(render)}</List>;\n};\n"],"names":["DefaultResultListItem"],"mappings":"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"}
1
+ {"version":3,"file":"extensions.esm.js","sources":["../src/extensions.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Fragment,\n ReactNode,\n PropsWithChildren,\n isValidElement,\n createElement,\n cloneElement,\n useCallback,\n} from 'react';\n\nimport {\n getComponentData,\n useElementFilter,\n Extension,\n createReactExtension,\n useAnalytics,\n} from '@backstage/core-plugin-api';\nimport { SearchDocument, SearchResult } from '@backstage/plugin-search-common';\n\nimport List, { ListProps } from '@material-ui/core/List';\nimport ListItem, { ListItemProps } from '@material-ui/core/ListItem';\n\nimport { DefaultResultListItem } from './components/DefaultResultListItem';\n\n/**\n * @internal\n * Key for result extensions.\n */\nconst SEARCH_RESULT_LIST_ITEM_EXTENSION =\n 'search.results.list.items.extensions.v1';\n\n/**\n * @internal\n * Returns the first extension element found for a given result, and null otherwise.\n * @param elements - All extension elements.\n * @param result - The search result.\n */\nconst findSearchResultListItemExtensionElement = (\n elements: ReactNode[],\n result: SearchResult,\n) => {\n for (const element of elements) {\n if (!isValidElement(element)) continue;\n const predicate = getComponentData<(result: SearchResult) => boolean>(\n element,\n SEARCH_RESULT_LIST_ITEM_EXTENSION,\n );\n if (!predicate?.(result)) continue;\n return cloneElement(element, {\n rank: result.rank,\n highlight: result.highlight,\n result: result.document,\n // Use props in situations where a consumer is manually rendering the extension\n ...element.props,\n });\n }\n return null;\n};\n\n/**\n * @public\n * Extends props for any search result list item extension\n */\nexport type SearchResultListItemExtensionProps<Props extends {} = {}> = Props &\n PropsWithChildren<\n {\n rank?: number;\n result?: SearchDocument;\n noTrack?: boolean;\n } & Omit<ListItemProps, 'button'>\n >;\n\n/**\n * @internal\n * Extends children with extension capabilities.\n * @param props - see {@link SearchResultListItemExtensionProps}.\n */\nexport const SearchResultListItemExtension = (\n props: SearchResultListItemExtensionProps,\n) => {\n const {\n rank,\n result,\n noTrack,\n children,\n alignItems = 'flex-start',\n ...rest\n } = props;\n const analytics = useAnalytics();\n\n const handleClickCapture = useCallback(() => {\n if (noTrack) return;\n if (!result) return;\n analytics.captureEvent('discover', result.title, {\n attributes: { to: result.location },\n value: rank,\n });\n }, [rank, result, noTrack, analytics]);\n\n return (\n <ListItem\n divider\n alignItems={alignItems}\n onClickCapture={handleClickCapture}\n {...rest}\n >\n {children}\n </ListItem>\n );\n};\n\n/**\n * @public\n * Options for {@link createSearchResultListItemExtension}.\n */\nexport type SearchResultListItemExtensionOptions<\n Component extends (props: any) => JSX.Element | null,\n> = {\n /**\n * The extension name.\n */\n name: string;\n /**\n * The extension component.\n */\n component: () => Promise<Component>;\n /**\n * When an extension defines a predicate, it returns true if the result should be rendered by that extension.\n * Defaults to a predicate that returns true, which means it renders all sorts of results.\n */\n predicate?: (result: SearchResult) => boolean;\n};\n\n/**\n * @public\n * Creates a search result item extension.\n * @param options - The extension options, see {@link SearchResultListItemExtensionOptions} for more details.\n */\nexport const createSearchResultListItemExtension = <\n Component extends (props: any) => JSX.Element | null,\n>(\n options: SearchResultListItemExtensionOptions<Component>,\n): Extension<Component> => {\n const { name, component, predicate = () => true } = options;\n\n return createReactExtension<Component>({\n name,\n component: {\n lazy: () =>\n component().then(\n type =>\n (props => (\n <SearchResultListItemExtension\n rank={props.rank}\n result={props.result}\n noTrack={props.noTrack}\n >\n {createElement(type, props)}\n </SearchResultListItemExtension>\n )) as Component,\n ),\n },\n data: {\n [SEARCH_RESULT_LIST_ITEM_EXTENSION]: predicate,\n },\n });\n};\n\n/**\n * @public\n * Returns a function that renders a result using extensions.\n */\nexport const useSearchResultListItemExtensions = (children: ReactNode) => {\n const elements = useElementFilter(\n children,\n collection => {\n return collection\n .selectByComponentData({\n key: SEARCH_RESULT_LIST_ITEM_EXTENSION,\n })\n .getElements();\n },\n [children],\n );\n\n return useCallback(\n (result: SearchResult, key?: number) => {\n const element = findSearchResultListItemExtensionElement(\n elements,\n result,\n );\n\n return (\n <Fragment key={key}>\n {element ?? (\n <SearchResultListItemExtension\n rank={result.rank}\n result={result.document}\n >\n <DefaultResultListItem\n rank={result.rank}\n highlight={result.highlight}\n result={result.document}\n />\n </SearchResultListItemExtension>\n )}\n </Fragment>\n );\n },\n [elements],\n );\n};\n\n/**\n * @public\n * Props for {@link SearchResultListItemExtensions}\n */\nexport type SearchResultListItemExtensionsProps = Omit<ListProps, 'results'> & {\n /**\n * Search result list.\n */\n results: SearchResult[];\n};\n\n/**\n * @public\n * Render results using search extensions.\n * @param props - see {@link SearchResultListItemExtensionsProps}\n */\nexport const SearchResultListItemExtensions = (\n props: SearchResultListItemExtensionsProps,\n) => {\n const { results, children, ...rest } = props;\n const render = useSearchResultListItemExtensions(children);\n return <List {...rest}>{results.map(render)}</List>;\n};\n"],"names":["DefaultResultListItem"],"mappings":"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"}