@verdaccio/ui-components 5.0.0-next-9.24 → 5.0.0-next-9.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/build/api/use-data.d.ts +2 -2
- package/build/api/use-data.js +2 -2
- package/build/api/use-data.js.map +1 -1
- package/build/api/use-data.mjs +2 -2
- package/build/api/use-data.mjs.map +1 -1
- package/build/components/CopyClipboard/CopyToClipBoard.d.ts +1 -0
- package/build/components/CopyClipboard/CopyToClipBoard.js +36 -17
- package/build/components/CopyClipboard/CopyToClipBoard.js.map +1 -1
- package/build/components/CopyClipboard/CopyToClipBoard.mjs +36 -19
- package/build/components/CopyClipboard/CopyToClipBoard.mjs.map +1 -1
- package/build/components/CopyClipboard/utils.d.ts +2 -1
- package/build/components/CopyClipboard/utils.js +6 -4
- package/build/components/CopyClipboard/utils.js.map +1 -1
- package/build/components/CopyClipboard/utils.mjs +6 -4
- package/build/components/CopyClipboard/utils.mjs.map +1 -1
- package/build/components/DocsLink/DocsLink.d.ts +8 -0
- package/build/components/DocsLink/DocsLink.js +40 -0
- package/build/components/DocsLink/DocsLink.js.map +1 -0
- package/build/components/DocsLink/DocsLink.mjs +35 -0
- package/build/components/DocsLink/DocsLink.mjs.map +1 -0
- package/build/components/DocsLink/index.d.ts +1 -0
- package/build/components/DocsLink/index.js +3 -0
- package/build/components/DocsLink/index.mjs +1 -0
- package/build/components/Help/Help.d.ts +13 -0
- package/build/components/Help/Help.js +280 -36
- package/build/components/Help/Help.js.map +1 -1
- package/build/components/Help/Help.mjs +274 -39
- package/build/components/Help/Help.mjs.map +1 -1
- package/build/components/Help/styles.d.ts +29 -0
- package/build/components/Help/styles.js +86 -1
- package/build/components/Help/styles.js.map +1 -1
- package/build/components/Help/styles.mjs +82 -2
- package/build/components/Help/styles.mjs.map +1 -1
- package/build/components/Icons/Managers/Bun.d.ts +2 -0
- package/build/components/Icons/Managers/Bun2.js +18 -0
- package/build/components/Icons/Managers/Bun2.js.map +1 -0
- package/build/components/Icons/Managers/Bun2.mjs +16 -0
- package/build/components/Icons/Managers/Bun2.mjs.map +1 -0
- package/build/components/Icons/Managers/bun.js +6 -0
- package/build/components/Icons/Managers/bun.js.map +1 -0
- package/build/components/Icons/Managers/bun.mjs +6 -0
- package/build/components/Icons/Managers/bun.mjs.map +1 -0
- package/build/components/Icons/Managers/bun.svg +1 -0
- package/build/components/Icons/Managers/index.d.ts +1 -0
- package/build/components/Icons/Managers/index.js +2 -0
- package/build/components/Icons/Managers/index.mjs +2 -1
- package/build/components/Icons/index.js +3 -0
- package/build/components/Icons/index.mjs +3 -1
- package/build/components/Install/Install.d.ts +2 -0
- package/build/components/Install/Install.js +30 -2
- package/build/components/Install/Install.js.map +1 -1
- package/build/components/Install/Install.mjs +30 -3
- package/build/components/Install/Install.mjs.map +1 -1
- package/build/components/Install/InstallListItem.d.ts +2 -1
- package/build/components/Install/InstallListItem.js +17 -0
- package/build/components/Install/InstallListItem.js.map +1 -1
- package/build/components/Install/InstallListItem.mjs +17 -0
- package/build/components/Install/InstallListItem.mjs.map +1 -1
- package/build/components/Loading/PackageListSkeleton.d.ts +3 -0
- package/build/components/Loading/PackageListSkeleton.js +70 -0
- package/build/components/Loading/PackageListSkeleton.js.map +1 -0
- package/build/components/Loading/PackageListSkeleton.mjs +65 -0
- package/build/components/Loading/PackageListSkeleton.mjs.map +1 -0
- package/build/components/Loading/VersionSkeleton.d.ts +3 -0
- package/build/components/Loading/VersionSkeleton.js +119 -0
- package/build/components/Loading/VersionSkeleton.js.map +1 -0
- package/build/components/Loading/VersionSkeleton.mjs +111 -0
- package/build/components/Loading/VersionSkeleton.mjs.map +1 -0
- package/build/components/Loading/index.d.ts +2 -0
- package/build/components/Loading/index.js +4 -0
- package/build/components/Loading/index.mjs +4 -1
- package/build/components/Package/Package.js +5 -1
- package/build/components/Package/Package.js.map +1 -1
- package/build/components/Package/Package.mjs +6 -2
- package/build/components/Package/Package.mjs.map +1 -1
- package/build/components/Package/styles.d.ts +3 -0
- package/build/components/Package/styles.js +8 -0
- package/build/components/Package/styles.js.map +1 -1
- package/build/components/Package/styles.mjs +8 -1
- package/build/components/Package/styles.mjs.map +1 -1
- package/build/components/PackageList/PackageList.js +4 -4
- package/build/components/PackageList/PackageList.js.map +1 -1
- package/build/components/PackageList/PackageList.mjs +5 -5
- package/build/components/PackageList/PackageList.mjs.map +1 -1
- package/build/components/PackageList/PackageListToolbar.d.ts +15 -0
- package/build/components/PackageList/PackageListToolbar.js +127 -0
- package/build/components/PackageList/PackageListToolbar.js.map +1 -0
- package/build/components/PackageList/PackageListToolbar.mjs +119 -0
- package/build/components/PackageList/PackageListToolbar.mjs.map +1 -0
- package/build/components/PackageList/filterPackages.d.ts +16 -0
- package/build/components/PackageList/filterPackages.js +37 -0
- package/build/components/PackageList/filterPackages.js.map +1 -0
- package/build/components/PackageList/filterPackages.mjs +34 -0
- package/build/components/PackageList/filterPackages.mjs.map +1 -0
- package/build/components/RegistryInfoDialog/RegistryInfoDialog.js +18 -7
- package/build/components/RegistryInfoDialog/RegistryInfoDialog.js.map +1 -1
- package/build/components/RegistryInfoDialog/RegistryInfoDialog.mjs +18 -7
- package/build/components/RegistryInfoDialog/RegistryInfoDialog.mjs.map +1 -1
- package/build/components/RegistryInfoDialog/types.d.ts +1 -0
- package/build/components/Search/AutoComplete/AutoComplete.d.ts +3 -0
- package/build/components/Search/AutoComplete/AutoComplete.js +3 -1
- package/build/components/Search/AutoComplete/AutoComplete.js.map +1 -1
- package/build/components/Search/AutoComplete/AutoComplete.mjs +3 -1
- package/build/components/Search/AutoComplete/AutoComplete.mjs.map +1 -1
- package/build/components/Search/Search.js +28 -1
- package/build/components/Search/Search.js.map +1 -1
- package/build/components/Search/Search.mjs +31 -5
- package/build/components/Search/Search.mjs.map +1 -1
- package/build/components/Search/SearchItem.d.ts +12 -1
- package/build/components/Search/SearchItem.js +53 -70
- package/build/components/Search/SearchItem.js.map +1 -1
- package/build/components/Search/SearchItem.mjs +51 -67
- package/build/components/Search/SearchItem.mjs.map +1 -1
- package/build/components/Search/utils.d.ts +10 -0
- package/build/components/Search/utils.js +28 -1
- package/build/components/Search/utils.js.map +1 -1
- package/build/components/Search/utils.mjs +26 -2
- package/build/components/Search/utils.mjs.map +1 -1
- package/build/components/SettingsMenu/SettingsMenu.js +2 -2
- package/build/components/SettingsMenu/SettingsMenu.mjs +1 -1
- package/build/components/Versions/Versions.js +8 -2
- package/build/components/Versions/Versions.js.map +1 -1
- package/build/components/Versions/Versions.mjs +8 -2
- package/build/components/Versions/Versions.mjs.map +1 -1
- package/build/components/VisuallyHidden/index.d.ts +5 -0
- package/build/components/VisuallyHidden/index.js +17 -0
- package/build/components/VisuallyHidden/index.js.map +1 -0
- package/build/components/VisuallyHidden/index.mjs +15 -0
- package/build/components/VisuallyHidden/index.mjs.map +1 -0
- package/build/configuration.js +2 -1
- package/build/configuration.js.map +1 -1
- package/build/configuration.mjs +2 -1
- package/build/configuration.mjs.map +1 -1
- package/build/i18n/crowdin/ui.js +68 -11
- package/build/i18n/crowdin/ui.js.map +1 -1
- package/build/i18n/crowdin/ui.json +64 -11
- package/build/i18n/crowdin/ui.mjs +67 -12
- package/build/i18n/crowdin/ui.mjs.map +1 -1
- package/build/i18n/download_translations/cs-CZ/ui.js +68 -11
- package/build/i18n/download_translations/cs-CZ/ui.js.map +1 -1
- package/build/i18n/download_translations/cs-CZ/ui.json +64 -11
- package/build/i18n/download_translations/cs-CZ/ui.mjs +67 -12
- package/build/i18n/download_translations/cs-CZ/ui.mjs.map +1 -1
- package/build/i18n/download_translations/de-DE/ui.js +68 -11
- package/build/i18n/download_translations/de-DE/ui.js.map +1 -1
- package/build/i18n/download_translations/de-DE/ui.json +64 -11
- package/build/i18n/download_translations/de-DE/ui.mjs +67 -12
- package/build/i18n/download_translations/de-DE/ui.mjs.map +1 -1
- package/build/i18n/download_translations/es-ES/ui.js +68 -11
- package/build/i18n/download_translations/es-ES/ui.js.map +1 -1
- package/build/i18n/download_translations/es-ES/ui.json +64 -11
- package/build/i18n/download_translations/es-ES/ui.mjs +67 -12
- package/build/i18n/download_translations/es-ES/ui.mjs.map +1 -1
- package/build/i18n/download_translations/fr-FR/ui.js +68 -11
- package/build/i18n/download_translations/fr-FR/ui.js.map +1 -1
- package/build/i18n/download_translations/fr-FR/ui.json +64 -11
- package/build/i18n/download_translations/fr-FR/ui.mjs +67 -12
- package/build/i18n/download_translations/fr-FR/ui.mjs.map +1 -1
- package/build/i18n/download_translations/ga-IE/ui.js +68 -11
- package/build/i18n/download_translations/ga-IE/ui.js.map +1 -1
- package/build/i18n/download_translations/ga-IE/ui.json +64 -11
- package/build/i18n/download_translations/ga-IE/ui.mjs +67 -12
- package/build/i18n/download_translations/ga-IE/ui.mjs.map +1 -1
- package/build/i18n/download_translations/gl-ES/ui.js +68 -11
- package/build/i18n/download_translations/gl-ES/ui.js.map +1 -1
- package/build/i18n/download_translations/gl-ES/ui.json +64 -11
- package/build/i18n/download_translations/gl-ES/ui.mjs +67 -12
- package/build/i18n/download_translations/gl-ES/ui.mjs.map +1 -1
- package/build/i18n/download_translations/it-IT/ui.js +68 -11
- package/build/i18n/download_translations/it-IT/ui.js.map +1 -1
- package/build/i18n/download_translations/it-IT/ui.json +64 -11
- package/build/i18n/download_translations/it-IT/ui.mjs +67 -12
- package/build/i18n/download_translations/it-IT/ui.mjs.map +1 -1
- package/build/i18n/download_translations/ko-KR/ui.js +68 -11
- package/build/i18n/download_translations/ko-KR/ui.js.map +1 -1
- package/build/i18n/download_translations/ko-KR/ui.json +64 -11
- package/build/i18n/download_translations/ko-KR/ui.mjs +67 -12
- package/build/i18n/download_translations/ko-KR/ui.mjs.map +1 -1
- package/build/i18n/download_translations/pl-PL/ui.js +68 -11
- package/build/i18n/download_translations/pl-PL/ui.js.map +1 -1
- package/build/i18n/download_translations/pl-PL/ui.json +64 -11
- package/build/i18n/download_translations/pl-PL/ui.mjs +67 -12
- package/build/i18n/download_translations/pl-PL/ui.mjs.map +1 -1
- package/build/i18n/download_translations/pt-BR/ui.js +68 -11
- package/build/i18n/download_translations/pt-BR/ui.js.map +1 -1
- package/build/i18n/download_translations/pt-BR/ui.json +64 -11
- package/build/i18n/download_translations/pt-BR/ui.mjs +67 -12
- package/build/i18n/download_translations/pt-BR/ui.mjs.map +1 -1
- package/build/i18n/download_translations/ru-RU/ui.js +68 -11
- package/build/i18n/download_translations/ru-RU/ui.js.map +1 -1
- package/build/i18n/download_translations/ru-RU/ui.json +64 -11
- package/build/i18n/download_translations/ru-RU/ui.mjs +67 -12
- package/build/i18n/download_translations/ru-RU/ui.mjs.map +1 -1
- package/build/i18n/download_translations/sr-CS/ui.js +66 -12
- package/build/i18n/download_translations/sr-CS/ui.js.map +1 -1
- package/build/i18n/download_translations/sr-CS/ui.json +64 -11
- package/build/i18n/download_translations/sr-CS/ui.mjs +66 -13
- package/build/i18n/download_translations/sr-CS/ui.mjs.map +1 -1
- package/build/i18n/download_translations/tr-TR/ui.js +68 -11
- package/build/i18n/download_translations/tr-TR/ui.js.map +1 -1
- package/build/i18n/download_translations/tr-TR/ui.json +64 -11
- package/build/i18n/download_translations/tr-TR/ui.mjs +67 -12
- package/build/i18n/download_translations/tr-TR/ui.mjs.map +1 -1
- package/build/i18n/download_translations/vi-VN/ui.js +66 -12
- package/build/i18n/download_translations/vi-VN/ui.js.map +1 -1
- package/build/i18n/download_translations/vi-VN/ui.json +64 -11
- package/build/i18n/download_translations/vi-VN/ui.mjs +66 -13
- package/build/i18n/download_translations/vi-VN/ui.mjs.map +1 -1
- package/build/i18n/download_translations/yo-NG/ui.js +66 -12
- package/build/i18n/download_translations/yo-NG/ui.js.map +1 -1
- package/build/i18n/download_translations/yo-NG/ui.json +64 -11
- package/build/i18n/download_translations/yo-NG/ui.mjs +66 -13
- package/build/i18n/download_translations/yo-NG/ui.mjs.map +1 -1
- package/build/i18n/download_translations/zh-CN/ui.js +68 -11
- package/build/i18n/download_translations/zh-CN/ui.js.map +1 -1
- package/build/i18n/download_translations/zh-CN/ui.json +64 -11
- package/build/i18n/download_translations/zh-CN/ui.mjs +67 -12
- package/build/i18n/download_translations/zh-CN/ui.mjs.map +1 -1
- package/build/i18n/download_translations/zh-TW/ui.js +68 -11
- package/build/i18n/download_translations/zh-TW/ui.js.map +1 -1
- package/build/i18n/download_translations/zh-TW/ui.json +64 -11
- package/build/i18n/download_translations/zh-TW/ui.mjs +67 -12
- package/build/i18n/download_translations/zh-TW/ui.mjs.map +1 -1
- package/build/i18n/loadTranslationFile.d.ts +2 -2
- package/build/i18n/loadTranslationFile.js +2 -2
- package/build/i18n/loadTranslationFile.js.map +1 -1
- package/build/i18n/loadTranslationFile.mjs +2 -2
- package/build/i18n/loadTranslationFile.mjs.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +8 -0
- package/build/index.mjs +4 -2
- package/build/mockServiceWorker.js +1 -0
- package/build/pages/Version/Version.js +2 -2
- package/build/pages/Version/Version.js.map +1 -1
- package/build/pages/Version/Version.mjs +2 -2
- package/build/pages/Version/Version.mjs.map +1 -1
- package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js +3 -1
- package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js.map +1 -1
- package/build/providers/AppConfigurationProvider/AppConfigurationProvider.mjs +3 -1
- package/build/providers/AppConfigurationProvider/AppConfigurationProvider.mjs.map +1 -1
- package/build/providers/ManifestsProvider/ManifestsProvider.d.ts +3 -0
- package/build/providers/ManifestsProvider/ManifestsProvider.js +9 -2
- package/build/providers/ManifestsProvider/ManifestsProvider.js.map +1 -1
- package/build/providers/ManifestsProvider/ManifestsProvider.mjs +10 -4
- package/build/providers/ManifestsProvider/ManifestsProvider.mjs.map +1 -1
- package/build/sections/Detail/ContainerContent.js +8 -0
- package/build/sections/Detail/ContainerContent.js.map +1 -1
- package/build/sections/Detail/ContainerContent.mjs +8 -1
- package/build/sections/Detail/ContainerContent.mjs.map +1 -1
- package/build/sections/Detail/Detail.d.ts +3 -6
- package/build/sections/Detail/Detail.js +13 -14
- package/build/sections/Detail/Detail.js.map +1 -1
- package/build/sections/Detail/Detail.mjs +14 -15
- package/build/sections/Detail/Detail.mjs.map +1 -1
- package/build/sections/Detail/Tabs.d.ts +3 -2
- package/build/sections/Detail/Tabs.js +9 -4
- package/build/sections/Detail/Tabs.js.map +1 -1
- package/build/sections/Detail/Tabs.mjs +9 -4
- package/build/sections/Detail/Tabs.mjs.map +1 -1
- package/build/sections/Footer/Footer.js +24 -3
- package/build/sections/Footer/Footer.js.map +1 -1
- package/build/sections/Footer/Footer.mjs +24 -4
- package/build/sections/Footer/Footer.mjs.map +1 -1
- package/build/sections/Footer/styles.d.ts +6 -0
- package/build/sections/Footer/styles.js +21 -2
- package/build/sections/Footer/styles.js.map +1 -1
- package/build/sections/Footer/styles.mjs +21 -3
- package/build/sections/Footer/styles.mjs.map +1 -1
- package/build/sections/Header/HeaderSettingsDialog.js +39 -10
- package/build/sections/Header/HeaderSettingsDialog.js.map +1 -1
- package/build/sections/Header/HeaderSettingsDialog.mjs +39 -10
- package/build/sections/Header/HeaderSettingsDialog.mjs.map +1 -1
- package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.d.ts +1 -4
- package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.js +98 -15
- package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.js.map +1 -1
- package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.mjs +100 -15
- package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.mjs.map +1 -1
- package/build/sections/Home/Home.js +58 -2
- package/build/sections/Home/Home.js.map +1 -1
- package/build/sections/Home/Home.mjs +60 -4
- package/build/sections/Home/Home.mjs.map +1 -1
- package/build/utils/cli-utils.d.ts +10 -0
- package/build/utils/cli-utils.js +26 -0
- package/build/utils/cli-utils.js.map +1 -1
- package/build/utils/cli-utils.mjs +23 -1
- package/build/utils/cli-utils.mjs.map +1 -1
- package/build/utils/index.d.ts +1 -1
- package/build/utils/index.js +4 -0
- package/build/utils/index.mjs +2 -2
- package/build/utils/markdown.d.ts +6 -0
- package/build/utils/markdown.js +16 -0
- package/build/utils/markdown.js.map +1 -0
- package/build/utils/markdown.mjs +13 -0
- package/build/utils/markdown.mjs.map +1 -0
- package/package.json +8 -8
|
@@ -7,7 +7,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
|
|
|
7
7
|
let _mui_material_Autocomplete = require("@mui/material/Autocomplete");
|
|
8
8
|
_mui_material_Autocomplete = require_runtime.__toESM(_mui_material_Autocomplete);
|
|
9
9
|
//#region src/components/Search/AutoComplete/AutoComplete.tsx
|
|
10
|
-
var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false }) => {
|
|
10
|
+
var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false, groupBy, renderGroup }) => {
|
|
11
11
|
const { t } = (0, react_i18next.useTranslation)();
|
|
12
12
|
const [inputValue, setInputValue] = (0, react.useState)("");
|
|
13
13
|
const handleOnInputChange = (event, value, reason) => {
|
|
@@ -30,6 +30,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
|
|
|
30
30
|
filterOptions: (options, state) => state.inputValue.trim() ? options : [],
|
|
31
31
|
fullWidth: true,
|
|
32
32
|
getOptionLabel,
|
|
33
|
+
groupBy,
|
|
33
34
|
id: "search-header-suggest",
|
|
34
35
|
inputValue,
|
|
35
36
|
loading: suggestionsLoading,
|
|
@@ -40,6 +41,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
|
|
|
40
41
|
onInputChange: handleOnInputChange,
|
|
41
42
|
options: hasError ? [] : suggestions,
|
|
42
43
|
renderInput,
|
|
44
|
+
renderGroup,
|
|
43
45
|
renderOption,
|
|
44
46
|
renderTags: () => null
|
|
45
47
|
}) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoComplete.js","names":["useTranslation","useState","Wrapper","Autocomplete"],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"AutoComplete.js","names":["useTranslation","useState","Wrapper","Autocomplete"],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n groupBy?: (option: any) => string;\n renderGroup?: (params: AutocompleteRenderGroupParams) => React.ReactNode;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n groupBy,\n renderGroup,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n groupBy={groupBy}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderGroup={renderGroup}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;;;;AA+BA,IAAM,gBAA2B,EAC/B,cAAc,CAAC,GACf,oBACA,oBACA,aACA,cACA,gBACA,cACA,qBAAqB,OACrB,WAAW,OACX,SACA,kBACW;CACX,MAAM,EAAE,OAAA,GAAMA,cAAAA,eAAAA,CAAe;CAC7B,MAAM,CAAC,YAAY,kBAAA,GAAiBC,MAAAA,SAAAA,CAAS,EAAE;CAE/C,MAAM,uBAAuB,OAA6B,OAAe,WAAmB;EAC1F,IAAI,WAAW,SAAS;GACtB,MAAM,eAAe;GACrB,mBAAmB,EAAE,MAAM,CAAC;GAC5B,cAAc,KAAK;EACrB,OAAO,IAAI,WAAW,SAAS;GAC7B,mBAAmB,KAAK;GACxB,cAAc,EAAE;EAClB;CACF;CAEA,MAAM,iBAAiB,UAAU;EAC/B,mBAAmB,KAAK;EACxB,cAAc,EAAE;CAClB;CAGA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,eAAAA,SAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,IAAA,CAACC,2BAAAA,SAAD;EAEE,aAAa;EACb,eAAe;EACf,gBAAgB,SAAS,UAAW,MAAM,WAAW,KAAK,IAAI,UAAU,CAAC;EACzE,WAAW;EACK;EACP;EACT,IAAG;EACS;EACZ,SAAS;EACT,aAAa,EAAE,sBAAsB;EAErC,eAAe,WAAW,EAAE,oBAAoB,IAAI,EAAE,+BAA+B;EACrF,UAAU;EACV,SAAS;EACT,eAAe;EACf,SAAS,WAAW,CAAC,IAAI;EACZ;EACA;EACC;EACd,kBAAkB;CACnB,CAAA,EACM,CAAA;AAEb"}
|
|
@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
|
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
import Autocomplete from "@mui/material/Autocomplete";
|
|
6
6
|
//#region src/components/Search/AutoComplete/AutoComplete.tsx
|
|
7
|
-
var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false }) => {
|
|
7
|
+
var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions, renderInput, renderOption, getOptionLabel, onSelectItem, suggestionsLoading = false, hasError = false, groupBy, renderGroup }) => {
|
|
8
8
|
const { t } = useTranslation();
|
|
9
9
|
const [inputValue, setInputValue] = useState("");
|
|
10
10
|
const handleOnInputChange = (event, value, reason) => {
|
|
@@ -27,6 +27,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
|
|
|
27
27
|
filterOptions: (options, state) => state.inputValue.trim() ? options : [],
|
|
28
28
|
fullWidth: true,
|
|
29
29
|
getOptionLabel,
|
|
30
|
+
groupBy,
|
|
30
31
|
id: "search-header-suggest",
|
|
31
32
|
inputValue,
|
|
32
33
|
loading: suggestionsLoading,
|
|
@@ -37,6 +38,7 @@ var AutoComplete = ({ suggestions = [], onSuggestionsFetch, onCleanSuggestions,
|
|
|
37
38
|
onInputChange: handleOnInputChange,
|
|
38
39
|
options: hasError ? [] : suggestions,
|
|
39
40
|
renderInput,
|
|
41
|
+
renderGroup,
|
|
40
42
|
renderOption,
|
|
41
43
|
renderTags: () => null
|
|
42
44
|
}) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutoComplete.mjs","names":[],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"AutoComplete.mjs","names":[],"sources":["../../../../src/components/Search/AutoComplete/AutoComplete.tsx"],"sourcesContent":["import type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport type { FC } from 'react';\nimport React, { useState } from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport type { SearchResultWeb } from '@verdaccio/types';\n\nimport { Wrapper } from './styles';\n\nexport type OnSelecItem = (\n event: React.SyntheticEvent,\n value: SearchResultWeb,\n reason: string,\n details?: string\n) => void;\ninterface Props {\n suggestions?: SearchResultWeb[];\n suggestionsLoading?: boolean;\n hasError?: boolean;\n placeholder: string;\n renderOption?: (props: any, option: any) => React.JSX.Element;\n renderInput: (params: any) => React.JSX.Element;\n onSuggestionsFetch: any;\n getOptionLabel: (option: any) => any;\n onCleanSuggestions: (event: React.SyntheticEvent) => void;\n onSelectItem: OnSelecItem;\n groupBy?: (option: any) => string;\n renderGroup?: (params: AutocompleteRenderGroupParams) => React.ReactNode;\n}\n\nconst AutoComplete: FC<Props> = ({\n suggestions = [],\n onSuggestionsFetch,\n onCleanSuggestions,\n renderInput,\n renderOption,\n getOptionLabel,\n onSelectItem,\n suggestionsLoading = false,\n hasError = false,\n groupBy,\n renderGroup,\n}: Props) => {\n const { t } = useTranslation();\n const [inputValue, setInputValue] = useState('');\n\n const handleOnInputChange = (event: React.SyntheticEvent, value: string, reason: string) => {\n if (reason === 'input') {\n event.preventDefault();\n onSuggestionsFetch({ value });\n setInputValue(value);\n } else if (reason === 'clear') {\n onCleanSuggestions(event);\n setInputValue('');\n }\n };\n\n const handleOnClose = (event) => {\n onCleanSuggestions(event);\n setInputValue('');\n };\n\n // @ts-ignore\n return (\n <Wrapper>\n <Autocomplete\n /* @ts-ignore */\n clearOnBlur={true}\n disablePortal={true}\n filterOptions={(options, state) => (state.inputValue.trim() ? options : [])}\n fullWidth={true}\n getOptionLabel={getOptionLabel}\n groupBy={groupBy}\n id=\"search-header-suggest\"\n inputValue={inputValue}\n loading={suggestionsLoading}\n loadingText={t('autoComplete.loading')}\n // a failed search must not read as \"no results found\"\n noOptionsText={hasError ? t('autoComplete.error') : t('autoComplete.no-results-found')}\n onChange={onSelectItem as any}\n onClose={handleOnClose}\n onInputChange={handleOnInputChange}\n options={hasError ? [] : suggestions}\n renderInput={renderInput}\n renderGroup={renderGroup}\n renderOption={renderOption}\n renderTags={() => null}\n />\n </Wrapper>\n );\n};\n\nexport default AutoComplete;\n"],"mappings":";;;;;;AA+BA,IAAM,gBAA2B,EAC/B,cAAc,CAAC,GACf,oBACA,oBACA,aACA,cACA,gBACA,cACA,qBAAqB,OACrB,WAAW,OACX,SACA,kBACW;CACX,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,CAAC,YAAY,iBAAiB,SAAS,EAAE;CAE/C,MAAM,uBAAuB,OAA6B,OAAe,WAAmB;EAC1F,IAAI,WAAW,SAAS;GACtB,MAAM,eAAe;GACrB,mBAAmB,EAAE,MAAM,CAAC;GAC5B,cAAc,KAAK;EACrB,OAAO,IAAI,WAAW,SAAS;GAC7B,mBAAmB,KAAK;GACxB,cAAc,EAAE;EAClB;CACF;CAEA,MAAM,iBAAiB,UAAU;EAC/B,mBAAmB,KAAK;EACxB,cAAc,EAAE;CAClB;CAGA,OACE,oBAAC,SAAD,EAAA,UACE,oBAAC,cAAD;EAEE,aAAa;EACb,eAAe;EACf,gBAAgB,SAAS,UAAW,MAAM,WAAW,KAAK,IAAI,UAAU,CAAC;EACzE,WAAW;EACK;EACP;EACT,IAAG;EACS;EACZ,SAAS;EACT,aAAa,EAAE,sBAAsB;EAErC,eAAe,WAAW,EAAE,oBAAoB,IAAI,EAAE,+BAA+B;EACrF,UAAU;EACV,SAAS;EACT,eAAe;EACf,SAAS,WAAW,CAAC,IAAI;EACZ;EACA;EACC;EACd,kBAAkB;CACnB,CAAA,EACM,CAAA;AAEb"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const require_runtime = require("../../_virtual/_rolldown/runtime.js");
|
|
2
2
|
const require_routes = require("../../utils/routes.js");
|
|
3
3
|
require("../../utils/index.js");
|
|
4
|
+
const require_AppConfigurationProvider = require("../../providers/AppConfigurationProvider/AppConfigurationProvider.js");
|
|
4
5
|
const require_SearchProvider = require("../../providers/SearchProvider/SearchProvider.js");
|
|
5
6
|
const require_AutoComplete = require("./AutoComplete/AutoComplete.js");
|
|
6
7
|
require("./AutoComplete/index.js");
|
|
@@ -16,6 +17,8 @@ let lodash_es = require("lodash-es");
|
|
|
16
17
|
let react_router = require("react-router");
|
|
17
18
|
let _mui_icons_material_Search = require("@mui/icons-material/Search");
|
|
18
19
|
_mui_icons_material_Search = require_runtime.__toESM(_mui_icons_material_Search);
|
|
20
|
+
let _mui_material_ListSubheader = require("@mui/material/ListSubheader");
|
|
21
|
+
_mui_material_ListSubheader = require_runtime.__toESM(_mui_material_ListSubheader);
|
|
19
22
|
//#region src/components/Search/Search.tsx
|
|
20
23
|
var CONSTANTS = {
|
|
21
24
|
API_DELAY: 300,
|
|
@@ -25,6 +28,9 @@ var Search = () => {
|
|
|
25
28
|
const { t } = (0, react_i18next.useTranslation)();
|
|
26
29
|
const navigate = (0, react_router.useNavigate)();
|
|
27
30
|
const { searchResults, isLoading, isError, doSearch, resetSearch } = require_SearchProvider.useSearch();
|
|
31
|
+
const { configOptions } = require_AppConfigurationProvider.useConfig();
|
|
32
|
+
const groupByOrigin = configOptions?.showUplinks === true;
|
|
33
|
+
const suggestions = (0, react.useMemo)(() => groupByOrigin && searchResults ? require_utils.sortByOrigin(searchResults) : searchResults, [groupByOrigin, searchResults]);
|
|
28
34
|
const abortControllerRef = (0, react.useRef)(null);
|
|
29
35
|
const cancelAllSearchRequests = (0, react.useCallback)(() => {
|
|
30
36
|
if (abortControllerRef.current) {
|
|
@@ -107,19 +113,40 @@ var Search = () => {
|
|
|
107
113
|
variant: "standard"
|
|
108
114
|
});
|
|
109
115
|
};
|
|
116
|
+
const getOptionGroup = (option) => require_utils.normalizeSearchOption(option).origin ?? "";
|
|
117
|
+
const renderGroup = ({ key, group, children }) => {
|
|
118
|
+
if (!group) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.default.Fragment, { children }, key);
|
|
119
|
+
const OriginIcon = require_SearchItem.ORIGIN_ICONS[group];
|
|
120
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_mui_material_ListSubheader.default, {
|
|
121
|
+
component: "div",
|
|
122
|
+
"data-testid": `search-group-${group}`,
|
|
123
|
+
sx: {
|
|
124
|
+
display: "flex",
|
|
125
|
+
alignItems: "center",
|
|
126
|
+
gap: 1,
|
|
127
|
+
lineHeight: "36px"
|
|
128
|
+
},
|
|
129
|
+
children: [OriginIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OriginIcon, { fontSize: "small" }), t(`search.group.${group}`, { count: react.default.Children.count(children) })]
|
|
130
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
131
|
+
style: { padding: 0 },
|
|
132
|
+
children
|
|
133
|
+
})] }, key);
|
|
134
|
+
};
|
|
110
135
|
const getOptionLabel = (option) => {
|
|
111
136
|
return require_utils.normalizeSearchOption(option).name;
|
|
112
137
|
};
|
|
113
138
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_AutoComplete.default, {
|
|
114
139
|
getOptionLabel,
|
|
140
|
+
groupBy: groupByOrigin ? getOptionGroup : void 0,
|
|
115
141
|
hasError: isError,
|
|
116
142
|
onCleanSuggestions: handleOnBlur,
|
|
117
143
|
onSelectItem: handleClickSearch,
|
|
118
144
|
onSuggestionsFetch: handleSuggestionsFetch,
|
|
119
145
|
placeholder: t("search.packages"),
|
|
146
|
+
renderGroup: groupByOrigin ? renderGroup : void 0,
|
|
120
147
|
renderInput,
|
|
121
148
|
renderOption,
|
|
122
|
-
suggestions
|
|
149
|
+
suggestions,
|
|
123
150
|
suggestionsLoading: isLoading || isDebouncing
|
|
124
151
|
});
|
|
125
152
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Search.js","names":["useTranslation","useNavigate","useSearch","useRef","useCallback","normalizeSearchOption","Route","useState","useMemo","debounce","SearchItem","StyledTextField","StyledInputAdornment","SearchMui","AutoComplete"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport { normalizeSearchOption } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={searchResults}\n suggestionsLoading={isLoading || isDebouncing}\n />\n );\n};\n\nexport default Search;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Search.js","names":["useTranslation","useNavigate","useSearch","useConfig","useMemo","sortByOrigin","useRef","useCallback","normalizeSearchOption","Route","useState","debounce","SearchItem","StyledTextField","StyledInputAdornment","SearchMui","React","ORIGIN_ICONS","ListSubheader","AutoComplete"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport ListSubheader from '@mui/material/ListSubheader';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useConfig, useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem, { ORIGIN_ICONS } from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport type { SearchOrigin } from './utils';\nimport { normalizeSearchOption, sortByOrigin } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n const { configOptions } = useConfig();\n const groupByOrigin = configOptions?.showUplinks === true;\n const suggestions = useMemo(\n () => (groupByOrigin && searchResults ? sortByOrigin(searchResults) : searchResults),\n [groupByOrigin, searchResults]\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionGroup = (option) => normalizeSearchOption(option).origin ?? '';\n\n const renderGroup = ({ key, group, children }: AutocompleteRenderGroupParams) => {\n if (!group) {\n return <React.Fragment key={key}>{children}</React.Fragment>;\n }\n const OriginIcon = ORIGIN_ICONS[group as SearchOrigin];\n return (\n <li key={key}>\n {/* a div: the default <li> would nest a list item inside the group's <li> */}\n <ListSubheader\n component=\"div\"\n data-testid={`search-group-${group}`}\n sx={{ display: 'flex', alignItems: 'center', gap: 1, lineHeight: '36px' }}\n >\n {OriginIcon && <OriginIcon fontSize=\"small\" />}\n {t(`search.group.${group}`, { count: React.Children.count(children) })}\n </ListSubheader>\n <ul style={{ padding: 0 }}>{children}</ul>\n </li>\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n groupBy={groupByOrigin ? getOptionGroup : undefined}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderGroup={groupByOrigin ? renderGroup : undefined}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={suggestions}\n suggestionsLoading={isLoading || isDebouncing}\n />\n );\n};\n\nexport default Search;\n"],"mappings":"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"}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { Route as Route$1 } from "../../utils/routes.mjs";
|
|
2
2
|
import "../../utils/index.mjs";
|
|
3
|
+
import { useConfig } from "../../providers/AppConfigurationProvider/AppConfigurationProvider.mjs";
|
|
3
4
|
import { useSearch } from "../../providers/SearchProvider/SearchProvider.mjs";
|
|
4
5
|
import AutoComplete from "./AutoComplete/AutoComplete.mjs";
|
|
5
6
|
import "./AutoComplete/index.mjs";
|
|
6
|
-
import { normalizeSearchOption } from "./utils.mjs";
|
|
7
|
-
import SearchItem from "./SearchItem.mjs";
|
|
7
|
+
import { normalizeSearchOption, sortByOrigin } from "./utils.mjs";
|
|
8
|
+
import SearchItem, { ORIGIN_ICONS } from "./SearchItem.mjs";
|
|
8
9
|
import { StyledInputAdornment, StyledTextField } from "./styles.mjs";
|
|
9
10
|
import "../../index.mjs";
|
|
10
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
12
|
import { useTranslation } from "react-i18next";
|
|
12
|
-
import { jsx } from "react/jsx-runtime";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
13
14
|
import { debounce } from "lodash-es";
|
|
14
15
|
import { useNavigate } from "react-router";
|
|
15
16
|
import SearchMui from "@mui/icons-material/Search";
|
|
17
|
+
import ListSubheader from "@mui/material/ListSubheader";
|
|
16
18
|
//#region src/components/Search/Search.tsx
|
|
17
19
|
var CONSTANTS = {
|
|
18
20
|
API_DELAY: 300,
|
|
@@ -22,6 +24,9 @@ var Search = () => {
|
|
|
22
24
|
const { t } = useTranslation();
|
|
23
25
|
const navigate = useNavigate();
|
|
24
26
|
const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();
|
|
27
|
+
const { configOptions } = useConfig();
|
|
28
|
+
const groupByOrigin = configOptions?.showUplinks === true;
|
|
29
|
+
const suggestions = useMemo(() => groupByOrigin && searchResults ? sortByOrigin(searchResults) : searchResults, [groupByOrigin, searchResults]);
|
|
25
30
|
const abortControllerRef = useRef(null);
|
|
26
31
|
const cancelAllSearchRequests = useCallback(() => {
|
|
27
32
|
if (abortControllerRef.current) {
|
|
@@ -104,19 +109,40 @@ var Search = () => {
|
|
|
104
109
|
variant: "standard"
|
|
105
110
|
});
|
|
106
111
|
};
|
|
112
|
+
const getOptionGroup = (option) => normalizeSearchOption(option).origin ?? "";
|
|
113
|
+
const renderGroup = ({ key, group, children }) => {
|
|
114
|
+
if (!group) return /* @__PURE__ */ jsx(React.Fragment, { children }, key);
|
|
115
|
+
const OriginIcon = ORIGIN_ICONS[group];
|
|
116
|
+
return /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsxs(ListSubheader, {
|
|
117
|
+
component: "div",
|
|
118
|
+
"data-testid": `search-group-${group}`,
|
|
119
|
+
sx: {
|
|
120
|
+
display: "flex",
|
|
121
|
+
alignItems: "center",
|
|
122
|
+
gap: 1,
|
|
123
|
+
lineHeight: "36px"
|
|
124
|
+
},
|
|
125
|
+
children: [OriginIcon && /* @__PURE__ */ jsx(OriginIcon, { fontSize: "small" }), t(`search.group.${group}`, { count: React.Children.count(children) })]
|
|
126
|
+
}), /* @__PURE__ */ jsx("ul", {
|
|
127
|
+
style: { padding: 0 },
|
|
128
|
+
children
|
|
129
|
+
})] }, key);
|
|
130
|
+
};
|
|
107
131
|
const getOptionLabel = (option) => {
|
|
108
132
|
return normalizeSearchOption(option).name;
|
|
109
133
|
};
|
|
110
134
|
return /* @__PURE__ */ jsx(AutoComplete, {
|
|
111
135
|
getOptionLabel,
|
|
136
|
+
groupBy: groupByOrigin ? getOptionGroup : void 0,
|
|
112
137
|
hasError: isError,
|
|
113
138
|
onCleanSuggestions: handleOnBlur,
|
|
114
139
|
onSelectItem: handleClickSearch,
|
|
115
140
|
onSuggestionsFetch: handleSuggestionsFetch,
|
|
116
141
|
placeholder: t("search.packages"),
|
|
142
|
+
renderGroup: groupByOrigin ? renderGroup : void 0,
|
|
117
143
|
renderInput,
|
|
118
144
|
renderOption,
|
|
119
|
-
suggestions
|
|
145
|
+
suggestions,
|
|
120
146
|
suggestionsLoading: isLoading || isDebouncing
|
|
121
147
|
});
|
|
122
148
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Search.mjs","names":["Route"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport { normalizeSearchOption } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={
|
|
1
|
+
{"version":3,"file":"Search.mjs","names":["Route"],"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["import SearchMui from '@mui/icons-material/Search';\nimport type { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete';\nimport ListSubheader from '@mui/material/ListSubheader';\nimport { debounce } from 'lodash-es';\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { useConfig, useSearch } from '../../';\nimport { Route } from '../../utils';\nimport AutoComplete from './AutoComplete';\nimport SearchItem, { ORIGIN_ICONS } from './SearchItem';\nimport { StyledInputAdornment, StyledTextField } from './styles';\nimport type { SearchOrigin } from './utils';\nimport { normalizeSearchOption, sortByOrigin } from './utils';\n\nconst CONSTANTS = {\n API_DELAY: 300,\n ABORT_ERROR: 'AbortError',\n};\n\nconst Search: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const { searchResults, isLoading, isError, doSearch, resetSearch } = useSearch();\n const { configOptions } = useConfig();\n const groupByOrigin = configOptions?.showUplinks === true;\n const suggestions = useMemo(\n () => (groupByOrigin && searchResults ? sortByOrigin(searchResults) : searchResults),\n [groupByOrigin, searchResults]\n );\n\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const cancelAllSearchRequests = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n abortControllerRef.current = null;\n }\n }, []);\n\n const handleOnBlur = useCallback(\n (event: React.SyntheticEvent) => {\n event.stopPropagation();\n cancelAllSearchRequests();\n },\n [cancelAllSearchRequests]\n );\n\n const handleClickSearch = useCallback(\n (event: React.SyntheticEvent, value: any, reason: string): void => {\n event.stopPropagation();\n if (reason === 'selectOption') {\n const { name } = normalizeSearchOption(value);\n if (name) {\n navigate(`${Route.DETAIL}${name}`);\n }\n }\n },\n [navigate]\n );\n\n // Use a ref to always access the latest doSearch without re-creating the debounced function\n const doSearchRef = useRef(doSearch);\n doSearchRef.current = doSearch;\n\n // shows the dropdown as loading during the debounce window; without it the\n // immediate reset below reads as \"no results found\" on every keystroke\n const [isDebouncing, setIsDebouncing] = useState(false);\n\n /**\n * Stable fetch function that reads the latest doSearch from a ref,\n * avoiding dependency changes that would break the debounce.\n */\n const handleFetchPackages = useCallback(\n async ({ value }: { value: string }) => {\n setIsDebouncing(false);\n if (value?.trim() !== '') {\n // Abort any previous pending request before starting a new one\n cancelAllSearchRequests();\n\n // Create a new controller for the current request\n const controller = new AbortController();\n abortControllerRef.current = controller;\n\n try {\n await doSearchRef.current?.({\n text: value,\n signal: controller.signal,\n });\n } catch (err: any) {\n if (err.name === CONSTANTS.ABORT_ERROR) {\n console.warn('Search request aborted');\n } else {\n console.error('Search error:', err);\n }\n }\n }\n },\n [cancelAllSearchRequests]\n );\n\n // Memoize the debounced function so a single instance is reused across renders,\n // ensuring the debounce timer works correctly instead of creating a new timer per render.\n const debouncedFetch = useMemo(\n () => debounce(handleFetchPackages, CONSTANTS.API_DELAY),\n [handleFetchPackages]\n );\n\n // clear the previous query's results right away so the dropdown never lists\n // stale suggestions under the new input while the debounce timer runs\n const handleSuggestionsFetch = useCallback(\n ({ value }: { value: string }) => {\n resetSearch?.();\n if (value?.trim() !== '') {\n setIsDebouncing(true);\n }\n debouncedFetch({ value });\n },\n [resetSearch, debouncedFetch]\n );\n\n useEffect(() => {\n return () => {\n debouncedFetch.cancel?.();\n cancelAllSearchRequests();\n };\n }, [debouncedFetch, cancelAllSearchRequests]);\n\n const renderOption = (props, option) => {\n const { key, ...otherProps } = props;\n const { name, version, description, isPrivate, isCached, isRemote } =\n normalizeSearchOption(option);\n return (\n <SearchItem\n key={key}\n {...otherProps}\n description={description}\n isCached={isCached}\n isPrivate={isPrivate}\n isRemote={isRemote}\n name={name}\n version={version}\n />\n );\n };\n\n const renderInput = (params) => {\n return (\n <StyledTextField\n {...params}\n InputProps={{\n ...params.InputProps,\n startAdornment: (\n <StyledInputAdornment position=\"start\">\n <SearchMui />\n </StyledInputAdornment>\n ),\n }}\n label=\"\"\n placeholder={t('search.packages')}\n variant=\"standard\"\n />\n );\n };\n\n const getOptionGroup = (option) => normalizeSearchOption(option).origin ?? '';\n\n const renderGroup = ({ key, group, children }: AutocompleteRenderGroupParams) => {\n if (!group) {\n return <React.Fragment key={key}>{children}</React.Fragment>;\n }\n const OriginIcon = ORIGIN_ICONS[group as SearchOrigin];\n return (\n <li key={key}>\n {/* a div: the default <li> would nest a list item inside the group's <li> */}\n <ListSubheader\n component=\"div\"\n data-testid={`search-group-${group}`}\n sx={{ display: 'flex', alignItems: 'center', gap: 1, lineHeight: '36px' }}\n >\n {OriginIcon && <OriginIcon fontSize=\"small\" />}\n {t(`search.group.${group}`, { count: React.Children.count(children) })}\n </ListSubheader>\n <ul style={{ padding: 0 }}>{children}</ul>\n </li>\n );\n };\n\n const getOptionLabel = (option) => {\n return normalizeSearchOption(option).name;\n };\n\n return (\n <AutoComplete\n getOptionLabel={getOptionLabel}\n groupBy={groupByOrigin ? getOptionGroup : undefined}\n hasError={isError}\n onCleanSuggestions={handleOnBlur}\n onSelectItem={handleClickSearch}\n onSuggestionsFetch={handleSuggestionsFetch}\n placeholder={t('search.packages')}\n renderGroup={groupByOrigin ? renderGroup : undefined}\n renderInput={renderInput}\n renderOption={renderOption}\n suggestions={suggestions}\n suggestionsLoading={isLoading || isDebouncing}\n />\n );\n};\n\nexport default Search;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAgBA,IAAM,YAAY;CAChB,WAAW;CACX,aAAa;AACf;AAEA,IAAM,eAAyB;CAC7B,MAAM,EAAE,MAAM,eAAe;CAC7B,MAAM,WAAW,YAAY;CAC7B,MAAM,EAAE,eAAe,WAAW,SAAS,UAAU,gBAAgB,UAAU;CAC/E,MAAM,EAAE,kBAAkB,UAAU;CACpC,MAAM,gBAAgB,eAAe,gBAAgB;CACrD,MAAM,cAAc,cACX,iBAAiB,gBAAgB,aAAa,aAAa,IAAI,eACtE,CAAC,eAAe,aAAa,CAC/B;CAEA,MAAM,qBAAqB,OAA+B,IAAI;CAE9D,MAAM,0BAA0B,kBAAkB;EAChD,IAAI,mBAAmB,SAAS;GAC9B,mBAAmB,QAAQ,MAAM;GACjC,mBAAmB,UAAU;EAC/B;CACF,GAAG,CAAC,CAAC;CAEL,MAAM,eAAe,aAClB,UAAgC;EAC/B,MAAM,gBAAgB;EACtB,wBAAwB;CAC1B,GACA,CAAC,uBAAuB,CAC1B;CAEA,MAAM,oBAAoB,aACvB,OAA6B,OAAY,WAAyB;EACjE,MAAM,gBAAgB;EACtB,IAAI,WAAW,gBAAgB;GAC7B,MAAM,EAAE,SAAS,sBAAsB,KAAK;GAC5C,IAAI,MACF,SAAS,GAAGA,QAAM,SAAS,MAAM;EAErC;CACF,GACA,CAAC,QAAQ,CACX;CAGA,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CAItB,MAAM,CAAC,cAAc,mBAAmB,SAAS,KAAK;;;;;CAMtD,MAAM,sBAAsB,YAC1B,OAAO,EAAE,YAA+B;EACtC,gBAAgB,KAAK;EACrB,IAAI,OAAO,KAAK,MAAM,IAAI;GAExB,wBAAwB;GAGxB,MAAM,aAAa,IAAI,gBAAgB;GACvC,mBAAmB,UAAU;GAE7B,IAAI;IACF,MAAM,YAAY,UAAU;KAC1B,MAAM;KACN,QAAQ,WAAW;IACrB,CAAC;GACH,SAAS,KAAU;IACjB,IAAI,IAAI,SAAS,UAAU,aACzB,QAAQ,KAAK,wBAAwB;SAErC,QAAQ,MAAM,iBAAiB,GAAG;GAEtC;EACF;CACF,GACA,CAAC,uBAAuB,CAC1B;CAIA,MAAM,iBAAiB,cACf,SAAS,qBAAqB,UAAU,SAAS,GACvD,CAAC,mBAAmB,CACtB;CAIA,MAAM,yBAAyB,aAC5B,EAAE,YAA+B;EAChC,cAAc;EACd,IAAI,OAAO,KAAK,MAAM,IACpB,gBAAgB,IAAI;EAEtB,eAAe,EAAE,MAAM,CAAC;CAC1B,GACA,CAAC,aAAa,cAAc,CAC9B;CAEA,gBAAgB;EACd,aAAa;GACX,eAAe,SAAS;GACxB,wBAAwB;EAC1B;CACF,GAAG,CAAC,gBAAgB,uBAAuB,CAAC;CAE5C,MAAM,gBAAgB,OAAO,WAAW;EACtC,MAAM,EAAE,KAAK,GAAG,eAAe;EAC/B,MAAM,EAAE,MAAM,SAAS,aAAa,WAAW,UAAU,aACvD,sBAAsB,MAAM;EAC9B,OACE,oBAAC,YAAD;GAEE,GAAI;GACS;GACH;GACC;GACD;GACJ;GACG;EACV,GARM,GAQN;CAEL;CAEA,MAAM,eAAe,WAAW;EAC9B,OACE,oBAAC,iBAAD;GACE,GAAI;GACJ,YAAY;IACV,GAAG,OAAO;IACV,gBACE,oBAAC,sBAAD;KAAsB,UAAS;KAC7B,UAAA,oBAAC,WAAD,CAAY,CAAA;IACQ,CAAA;GAE1B;GACA,OAAM;GACN,aAAa,EAAE,iBAAiB;GAChC,SAAQ;EACT,CAAA;CAEL;CAEA,MAAM,kBAAkB,WAAW,sBAAsB,MAAM,CAAC,CAAC,UAAU;CAE3E,MAAM,eAAe,EAAE,KAAK,OAAO,eAA8C;EAC/E,IAAI,CAAC,OACH,OAAO,oBAAC,MAAM,UAAP,EAA2B,SAAyB,GAA/B,GAA+B;EAE7D,MAAM,aAAa,aAAa;EAChC,OACE,qBAAC,MAAD,EAAA,UAAA,CAEE,qBAAC,eAAD;GACE,WAAU;GACV,eAAa,gBAAgB;GAC7B,IAAI;IAAE,SAAS;IAAQ,YAAY;IAAU,KAAK;IAAG,YAAY;GAAO;GAH1E,UAAA,CAKG,cAAc,oBAAC,YAAD,EAAY,UAAS,QAAS,CAAA,GAC5C,EAAE,gBAAgB,SAAS,EAAE,OAAO,MAAM,SAAS,MAAM,QAAQ,EAAE,CAAC,CACxD;EACf,CAAA,GAAA,oBAAC,MAAD;GAAI,OAAO,EAAE,SAAS,EAAE;GAAI;EAAa,CAAA,CACvC,EAAA,GAXK,GAWL;CAER;CAEA,MAAM,kBAAkB,WAAW;EACjC,OAAO,sBAAsB,MAAM,CAAC,CAAC;CACvC;CAEA,OACE,oBAAC,cAAD;EACkB;EAChB,SAAS,gBAAgB,iBAAiB,KAAA;EAC1C,UAAU;EACV,oBAAoB;EACpB,cAAc;EACd,oBAAoB;EACpB,aAAa,EAAE,iBAAiB;EAChC,aAAa,gBAAgB,cAAc,KAAA;EAC9B;EACC;EACD;EACb,oBAAoB,aAAa;CAClC,CAAA;AAEL"}
|
|
@@ -8,11 +8,22 @@ type SearchItemProps = {
|
|
|
8
8
|
isCached?: boolean;
|
|
9
9
|
isRemote?: boolean;
|
|
10
10
|
};
|
|
11
|
+
export declare const ORIGIN_ICONS: {
|
|
12
|
+
private: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
|
|
13
|
+
muiName: string;
|
|
14
|
+
};
|
|
15
|
+
cached: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
|
|
16
|
+
muiName: string;
|
|
17
|
+
};
|
|
18
|
+
remote: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
|
|
19
|
+
muiName: string;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
11
22
|
export declare const Description: import("@emotion/styled").StyledComponent<{
|
|
12
23
|
theme?: import("@emotion/react").Theme;
|
|
13
24
|
as?: React.ElementType;
|
|
14
25
|
} & {
|
|
15
26
|
theme?: Theme;
|
|
16
|
-
}, React.DetailedHTMLProps<React.HTMLAttributes<
|
|
27
|
+
}, React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
|
|
17
28
|
declare const SearchItem: React.FC<SearchItemProps>;
|
|
18
29
|
export default SearchItem;
|
|
@@ -8,92 +8,75 @@ let react = require("react");
|
|
|
8
8
|
react = require_runtime.__toESM(react);
|
|
9
9
|
let react_i18next = require("react-i18next");
|
|
10
10
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
|
-
let
|
|
12
|
-
|
|
13
|
-
let
|
|
14
|
-
|
|
15
|
-
let
|
|
16
|
-
|
|
17
|
-
let _mui_icons_material_Https = require("@mui/icons-material/Https");
|
|
18
|
-
_mui_icons_material_Https = require_runtime.__toESM(_mui_icons_material_Https);
|
|
19
|
-
let _mui_icons_material_SyncAlt = require("@mui/icons-material/SyncAlt");
|
|
20
|
-
_mui_icons_material_SyncAlt = require_runtime.__toESM(_mui_icons_material_SyncAlt);
|
|
11
|
+
let _mui_icons_material_LockOutlined = require("@mui/icons-material/LockOutlined");
|
|
12
|
+
_mui_icons_material_LockOutlined = require_runtime.__toESM(_mui_icons_material_LockOutlined);
|
|
13
|
+
let _mui_icons_material_CloudOutlined = require("@mui/icons-material/CloudOutlined");
|
|
14
|
+
_mui_icons_material_CloudOutlined = require_runtime.__toESM(_mui_icons_material_CloudOutlined);
|
|
15
|
+
let _mui_icons_material_Inventory2Outlined = require("@mui/icons-material/Inventory2Outlined");
|
|
16
|
+
_mui_icons_material_Inventory2Outlined = require_runtime.__toESM(_mui_icons_material_Inventory2Outlined);
|
|
21
17
|
//#region src/components/Search/SearchItem.tsx
|
|
22
|
-
var
|
|
18
|
+
var ORIGIN_ICONS = {
|
|
19
|
+
[require_utils.SearchOrigin.PRIVATE]: _mui_icons_material_LockOutlined.default,
|
|
20
|
+
[require_utils.SearchOrigin.CACHED]: _mui_icons_material_Inventory2Outlined.default,
|
|
21
|
+
[require_utils.SearchOrigin.REMOTE]: _mui_icons_material_CloudOutlined.default
|
|
22
|
+
};
|
|
23
|
+
var Row = (0, _emotion_styled.default)("div")({
|
|
23
24
|
display: "flex",
|
|
24
25
|
alignItems: "center",
|
|
25
|
-
|
|
26
|
+
gap: 12,
|
|
27
|
+
width: "100%",
|
|
28
|
+
minWidth: 0
|
|
26
29
|
});
|
|
27
|
-
var
|
|
28
|
-
display: "
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
overflow: "hidden",
|
|
35
|
-
paddingLeft: theme.spacing(),
|
|
36
|
-
fontSize: theme.fontSize.ssm,
|
|
37
|
-
[`@media (min-width: ${theme.breakPoints.medium}px)`]: {
|
|
38
|
-
display: "block",
|
|
39
|
-
width: "300px"
|
|
40
|
-
},
|
|
41
|
-
[`@media (min-width: ${theme.breakPoints.large}px)`]: {
|
|
42
|
-
display: "block",
|
|
43
|
-
width: "500px"
|
|
44
|
-
},
|
|
45
|
-
[`@media (min-width: 1440px)`]: {
|
|
46
|
-
display: "block",
|
|
47
|
-
width: "600px"
|
|
48
|
-
}
|
|
49
|
-
}));
|
|
50
|
-
var NameGroup = _emotion_styled.default.span({
|
|
30
|
+
var Text = (0, _emotion_styled.default)("div")({
|
|
31
|
+
display: "flex",
|
|
32
|
+
flexDirection: "column",
|
|
33
|
+
flex: 1,
|
|
34
|
+
minWidth: 0
|
|
35
|
+
});
|
|
36
|
+
var TitleLine = (0, _emotion_styled.default)("div")({
|
|
51
37
|
display: "flex",
|
|
52
|
-
|
|
38
|
+
alignItems: "baseline",
|
|
39
|
+
gap: 8
|
|
53
40
|
});
|
|
54
41
|
var Name = (0, _emotion_styled.default)("span")(({ theme }) => ({
|
|
55
|
-
fontWeight:
|
|
56
|
-
fontSize: theme.fontSize.sm
|
|
42
|
+
fontWeight: 700,
|
|
43
|
+
fontSize: theme.fontSize.sm,
|
|
44
|
+
overflow: "hidden",
|
|
45
|
+
textOverflow: "ellipsis",
|
|
46
|
+
whiteSpace: "nowrap"
|
|
47
|
+
}));
|
|
48
|
+
var Version = (0, _emotion_styled.default)("span")(({ theme }) => ({
|
|
49
|
+
marginLeft: "auto",
|
|
50
|
+
flexShrink: 0,
|
|
51
|
+
fontSize: theme.fontSize.ssm,
|
|
52
|
+
color: theme.palette.text.secondary
|
|
53
|
+
}));
|
|
54
|
+
var Description = (0, _emotion_styled.default)("span")(({ theme }) => ({
|
|
55
|
+
color: theme.palette.text.secondary,
|
|
56
|
+
fontSize: theme.fontSize.ssm,
|
|
57
|
+
lineHeight: 1.5,
|
|
58
|
+
overflow: "hidden",
|
|
59
|
+
textOverflow: "ellipsis",
|
|
60
|
+
whiteSpace: "nowrap"
|
|
57
61
|
}));
|
|
58
|
-
var Version = (0, _emotion_styled.default)("span")(({ theme }) => ({ fontSize: theme.fontSize.ssm }));
|
|
59
62
|
var SearchItem = ({ name, description, isPrivate = false, isRemote = false, isCached = false, version, ...props }) => {
|
|
60
63
|
const { t } = (0, react_i18next.useTranslation)();
|
|
61
64
|
const { configOptions } = require_AppConfigurationProvider.useConfig();
|
|
62
|
-
const
|
|
63
|
-
|
|
65
|
+
const origin = isPrivate ? require_utils.SearchOrigin.PRIVATE : isCached ? require_utils.SearchOrigin.CACHED : isRemote ? require_utils.SearchOrigin.REMOTE : void 0;
|
|
66
|
+
const OriginIcon = configOptions?.showUplinks && origin ? ORIGIN_ICONS[origin] : void 0;
|
|
67
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
64
68
|
...props,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
color: "primary",
|
|
72
|
-
deleteIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_icons_material_Https.default, {}),
|
|
73
|
-
label: t("search.isPrivate"),
|
|
74
|
-
onDelete: handleDelete,
|
|
75
|
-
size: "small"
|
|
76
|
-
}),
|
|
77
|
-
isRemote && !isPrivate && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_Chip.default, {
|
|
78
|
-
deleteIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_icons_material_SyncAlt.default, {}),
|
|
79
|
-
label: t("search.isRemote"),
|
|
80
|
-
onDelete: handleDelete,
|
|
81
|
-
size: "small",
|
|
82
|
-
variant: "outlined"
|
|
83
|
-
}),
|
|
84
|
-
isCached && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_Chip.default, {
|
|
85
|
-
deleteIcon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_icons_material_Cached.default, {}),
|
|
86
|
-
label: t("search.isCached"),
|
|
87
|
-
onDelete: handleDelete,
|
|
88
|
-
size: "small",
|
|
89
|
-
variant: "outlined"
|
|
90
|
-
})
|
|
91
|
-
]
|
|
92
|
-
}) })]
|
|
69
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, { children: [OriginIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OriginIcon, {
|
|
70
|
+
color: origin === require_utils.SearchOrigin.PRIVATE ? "primary" : "action",
|
|
71
|
+
"data-testid": `search-origin-${origin}`,
|
|
72
|
+
fontSize: "small",
|
|
73
|
+
titleAccess: t(`search.origin.${origin}`)
|
|
74
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Text, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(TitleLine, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Name, { children: name }), version && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Version, { children: version })] }), description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Description, { children: require_utils.cleanDescription(description) })] })] })
|
|
93
75
|
});
|
|
94
76
|
};
|
|
95
77
|
//#endregion
|
|
96
78
|
exports.Description = Description;
|
|
79
|
+
exports.ORIGIN_ICONS = ORIGIN_ICONS;
|
|
97
80
|
exports.default = SearchItem;
|
|
98
81
|
|
|
99
82
|
//# sourceMappingURL=SearchItem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchItem.js","names":["
|
|
1
|
+
{"version":3,"file":"SearchItem.js","names":["SearchOrigin","LockOutlined","Inventory2Outlined","CloudOutlined","styled","useTranslation","useConfig","cleanDescription"],"sources":["../../../src/components/Search/SearchItem.tsx"],"sourcesContent":["import styled from '@emotion/styled';\nimport CloudOutlined from '@mui/icons-material/CloudOutlined';\nimport Inventory2Outlined from '@mui/icons-material/Inventory2Outlined';\nimport LockOutlined from '@mui/icons-material/LockOutlined';\nimport type { Theme } from '@mui/material';\nimport React from 'react';\nimport { useTranslation } from 'react-i18next';\n\nimport { useConfig } from '../../';\nimport { SearchOrigin, cleanDescription } from './utils';\n\ntype SearchItemProps = {\n name: string;\n version?: string;\n description?: string;\n isPrivate?: boolean;\n isCached?: boolean;\n isRemote?: boolean;\n};\n\nexport const ORIGIN_ICONS = {\n [SearchOrigin.PRIVATE]: LockOutlined,\n [SearchOrigin.CACHED]: Inventory2Outlined,\n [SearchOrigin.REMOTE]: CloudOutlined,\n};\n\nconst Row = styled('div')({\n display: 'flex',\n alignItems: 'center',\n gap: 12,\n width: '100%',\n minWidth: 0,\n});\n\nconst Text = styled('div')({\n display: 'flex',\n flexDirection: 'column',\n flex: 1,\n minWidth: 0,\n});\n\nconst TitleLine = styled('div')({\n display: 'flex',\n alignItems: 'baseline',\n gap: 8,\n});\n\nconst Name = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n fontWeight: 700,\n fontSize: theme.fontSize.sm,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}));\n\nconst Version = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n marginLeft: 'auto',\n flexShrink: 0,\n fontSize: theme.fontSize.ssm,\n color: theme.palette.text.secondary,\n}));\n\nexport const Description = styled('span')<{ theme?: Theme }>(({ theme }) => ({\n color: theme.palette.text.secondary,\n fontSize: theme.fontSize.ssm,\n lineHeight: 1.5,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n}));\n\nconst SearchItem: React.FC<SearchItemProps> = ({\n name,\n description,\n isPrivate = false,\n isRemote = false,\n isCached = false,\n version,\n ...props\n}) => {\n const { t } = useTranslation();\n const { configOptions } = useConfig();\n const origin = isPrivate\n ? SearchOrigin.PRIVATE\n : isCached\n ? SearchOrigin.CACHED\n : isRemote\n ? SearchOrigin.REMOTE\n : undefined;\n const OriginIcon = configOptions?.showUplinks && origin ? ORIGIN_ICONS[origin] : undefined;\n\n return (\n <li {...props}>\n <Row>\n {OriginIcon && (\n <OriginIcon\n color={origin === SearchOrigin.PRIVATE ? 'primary' : 'action'}\n data-testid={`search-origin-${origin}`}\n fontSize=\"small\"\n titleAccess={t(`search.origin.${origin}`)}\n />\n )}\n <Text>\n <TitleLine>\n <Name>{name}</Name>\n {version && <Version>{version}</Version>}\n </TitleLine>\n {description && <Description>{cleanDescription(description)}</Description>}\n </Text>\n </Row>\n </li>\n );\n};\n\nexport default SearchItem;\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,IAAa,eAAe;EACzBA,cAAAA,aAAa,UAAUC,iCAAAA;EACvBD,cAAAA,aAAa,SAASE,uCAAAA;EACtBF,cAAAA,aAAa,SAASG,kCAAAA;AACzB;AAEA,IAAM,OAAA,GAAMC,gBAAAA,QAAAA,CAAO,KAAK,CAAC,CAAC;CACxB,SAAS;CACT,YAAY;CACZ,KAAK;CACL,OAAO;CACP,UAAU;AACZ,CAAC;AAED,IAAM,QAAA,GAAOA,gBAAAA,QAAAA,CAAO,KAAK,CAAC,CAAC;CACzB,SAAS;CACT,eAAe;CACf,MAAM;CACN,UAAU;AACZ,CAAC;AAED,IAAM,aAAA,GAAYA,gBAAAA,QAAAA,CAAO,KAAK,CAAC,CAAC;CAC9B,SAAS;CACT,YAAY;CACZ,KAAK;AACP,CAAC;AAED,IAAM,QAAA,GAAOA,gBAAAA,QAAAA,CAAO,MAAM,CAAC,EAAqB,EAAE,aAAa;CAC7D,YAAY;CACZ,UAAU,MAAM,SAAS;CACzB,UAAU;CACV,cAAc;CACd,YAAY;AACd,EAAE;AAEF,IAAM,WAAA,GAAUA,gBAAAA,QAAAA,CAAO,MAAM,CAAC,EAAqB,EAAE,aAAa;CAChE,YAAY;CACZ,YAAY;CACZ,UAAU,MAAM,SAAS;CACzB,OAAO,MAAM,QAAQ,KAAK;AAC5B,EAAE;AAEF,IAAa,eAAA,GAAcA,gBAAAA,QAAAA,CAAO,MAAM,CAAC,EAAqB,EAAE,aAAa;CAC3E,OAAO,MAAM,QAAQ,KAAK;CAC1B,UAAU,MAAM,SAAS;CACzB,YAAY;CACZ,UAAU;CACV,cAAc;CACd,YAAY;AACd,EAAE;AAEF,IAAM,cAAyC,EAC7C,MACA,aACA,YAAY,OACZ,WAAW,OACX,WAAW,OACX,SACA,GAAG,YACC;CACJ,MAAM,EAAE,OAAA,GAAMC,cAAAA,eAAAA,CAAe;CAC7B,MAAM,EAAE,kBAAkBC,iCAAAA,UAAU;CACpC,MAAM,SAAS,YACXN,cAAAA,aAAa,UACb,WACEA,cAAAA,aAAa,SACb,WACEA,cAAAA,aAAa,SACb,KAAA;CACR,MAAM,aAAa,eAAe,eAAe,SAAS,aAAa,UAAU,KAAA;CAEjF,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;EAAI,GAAI;EACN,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,KAAD,EAAA,UAAA,CACG,cACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;GACE,OAAO,WAAWA,cAAAA,aAAa,UAAU,YAAY;GACrD,eAAa,iBAAiB;GAC9B,UAAS;GACT,aAAa,EAAE,iBAAiB,QAAQ;EACzC,CAAA,GAEH,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD,EAAA,UAAO,KAAW,CAAA,GACjB,WAAW,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD,EAAA,UAAU,QAAiB,CAAA,CAC9B,EAAA,CAAA,GACV,eAAe,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD,EAAA,UAAcO,cAAAA,iBAAiB,WAAW,EAAe,CAAA,CACrE,EAAA,CAAA,CACH,EAAA,CAAA;CACH,CAAA;AAER"}
|