diff --git a/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx b/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx index 505f06f90d..c3e23e457b 100644 --- a/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx +++ b/deepfence_frontend/apps/dashboard/src/components/forms/CompareScanInputModal.tsx @@ -25,8 +25,8 @@ const Tags = ({ setSelectedTag, scanType, }: { - selectedTag: ImageTagType; - setSelectedTag: React.Dispatch>; + selectedTag: ImageTagType | null; + setSelectedTag: React.Dispatch>; scanType: ScanTypeEnum; }) => { const dockerImageName = useScanResults({ @@ -73,7 +73,7 @@ const InputForm = ({ toScanData: ToScanDataType; setToScanData: React.Dispatch>; }) => { - const [selectedTag, setSelectedTag] = useState({ + const [selectedTag, setSelectedTag] = useState({ nodeId, nodeName: '', tagList: [], diff --git a/deepfence_frontend/apps/dashboard/src/components/forms/SearchableTagList.tsx b/deepfence_frontend/apps/dashboard/src/components/forms/SearchableTagList.tsx index 2ccb40fa8e..e7f878680d 100644 --- a/deepfence_frontend/apps/dashboard/src/components/forms/SearchableTagList.tsx +++ b/deepfence_frontend/apps/dashboard/src/components/forms/SearchableTagList.tsx @@ -8,9 +8,9 @@ import { ScanTypeEnum } from '@/types/common'; export type Props = { scanType: ScanTypeEnum | 'none'; - onChange?: (value: ImageTagType) => void; + onChange?: (value: ImageTagType | null) => void; onClearAll?: () => void; - defaultSelectedTag?: ImageTagType; + defaultSelectedTag?: ImageTagType | null; valueKey?: 'nodeId' | 'nodeName'; active?: boolean; triggerVariant?: 'select' | 'button'; @@ -35,8 +35,8 @@ const SearchableTag = ({ filter, }: Props) => { const [searchText, setSearchText] = useState(''); - const [selectedTag, setSelectedTag] = useState(() => { - return defaultSelectedTag; + const [selectedTag, setSelectedTag] = useState(() => { + return defaultSelectedTag ?? null; }); const isSelectVariantType = useMemo(() => { @@ -44,7 +44,7 @@ const SearchableTag = ({ }, [triggerVariant]); useEffect(() => { - setSelectedTag(defaultSelectedTag ?? undefined); + setSelectedTag(defaultSelectedTag ?? null); }, [defaultSelectedTag]); const { data, isFetchingNextPage, hasNextPage, fetchNextPage } = diff --git a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx index c18a5b468e..3ac8887e59 100644 --- a/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/malwares/pages/MalwareScans.tsx @@ -455,7 +455,6 @@ const Filters = () => { { setMalwareScanStatusSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx b/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx index 2199285c50..0bfe479b4b 100644 --- a/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/postures/pages/Accounts.tsx @@ -390,7 +390,6 @@ const Filters = () => { { setComplianceScanStatusSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryImageTags.tsx b/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryImageTags.tsx index e1279489d7..4a2a79020c 100644 --- a/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryImageTags.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/registries/pages/RegistryImageTags.tsx @@ -245,7 +245,6 @@ const Filters = () => {
{ setVulnerabilityScanStatusSearchText(query); }} @@ -279,7 +278,6 @@ const Filters = () => { { setSecretScanStatusSearchText(query); }} @@ -313,7 +311,6 @@ const Filters = () => { { setMalwareScanStatusSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx index 54b9f4050f..22fabe3c59 100644 --- a/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/secrets/pages/SecretScans.tsx @@ -454,7 +454,6 @@ const Filters = () => { { setSecretScanStatusSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/threat-graph/pages/ThreatGraph.tsx b/deepfence_frontend/apps/dashboard/src/features/threat-graph/pages/ThreatGraph.tsx index bf5b366439..4a88efae4f 100644 --- a/deepfence_frontend/apps/dashboard/src/features/threat-graph/pages/ThreatGraph.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/threat-graph/pages/ThreatGraph.tsx @@ -159,7 +159,6 @@ const Filters = () => { value={THREAT_TYPES.find((threatType) => { return threatType.value === searchParams.get('type'); })} - nullable onQueryChange={(query) => { setThreatTypeSearchText(query); }} @@ -190,7 +189,6 @@ const Filters = () => { value={THREAT_GRAPH_SCOPE.find((scope) => { return scope.value === searchParams.get('cloud_resource_only'); })} - nullable onQueryChange={(query) => { setScopeSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/CloudResourcesTable.tsx b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/CloudResourcesTable.tsx index d3ddf3e2db..74a074ca62 100644 --- a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/CloudResourcesTable.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/CloudResourcesTable.tsx @@ -154,7 +154,6 @@ function SearchableServiceType() { return ( { setVulnerabilityScanStatusSearchText(query); }} @@ -315,7 +314,6 @@ function Filters() { { setSecretScanStatusSearchText(query); }} @@ -352,7 +350,6 @@ function Filters() { { setMalwareScanStatusSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/HostsTable.tsx b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/HostsTable.tsx index bb274edbd7..f25d090274 100644 --- a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/HostsTable.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/HostsTable.tsx @@ -315,7 +315,6 @@ function Filters() { /> { setVulnerabilityScanStatusSearchText(query); }} @@ -352,7 +351,6 @@ function Filters() { { setSecretScanStatusSearchText(query); }} @@ -389,7 +387,6 @@ function Filters() { { setMalwareScanStatusSearchText(query); }} @@ -426,7 +423,6 @@ function Filters() { { setComplianceScanStatusSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/PodsTable.tsx b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/PodsTable.tsx index 0a300d5e1f..97f26ee1bd 100644 --- a/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/PodsTable.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/topology/data-components/tables/PodsTable.tsx @@ -185,7 +185,6 @@ function Filters() { value={KUBERNETES_STATUSES.find((status) => { return status.value === searchParams.get('kubernetesStatus'); })} - nullable onQueryChange={(query) => { setKubernetesStatusSearchText(query); }} diff --git a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx index aa2df1812d..0b46898800 100644 --- a/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx +++ b/deepfence_frontend/apps/dashboard/src/features/vulnerabilities/pages/VulnerabilityScans.tsx @@ -860,7 +860,6 @@ const Filters = () => { { setVulnerabilityScanStatusSearchText(query); }} diff --git a/deepfence_frontend/packages/ui-components/package.json b/deepfence_frontend/packages/ui-components/package.json index 6c3fd46576..28ac6203d2 100644 --- a/deepfence_frontend/packages/ui-components/package.json +++ b/deepfence_frontend/packages/ui-components/package.json @@ -25,7 +25,7 @@ "coverage": "vitest run --coverage" }, "dependencies": { - "@headlessui/react": "^1.7.18", + "@headlessui/react": "^2.1.0", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", diff --git a/deepfence_frontend/packages/ui-components/src/components/select/Combobox.stories.tsx b/deepfence_frontend/packages/ui-components/src/components/select/Combobox.stories.tsx index f82f218fd1..61d4a4acf5 100644 --- a/deepfence_frontend/packages/ui-components/src/components/select/Combobox.stories.tsx +++ b/deepfence_frontend/packages/ui-components/src/components/select/Combobox.stories.tsx @@ -52,7 +52,7 @@ const OPTIONS = [ }, ]; -const SingleSelectNullableTemplate: StoryFn = () => { +const SingleSelectTemplate: StoryFn = () => { const [selected, setSelected] = useState<(typeof OPTIONS)[number] | null>(null); const [options, setOptions] = useState([...OPTIONS]); const [loading, setLoading] = useState(false); @@ -71,7 +71,6 @@ const SingleSelectNullableTemplate: StoryFn = () => { return ( { setQuery(query); }} @@ -98,12 +97,12 @@ const SingleSelectNullableTemplate: StoryFn = () => { ); }; -export const SingleSelectNullable: StoryObj = { - render: SingleSelectNullableTemplate, +export const SingleSelect: StoryObj = { + render: SingleSelectTemplate, args: {}, }; -const SingleSelectNullableWithStringValuesTemplate: StoryFn = () => { +const SingleSelectWithStringValuesTemplate: StoryFn = () => { const [selected, setSelected] = useState(null); const [options, setOptions] = useState([...OPTIONS]); @@ -112,7 +111,6 @@ const SingleSelectNullableWithStringValuesTemplate: StoryFn = ( return ( { setQuery(query); @@ -144,63 +142,12 @@ const SingleSelectNullableWithStringValuesTemplate: StoryFn = ( ); }; -export const SingleSelectNullableStringValuesAndSelectTrigger: StoryObj = - { - render: SingleSelectNullableWithStringValuesTemplate, - args: {}, - }; - -const SingleSelectNonNullableTemplate: StoryFn = () => { - const [selected, setSelected] = useState<(typeof OPTIONS)[number]>(OPTIONS[0]); - const [options, setOptions] = useState([...OPTIONS]); - const [loading, setLoading] = useState(false); - - const [query, setQuery] = useState(''); - - function fetchMoreData() { - // we can use query here as well - setLoading(true); - setTimeout(() => { - setOptions([...options, ...OPTIONS]); - setLoading(false); - }, 1000); - } - - return ( - { - setQuery(query); - }} - label="Select your value" - onChange={(value) => { - setSelected(value); - }} - getDisplayValue={() => { - return 'PropertyName'; - }} - onEndReached={() => { - fetchMoreData(); - }} - loading={loading} - > - {options.map((person, index) => { - return ( - - {person.name} - - ); - })} - - ); -}; - -export const SingleSelectNonNullable: StoryObj = { - render: SingleSelectNonNullableTemplate, +export const SingleSelectStringValuesAndSelectTrigger: StoryObj = { + render: SingleSelectWithStringValuesTemplate, args: {}, }; -const MultiSelectNullableTemplate: StoryFn = () => { +const MultiSelectTemplate: StoryFn = () => { const [selected, setSelected] = useState([]); const [options, setOptions] = useState([...OPTIONS]); const [loading, setLoading] = useState(false); @@ -228,7 +175,6 @@ const MultiSelectNullableTemplate: StoryFn = () => { }} clearAllElement="Clear filters" multiple - nullable getDisplayValue={() => { return 'PropertyName'; }} @@ -248,12 +194,12 @@ const MultiSelectNullableTemplate: StoryFn = () => { ); }; -export const MultiSelectNullable: StoryObj = { - render: MultiSelectNullableTemplate, +export const MultiSelect: StoryObj = { + render: MultiSelectTemplate, args: {}, }; -const MultiSelectNullableWithSelectVariantTemplate: StoryFn = () => { +const MultiSelectWithSelectVariantTemplate: StoryFn = () => { const [selected, setSelected] = useState([]); const [options, setOptions] = useState([...OPTIONS]); const [loading, setLoading] = useState(false); @@ -282,7 +228,6 @@ const MultiSelectNullableWithSelectVariantTemplate: StoryFn = ( }} clearAllElement="Clear" multiple - nullable placeholder="Please select..." getDisplayValue={(value) => { return value.length ? `${value.length} selected` : null; @@ -306,64 +251,12 @@ const MultiSelectNullableWithSelectVariantTemplate: StoryFn = ( ); }; -export const MultiSelectNullableWithSelectVariant: StoryObj = { - render: MultiSelectNullableWithSelectVariantTemplate, - args: {}, -}; - -const MultiSelectNonNullableTemplate: StoryFn = () => { - const [selected, setSelected] = useState([]); - const [options, setOptions] = useState([...OPTIONS]); - const [loading, setLoading] = useState(false); - - const [query, setQuery] = useState(''); - - function fetchMoreData() { - // we can use query here as well - setLoading(true); - setTimeout(() => { - setOptions([...options, ...OPTIONS]); - setLoading(false); - }, 1000); - } - - return ( - { - setQuery(query); - }} - label="Select your value" - clearAllElement="Clear filters" - onChange={(value) => { - setSelected(value); - }} - multiple - getDisplayValue={() => { - return 'PropertyName'; - }} - onEndReached={() => { - fetchMoreData(); - }} - loading={loading} - > - {options.map((person, index) => { - return ( - - {person.name} - - ); - })} - - ); -}; - -export const MultiSelectNonNullable: StoryObj = { - render: MultiSelectNonNullableTemplate, +export const MultiSelectWithSelectVariant: StoryObj = { + render: MultiSelectWithSelectVariantTemplate, args: {}, }; -const MultiSelectNonNullableTemplateInsideDialog: StoryFn = () => { +const MultiSelectTemplateInsideDialog: StoryFn = () => { const [selected, setSelected] = useState([]); const [options, setOptions] = useState([...OPTIONS]); const [loading, setLoading] = useState(false); @@ -421,7 +314,7 @@ const MultiSelectNonNullableTemplateInsideDialog: StoryFn = () ); }; -export const MultiSelectNonNullableInsideDialog: StoryObj = { - render: MultiSelectNonNullableTemplateInsideDialog, +export const MultiSelectInsideDialog: StoryObj = { + render: MultiSelectTemplateInsideDialog, args: {}, }; diff --git a/deepfence_frontend/packages/ui-components/src/components/select/Combobox.test.tsx b/deepfence_frontend/packages/ui-components/src/components/select/Combobox.test.tsx index a8fe2c29cd..8b1476d41a 100644 --- a/deepfence_frontend/packages/ui-components/src/components/select/Combobox.test.tsx +++ b/deepfence_frontend/packages/ui-components/src/components/select/Combobox.test.tsx @@ -1,6 +1,7 @@ import '@testing-library/jest-dom'; import { act, fireEvent, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { useEffect, useState } from 'react'; import { describe, expect } from 'vitest'; @@ -55,7 +56,6 @@ describe('Combobox', () => { return ( { setQuery(query); }} @@ -81,16 +81,15 @@ describe('Combobox', () => { const triggerBtn = screen.getByTestId('comboboxTriggerButtonId'); expect(triggerBtn).toHaveTextContent('PropertyName'); await act(async () => { - return triggerBtn.click(); + return userEvent.click(triggerBtn); }); const op1 = screen.getByRole('option', { name: 'Jon', }); - expect(op1).toBeInTheDocument(); await act(async () => { - return op1.click(); + return userEvent.click(op1); }); expect(triggerBtn).toHaveTextContent('Jon'); }); @@ -104,7 +103,6 @@ describe('Combobox', () => { { setQuery(query); }} @@ -130,7 +128,7 @@ describe('Combobox', () => { const triggerBtn = screen.getByTestId('comboboxTriggerButtonId'); expect(triggerBtn).toHaveTextContent('PropertyName'); await act(async () => { - return triggerBtn.click(); + return userEvent.click(triggerBtn); }); const op1 = screen.getByRole('option', { @@ -139,7 +137,7 @@ describe('Combobox', () => { expect(op1).toBeInTheDocument(); await act(async () => { - return op1.click(); + return userEvent.click(op1); }); expect(triggerBtn).toHaveTextContent('Jon'); }); @@ -163,7 +161,6 @@ describe('Combobox', () => { }} clearAllElement="Clear filters" multiple - nullable getDisplayValue={() => { return 'PropertyName'; }} @@ -183,7 +180,7 @@ describe('Combobox', () => { const triggerBtn = screen.getByTestId('comboboxTriggerButtonId'); expect(triggerBtn).toHaveTextContent('PropertyName'); await act(async () => { - return triggerBtn.click(); + return userEvent.click(triggerBtn); }); const op1 = screen.getByRole('option', { @@ -192,7 +189,7 @@ describe('Combobox', () => { expect(op1).toBeInTheDocument(); await act(async () => { - return op1.click(); + return userEvent.click(op1); }); expect(triggerBtn).toHaveTextContent('1'); }); @@ -219,7 +216,6 @@ describe('Combobox', () => { return ( { setQuery(query); @@ -248,7 +244,7 @@ describe('Combobox', () => { const triggerBtn = screen.getByTestId('comboboxTriggerButtonId'); expect(triggerBtn).toHaveTextContent('PropertyName'); await act(async () => { - return triggerBtn.click(); + return userEvent.click(triggerBtn); }); const op1 = screen.getByRole('option', { diff --git a/deepfence_frontend/packages/ui-components/src/components/select/Combobox.tsx b/deepfence_frontend/packages/ui-components/src/components/select/Combobox.tsx index e7e574e855..07853501ee 100644 --- a/deepfence_frontend/packages/ui-components/src/components/select/Combobox.tsx +++ b/deepfence_frontend/packages/ui-components/src/components/select/Combobox.tsx @@ -1,7 +1,13 @@ import { Combobox as HUICombobox, + ComboboxButton, + ComboboxInput, + ComboboxOption as HUIComboboxOption, ComboboxOptionProps as HUIComboboxOptionProps, + ComboboxOptions, ComboboxProps as HUIComboboxProps, + Field, + Label, } from '@headlessui/react'; import * as PopoverPrimitive from '@radix-ui/react-popover'; import { Slot } from '@radix-ui/react-slot'; @@ -75,10 +81,9 @@ const OptionsWrapper = ({ children }: { children: React.ReactNode }) => { }; type ComboboxProps< TValue, - TNullable extends boolean | undefined, TMultiple extends boolean | undefined, TTag extends ElementType, -> = HUIComboboxProps & { +> = HUIComboboxProps & { triggerVariant?: 'button' | 'select'; color?: 'error' | 'default'; helperText?: string; @@ -100,16 +105,10 @@ let DEFAULT_COMBOBOX_TAG: React.ExoticComponent<{ }>; export function Combobox( - props: ComboboxProps, + props: ComboboxProps, ): JSX.Element; export function Combobox( - props: ComboboxProps, -): JSX.Element; -export function Combobox( - props: ComboboxProps, -): JSX.Element; -export function Combobox( - props: ComboboxProps, + props: ComboboxProps, ): JSX.Element; export function Combobox({ children, @@ -130,7 +129,7 @@ export function Combobox) { +}: ComboboxProps) { const inputBtnId = useId(); return ( @@ -139,36 +138,35 @@ export function Combobox - - {({ open }) => { - return ( -
- {label?.length && ( - - {label} - - )} + + {label?.length ? ( + + ) : null} + + {({ open }) => { + return (
{triggerVariant === 'button' ? ( - - - + {startIcon ?? } + {getDisplayValue?.(value as unknown as any) ?? placeholder} + {endIcon} + {multiple && Array.isArray(value) && value.length > 0 ? ( +
+ +
+ ) : null} + ) : ( -
- + )} @@ -255,7 +251,7 @@ export function Combobox - - +
- @@ -312,10 +308,10 @@ export function Combobox
- + ) : null} -
+ { @@ -336,15 +332,15 @@ export function Combobox )}
- {helperText && triggerVariant === 'select' && ( -
- -
- )} -
- ); - }} - + ); + }} + + {helperText && triggerVariant === 'select' && ( +
+ +
+ )} + ); } @@ -355,8 +351,8 @@ export function ComboboxOption({ }: HUIComboboxOptionProps<'li', TType>) { const { multiple } = useContext(ListboxContext); return ( - { + { return cn( 'relative select-none', 'pt-1.5 pb-1.5 px-3', @@ -364,7 +360,7 @@ export function ComboboxOption({ 'cursor-pointer text-p4a', 'dark:hover:bg-bg-hover-2 hover:bg-bg-breadcrumb-bar', { - 'dark:bg-bg-grid-header bg-bg-breadcrumb-bar text-p4a': active, + 'dark:bg-bg-grid-header bg-bg-breadcrumb-bar text-p4a': focus, 'dark:bg-bg-active-selection bg-bg-breadcrumb-bar text-text-input-value text-p4a': selected, }, @@ -380,7 +376,7 @@ export function ComboboxOption({ ); }} - + ); } diff --git a/deepfence_frontend/packages/ui-components/src/components/select/Listbox.tsx b/deepfence_frontend/packages/ui-components/src/components/select/Listbox.tsx index 5d7d419914..ebe5e25d24 100644 --- a/deepfence_frontend/packages/ui-components/src/components/select/Listbox.tsx +++ b/deepfence_frontend/packages/ui-components/src/components/select/Listbox.tsx @@ -1,8 +1,13 @@ import { + Field, Listbox as HUIListbox, + ListboxButton, + ListboxOption as HUIListboxOption, ListboxOptionProps as HUIListboxOptionProps, + ListboxOptions, ListboxProps as HUIListboxProps, } from '@headlessui/react'; +import { Label } from '@radix-ui/react-label'; import * as PopoverPrimitive from '@radix-ui/react-popover'; import { cva } from 'cva'; import { isEmpty, isNil } from 'lodash-es'; @@ -212,124 +217,126 @@ export function Listbox({ multiple: !!multiple, }} > - - {({ open }) => { - return ( -
- {label && ( - - {required && *} - {label} - - )} + + {label ? ( + + ) : null} - - - -
- {startIcon ? ( -
{startIcon}
- ) : null} - - {getPlaceholderValue(value, getDisplayValue, placeholder)} - -
-
+ {({ open }) => { + return ( +
+ + + - - {multiple && Array.isArray(value) && value.length > 0 ? ( -
- -
- ) : null} -
- - - - -
- -
- - {children} - - {loading ? ( -
- -
- ) : ( - { - onEndReached?.(); - }} +
+ {startIcon ? ( +
{startIcon}
+ ) : null} + + {getPlaceholderValue(value, getDisplayValue, placeholder)} + +
+
+ + {multiple && Array.isArray(value) && value.length > 0 ? ( +
+ - )} -
- {multiple ? ( - <> - - -
- -
-
- +
) : null} - -
- - - - {helperText && ( -
- -
- )} -
- ); - }} - +
+ +
+ + +
+ +
+ + {children} + + {loading ? ( +
+ +
+ ) : ( + { + onEndReached?.(); + }} + /> + )} +
+ {multiple ? ( + <> + + +
+ +
+
+ + ) : null} +
+
+
+
+
+
+ ); + }} +
+ {helperText && ( +
+ +
+ )} + ); } @@ -358,7 +365,7 @@ export function ListboxOption({ const { multiple } = useContext(ListboxContext); return ( - { return cn( 'relative select-none', @@ -382,7 +389,7 @@ export function ListboxOption({ {children} )} - + ); } function getPlaceholderValue( diff --git a/deepfence_frontend/pnpm-lock.yaml b/deepfence_frontend/pnpm-lock.yaml index 2a5a421a3f..bef4884c82 100644 --- a/deepfence_frontend/pnpm-lock.yaml +++ b/deepfence_frontend/pnpm-lock.yaml @@ -148,7 +148,7 @@ importers: packages/ui-components: specifiers: - '@headlessui/react': ^1.7.18 + '@headlessui/react': ^2.1.0 '@radix-ui/react-accordion': ^1.1.2 '@radix-ui/react-checkbox': ^1.0.4 '@radix-ui/react-dialog': ^1.0.5 @@ -208,7 +208,7 @@ importers: vite-plugin-dts: ^3.8.1 vitest: ^1.4.0 dependencies: - '@headlessui/react': 1.7.18_biqbaboplfbrettd7655fr4n2y + '@headlessui/react': 2.1.0_biqbaboplfbrettd7655fr4n2y '@radix-ui/react-accordion': 1.1.2_cc55nvzwlsvwrl3jhzkkbmzrbi '@radix-ui/react-checkbox': 1.0.4_cc55nvzwlsvwrl3jhzkkbmzrbi '@radix-ui/react-dialog': 1.0.5_cc55nvzwlsvwrl3jhzkkbmzrbi @@ -238,7 +238,7 @@ importers: '@storybook/theming': 8.0.6_biqbaboplfbrettd7655fr4n2y '@testing-library/jest-dom': 6.4.2_vitest@1.4.0 '@testing-library/react': 14.3.0_biqbaboplfbrettd7655fr4n2y - '@testing-library/user-event': 14.5.2_@testing-library+dom@9.3.4 + '@testing-library/user-event': 14.5.2_ypjnezujtg6qeyrus7c6ymewii '@types/lodash-es': 4.17.12 '@types/react': 18.2.75 '@types/react-dom': 18.2.24 @@ -251,7 +251,7 @@ importers: eslint-config-prettier: 9.1.0_eslint@8.57.0 eslint-plugin-import: 2.29.1_ncq5gofulvdfszkh2q5am53rqa eslint-plugin-jsx-a11y: 6.8.0_eslint@8.57.0 - eslint-plugin-prettier: 5.1.3_udeglvt2rvqfn252kbszwwr7nu + eslint-plugin-prettier: 5.1.3_l5rqmuggcievdbel77zlrp73ji eslint-plugin-react: 7.34.1_eslint@8.57.0 eslint-plugin-simple-import-sort: 12.0.0_eslint@8.57.0 eslint-plugin-storybook: 0.8.0_sojhslj24nfrktykmoxvmoo65u @@ -564,6 +564,14 @@ packages: picocolors: 1.0.0 dev: true + /@babel/code-frame/7.24.7: + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 + dev: true + /@babel/compat-data/7.24.4: resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} engines: {node: '>=6.9.0'} @@ -846,6 +854,11 @@ packages: engines: {node: '>=6.9.0'} dev: true + /@babel/helper-validator-identifier/7.24.7: + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helper-validator-option/7.23.5: resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} @@ -890,6 +903,16 @@ packages: picocolors: 1.0.0 dev: true + /@babel/highlight/7.24.7: + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + dev: true + /@babel/parser/7.22.10: resolution: {integrity: sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==} engines: {node: '>=6.0.0'} @@ -1914,6 +1937,13 @@ packages: dependencies: regenerator-runtime: 0.14.0 + /@babel/runtime/7.24.7: + resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + /@babel/template/7.24.0: resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} engines: {node: '>=6.9.0'} @@ -2271,19 +2301,49 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false + /@floating-ui/react-dom/2.1.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/dom': 1.5.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + + /@floating-ui/react/0.26.17_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-ESD+jYWwqwVzaIgIhExrArdsCL1rOAzryG/Sjlu8yaD3Mtqi3uVyhbE2V7jD58Mo52qbzKz2eUY/Xgh5I86FCQ==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@floating-ui/react-dom': 2.1.0_biqbaboplfbrettd7655fr4n2y + '@floating-ui/utils': 0.2.2 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + tabbable: 6.2.0 + dev: false + /@floating-ui/utils/0.1.1: resolution: {integrity: sha512-m0G6wlnhm/AX0H12IOWtK8gASEMffnX08RtKkCgTdHb9JpHKGloI7icFfLg9ZmQeavcvR0PKmzxClyuFPSjKWw==} dev: false - /@headlessui/react/1.7.18_biqbaboplfbrettd7655fr4n2y: - resolution: {integrity: sha512-4i5DOrzwN4qSgNsL4Si61VMkUcWbcSKueUV7sFhpHzQcSShdlHENE5+QBntMSRvHt8NyoFO2AGG8si9lq+w4zQ==} + /@floating-ui/utils/0.2.2: + resolution: {integrity: sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==} + dev: false + + /@headlessui/react/2.1.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-/MizQk2xqR5ELkmCI1xWy3VgJULvR8gcAXtZhcK7sY53TNRCPeMdeODEXKSv9LPSSRlEAyzW1+NGJiaXq6dLRw==} engines: {node: '>=10'} peerDependencies: - react: ^16 || ^17 || ^18 - react-dom: ^16 || ^17 || ^18 + react: ^18 + react-dom: ^18 dependencies: - '@tanstack/react-virtual': 3.2.0_biqbaboplfbrettd7655fr4n2y - client-only: 0.0.1 + '@floating-ui/react': 0.26.17_biqbaboplfbrettd7655fr4n2y + '@react-aria/focus': 3.17.1_react@18.2.0 + '@react-aria/interactions': 3.21.3_react@18.2.0 + '@tanstack/react-virtual': 3.5.0_biqbaboplfbrettd7655fr4n2y react: 18.2.0 react-dom: 18.2.0_react@18.2.0 dev: false @@ -3542,6 +3602,71 @@ packages: '@babel/runtime': 7.24.4 dev: false + /@react-aria/focus/3.17.1_react@18.2.0: + resolution: {integrity: sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + dependencies: + '@react-aria/interactions': 3.21.3_react@18.2.0 + '@react-aria/utils': 3.24.1_react@18.2.0 + '@react-types/shared': 3.23.1_react@18.2.0 + '@swc/helpers': 0.5.11 + clsx: 2.0.0 + react: 18.2.0 + dev: false + + /@react-aria/interactions/3.21.3_react@18.2.0: + resolution: {integrity: sha512-BWIuf4qCs5FreDJ9AguawLVS0lV9UU+sK4CCnbCNNmYqOWY+1+gRXCsnOM32K+oMESBxilAjdHW5n1hsMqYMpA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + dependencies: + '@react-aria/ssr': 3.9.4_react@18.2.0 + '@react-aria/utils': 3.24.1_react@18.2.0 + '@react-types/shared': 3.23.1_react@18.2.0 + '@swc/helpers': 0.5.11 + react: 18.2.0 + dev: false + + /@react-aria/ssr/3.9.4_react@18.2.0: + resolution: {integrity: sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ==} + engines: {node: '>= 12'} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + dependencies: + '@swc/helpers': 0.5.11 + react: 18.2.0 + dev: false + + /@react-aria/utils/3.24.1_react@18.2.0: + resolution: {integrity: sha512-O3s9qhPMd6n42x9sKeJ3lhu5V1Tlnzhu6Yk8QOvDuXf7UGuUjXf9mzfHJt1dYzID4l9Fwm8toczBzPM9t0jc8Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + dependencies: + '@react-aria/ssr': 3.9.4_react@18.2.0 + '@react-stately/utils': 3.10.1_react@18.2.0 + '@react-types/shared': 3.23.1_react@18.2.0 + '@swc/helpers': 0.5.11 + clsx: 2.0.0 + react: 18.2.0 + dev: false + + /@react-stately/utils/3.10.1_react@18.2.0: + resolution: {integrity: sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + dependencies: + '@swc/helpers': 0.5.11 + react: 18.2.0 + dev: false + + /@react-types/shared/3.23.1_react@18.2.0: + resolution: {integrity: sha512-5d+3HbFDxGZjhbMBeFHRQhexMFt4pUce3okyRtUVKbbedQFUrtXSBg9VszgF2RTeQDKDkMCIQDtz5ccP/Lk1gw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /@remix-run/router/1.15.3: resolution: {integrity: sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==} engines: {node: '>=14.0.0'} @@ -4515,6 +4640,12 @@ packages: use-sync-external-store: 1.2.0_react@18.2.0 dev: false + /@swc/helpers/0.5.11: + resolution: {integrity: sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==} + dependencies: + tslib: 2.6.2 + dev: false + /@tailwindcss/typography/0.5.12_tailwindcss@3.4.3: resolution: {integrity: sha512-CNwpBpconcP7ppxmuq3qvaCxiRWnbhANpY/ruH4L5qs2GCiVDJXde/pjj2HWPV1+Q4G9+V/etrwUYopdcjAlyg==} peerDependencies: @@ -4561,13 +4692,13 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false - /@tanstack/react-virtual/3.2.0_biqbaboplfbrettd7655fr4n2y: - resolution: {integrity: sha512-OEdMByf2hEfDa6XDbGlZN8qO6bTjlNKqjM3im9JG+u3mCL8jALy0T/67oDI001raUUPh1Bdmfn4ZvPOV5knpcg==} + /@tanstack/react-virtual/3.5.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 dependencies: - '@tanstack/virtual-core': 3.2.0 + '@tanstack/virtual-core': 3.5.0 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 dev: false @@ -4577,10 +4708,24 @@ packages: engines: {node: '>=12'} dev: false - /@tanstack/virtual-core/3.2.0: - resolution: {integrity: sha512-P5XgYoAw/vfW65byBbJQCw+cagdXDT/qH6wmABiLt4v4YBT2q2vqCOhihe+D1Nt325F/S/0Tkv6C5z0Lv+VBQQ==} + /@tanstack/virtual-core/3.5.0: + resolution: {integrity: sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==} dev: false + /@testing-library/dom/10.1.0: + resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} + engines: {node: '>=18'} + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/runtime': 7.24.7 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + dev: true + /@testing-library/dom/9.3.1: resolution: {integrity: sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==} engines: {node: '>=14'} @@ -4638,7 +4783,7 @@ packages: dom-accessibility-api: 0.6.3 lodash: 4.17.21 redent: 3.0.0 - vitest: 1.4.0 + vitest: 1.4.0_jsdom@24.0.0 dev: true /@testing-library/react/14.3.0_biqbaboplfbrettd7655fr4n2y: @@ -4664,6 +4809,15 @@ packages: '@testing-library/dom': 9.3.4 dev: true + /@testing-library/user-event/14.5.2_ypjnezujtg6qeyrus7c6ymewii: + resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + dependencies: + '@testing-library/dom': 10.1.0 + dev: true + /@types/argparse/1.0.38: resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} dev: true @@ -4672,6 +4826,10 @@ packages: resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==} dev: true + /@types/aria-query/5.0.4: + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + dev: true + /@types/babel__core/7.20.5: resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} dependencies: @@ -5194,7 +5352,7 @@ packages: strip-literal: 2.1.0 test-exclude: 6.0.0 v8-to-istanbul: 9.2.0 - vitest: 1.4.0 + vitest: 1.4.0_jsdom@24.0.0 transitivePeerDependencies: - supports-color dev: true @@ -6093,10 +6251,6 @@ packages: engines: {node: '>= 12'} dev: true - /client-only/0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - /cliui/7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} dependencies: @@ -7196,6 +7350,27 @@ packages: object.fromentries: 2.0.8 dev: true + /eslint-plugin-prettier/5.1.3_l5rqmuggcievdbel77zlrp73ji: + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.57.0 + eslint-config-prettier: 9.1.0_eslint@8.57.0 + prettier: 3.3.2 + prettier-linter-helpers: 1.0.0 + synckit: 0.8.8 + dev: true + /eslint-plugin-prettier/5.1.3_udeglvt2rvqfn252kbszwwr7nu: resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -8011,7 +8186,7 @@ packages: source-map: 0.6.1 wordwrap: 1.0.0 optionalDependencies: - uglify-js: 3.17.4 + uglify-js: 3.18.0 dev: true /has-bigints/1.0.2: @@ -10239,6 +10414,10 @@ packages: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true + /picocolors/1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + dev: true + /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -10408,6 +10587,12 @@ packages: hasBin: true dev: true + /prettier/3.3.2: + resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==} + engines: {node: '>=14'} + hasBin: true + dev: true + /pretty-format/27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -10872,6 +11057,10 @@ packages: /regenerator-runtime/0.14.0: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} + /regenerator-runtime/0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + /regenerator-transform/0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} dependencies: @@ -11736,6 +11925,10 @@ packages: tslib: 2.6.2 dev: true + /tabbable/6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: false + /tailwind-merge/2.2.2: resolution: {integrity: sha512-tWANXsnmJzgw6mQ07nE3aCDkCK4QdT3ThPMCzawoYA2Pws7vSTCvz3Vrjg61jVUGfFZPJzxEP+NimbcW+EdaDw==} dependencies: @@ -12246,8 +12439,8 @@ packages: resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} dev: true - /uglify-js/3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + /uglify-js/3.18.0: + resolution: {integrity: sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==} engines: {node: '>=0.8.0'} hasBin: true requiresBuild: true