// Copyright 2022 The Parca Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import {Fragment, useState} from 'react'; import {Listbox, Transition} from '@headlessui/react'; import {Icon} from '@iconify/react'; import cx from 'classnames'; import {Button, useParcaContext} from '@parca/components'; export interface DropdownElement { active: JSX.Element; expanded: JSX.Element; } export interface DropdownItem { key: string; id?: string; disabled?: boolean; disabledText?: string; element: DropdownElement; innerAction?: InnerAction; } export interface InnerAction { text: string; onClick: () => void; isDisabled?: boolean; } export function contructItemsFromArray(items: any[]): DropdownItem[] { return items.map(item => ({ key: item.key, element: {active: <>{item.label}, expanded: <>{item.label}}, innerAction: item.innerAction, })); } const Dropdown = ({ items, selectedKey, onSelection, placeholder, width, className = '', loading, primary = false, disabled = false, icon, id, optionsClassName = '', }: { items: DropdownItem[]; selectedKey: string | undefined; onSelection: (value: string) => void; placeholder?: string; width?: number; className?: string; loading?: boolean; primary?: boolean; disabled?: boolean; icon?: JSX.Element; id?: string; optionsClassName?: string; }): JSX.Element => { const selection = items.find(v => v.key === selectedKey) ?? { key: selectedKey, element: {active: <>{selectedKey}, expanded: <>{selectedKey}}, }; const {loader} = useParcaContext(); const styles = 'relative border rounded-md shadow-sm px-4 py-2 text-left cursor-default focus:outline-none focus:ring-1 items-center focus:ring-indigo-500 focus:border-indigo-500 text-sm flex gap-2 flex items-center justify-between'; const defaultStyles = 'bg-white dark:bg-gray-900 dark:border-gray-600'; const primaryStyles = 'text-gray-100 dark:gray-900 bg-indigo-600 border-indigo-500 font-medium py-2 px-4'; return ( {({open}) => (
0} )} >
{selection?.key !== '' ? selection.element.active : placeholder}
{icon ??
{loading === true ? (
{loader}
) : ( items.length > 0 && items.map(option => ) )}
)}
); }; const DropdownOption = ({option}: {option: DropdownItem}): JSX.Element => { const [isMouseOver, setIsMouseOver] = useState(false); return ( cx( active && 'bg-indigo-600 text-white', 'relative flex cursor-default select-none py-2 px-3' ) } value={option.key} > {({selected, active, disabled}) => (
setIsMouseOver(true)} onMouseLeave={() => setIsMouseOver(false)} > {isMouseOver && disabled && option.disabledText != null ? (
setIsMouseOver(false)} > {option.disabledText}
) : null}
{option.element.expanded}
{option.innerAction !== undefined && ( )} {selected ? ( ) : null}
)}
); }; export default Dropdown;