diff --git a/packages/ui/components/form/selectimproved/components/Item.tsx b/packages/ui/components/form/selectimproved/components/Item.tsx deleted file mode 100755 index 9350231eed..0000000000 --- a/packages/ui/components/form/selectimproved/components/Item.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { Check } from "lucide-react"; -import React from "react"; - -import { classNames as cn } from "@calcom/lib"; - -import { useSelectContext } from "./SelectProvider"; -import type { Option } from "./type"; - -interface ItemProps { - item: Option; - index?: number; - focused: boolean; -} - -const Item: React.FC = ({ item, index, focused }) => { - const { classNames, selectedItems, handleValueChange } = useSelectContext(); - const isMultiple = Array.isArray(selectedItems); - const isSelected = - (isMultiple && selectedItems?.some((selection) => selection.value === item.value)) || - (!isMultiple && selectedItems?.value === item.value); - - if (item.disabled) { - return ( -
  • - <> -
    - {item.leftNode && item.leftNode} -

    {item.label}

    -
    - {isMultiple ? ( -
    - {isSelected && } -
    - ) : ( - isSelected && - )} - -
  • - ); - } - - return ( -
  • handleValueChange(item)} - className={cn( - "block flex cursor-pointer select-none items-center justify-between truncate border-transparent px-3 py-2 transition duration-200", - isSelected - ? "dark:bg-darkgray-200 bg-subtle text-emphasis" - : " dark:hover:bg-darkgray-200 text-default hover:bg-subtle", - focused && "dark:bg-darkgray-200 bg-muted", - classNames?.listItem - )}> -
    - {item.leftNode && item.leftNode} -

    {item.label}

    -
    - - {isMultiple ? ( -
    - {isSelected && } -
    - ) : ( - isSelected && - )} -
  • - ); -}; - -export default Item; diff --git a/packages/ui/components/form/selectimproved/components/Options.tsx b/packages/ui/components/form/selectimproved/components/Options.tsx deleted file mode 100755 index c59cff9e07..0000000000 --- a/packages/ui/components/form/selectimproved/components/Options.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; - -import classNames from "@calcom/lib/classNames"; -import { useKeyPress } from "@calcom/lib/hooks/useKeyPress"; - -import { Label } from "../../inputs/Label"; -import Item from "./Item"; -import { SelectContext } from "./SelectProvider"; -import type { Option } from "./type"; - -interface OptionsProps { - list: T[]; - inputValue: string; - isMultiple: boolean; - selected: T | T[] | null; - searchBoxRef: React.RefObject; -} - -type FlattenedOption = Option & { current: number; groupedIndex?: number }; - -const flattenOptions = (options: Option[], groupCount?: number): FlattenedOption[] => { - return options.reduce((acc, option, current) => { - if (option.options) { - return [...acc, ...flattenOptions(option.options, current + (groupCount || 0))]; - } - return [...acc, { ...option, current, groupedIndex: groupCount }]; - }, [] as FlattenedOption[]); -}; - -function FilteredItem({ - index, - keyboardFocus, - item, - inputValue, - list, -}: { - index: number; - keyboardFocus: number; - item: FlattenedOption; - inputValue: string; - list: T[]; -}) { - const focused = index === keyboardFocus; - const ref = useRef(null); - - useEffect(() => { - if (ref.current && focused) { - ref.current.scrollIntoView({ behavior: "smooth" }); - } - }, [ref, focused]); - - return ( -
    - {item.current === 0 && item.groupedIndex !== undefined && !inputValue && ( -
    - {index !== 0 &&
    } - -
    - )} - -
    - ); -} - -function Options({ list, inputValue, searchBoxRef }: OptionsProps) { - const { classNames, handleValueChange } = useContext(SelectContext); - const [keyboardFocus, setKeyboardFocus] = useState(-1); - const enterPress = useKeyPress("Enter", searchBoxRef); - - const flattenedList = useMemo(() => flattenOptions(list), [list]); - - const totalOptionsLength = useMemo(() => { - return flattenedList.length; - }, [flattenedList]); - - useKeyPress("ArrowDown", searchBoxRef, () => setKeyboardFocus((prev) => (prev + 1) % totalOptionsLength)); - useKeyPress("ArrowUp", searchBoxRef, () => - setKeyboardFocus((prev) => (prev - 1 + totalOptionsLength) % totalOptionsLength) - ); - - useEffect(() => { - if (enterPress) { - const item = filteredList[keyboardFocus]; - if (!item || item.disabled) return; - handleValueChange(item); - } - // We don't want to re-run this effect when handleValueChange changes - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [enterPress, keyboardFocus, list]); - - const search = useCallback((optionsArray: FlattenedOption[], searchTerm: string) => { - // search options by label, or group label or options.options - return optionsArray.reduce((acc: FlattenedOption[], option: FlattenedOption) => { - // @TODO: add search by lavbel group gets awkward as it doesnt exist in the flattened list - if (option.label.toLowerCase().includes(searchTerm.toLowerCase())) { - acc.push(option); - } - - return acc; - }, [] as FlattenedOption[]); - }, []); - - const filteredList = useMemo(() => { - if (inputValue.length > 0) { - return search(flattenedList, inputValue); - } - - return flattenedList; - }, [inputValue, flattenedList, search]); - - return ( -
    - {filteredList?.map((item, index) => ( - - ))} -
    - ); -} - -export default Options; diff --git a/packages/ui/components/form/selectimproved/components/SearchInput.tsx b/packages/ui/components/form/selectimproved/components/SearchInput.tsx deleted file mode 100755 index 455d9510b9..0000000000 --- a/packages/ui/components/form/selectimproved/components/SearchInput.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React, { useContext } from "react"; - -import { Search } from "../../../icon"; -import { SelectContext } from "./SelectProvider"; - -interface SearchInputProps { - placeholder?: string; - value: string; - onChange: (e: React.ChangeEvent) => void; - name?: string; - searchInputRef?: React.RefObject; -} - -const SearchInput: React.FC = ({ - placeholder = "", - value = "", - onChange, - name = "", - searchInputRef, -}) => { - const { classNames } = useContext(SelectContext); - return ( -
    - - -
    - ); -}; - -export default SearchInput; diff --git a/packages/ui/components/form/selectimproved/components/Select.tsx b/packages/ui/components/form/selectimproved/components/Select.tsx deleted file mode 100755 index f3740352c3..0000000000 --- a/packages/ui/components/form/selectimproved/components/Select.tsx +++ /dev/null @@ -1,233 +0,0 @@ -import * as Popover from "@radix-ui/react-popover"; -import React, { useCallback, useRef, useState } from "react"; - -import { classNames as cn } from "@calcom/lib"; - -import { X, ChevronDown } from "../../../icon"; -import Options from "./Options"; -import SearchInput from "./SearchInput"; -import SelectProvider from "./SelectProvider"; -import type { Option } from "./type"; - -interface SelectProps { - options: T[]; - selectedItems: T | T[] | null; - onChange: (value?: Option | Option[] | null) => void; - placeholder?: string; - isMultiple?: boolean; - isClearable?: boolean; - isSearchable?: boolean; - isDisabled?: boolean; - loading?: boolean; - menuIsOpen?: boolean; - searchInputPlaceholder?: string; - noOptionsMessage?: string; - classNames?: { - menuButton?: ({ isDisabled }: { isDisabled: boolean }) => string; - menu?: string; - tagItem?: ({ isDisabled }: { isDisabled: boolean }) => string; - tagItemText?: string; - tagItemIconContainer?: string; - tagItemIcon?: string; - list?: string; - listGroupLabel?: string; - listItem?: ({ isSelected }: { isSelected: boolean }) => string; - listDisabledItem?: string; - ChevronIcon?: ({ open }: { open: boolean }) => string; - searchContainer?: string; - searchBox?: string; - searchIcon?: string; - closeIcon?: string; - }; -} - -function Select({ - options = [], - selectedItems = null, - onChange, - placeholder = "Select...", - searchInputPlaceholder = "Search...", - isMultiple = false, - isClearable = false, - isSearchable = false, - isDisabled = false, - menuIsOpen = false, - classNames, -}: SelectProps) { - const [inputValue, setInputValue] = useState(""); - const [open, setOpen] = useState(menuIsOpen); - const searchBoxRef = useRef(null); - - const isMultipleValue = Array.isArray(selectedItems) && isMultiple; - - const removeItem = useCallback( - (item: Option) => { - // remove the item from the selected items - if (Array.isArray(selectedItems)) { - const newSelectedItems = selectedItems.filter((selectedItem) => selectedItem.value !== item.value); - onChange(newSelectedItems); - } else { - onChange(null); - } - }, - [onChange, selectedItems] - ); - - const closeDropDown = useCallback(() => { - console.log({ open }); - if (open) setOpen(false); - }, [open]); - - const handleValueChange = useCallback( - (selected: Option) => { - function update() { - if (!isMultiple && !Array.isArray(selectedItems)) { - // Close dropdown when you select an item when we are on single select - closeDropDown(); - onChange(selected); - return; - } - - // check if the selected item is already selected - if (Array.isArray(selectedItems)) { - const isAlreadySelected = selectedItems.some((item) => item.value === selected.value); - if (isAlreadySelected) { - removeItem(selected); - return; - } - onChange(selectedItems === null ? [selected] : [...selectedItems, selected]); - } - } - - if (selected.disabled) return; - - if (selected !== selectedItems) { - update(); - } - }, - [closeDropDown, isMultiple, onChange, selectedItems, removeItem] - ); - - const clearValue = useCallback( - (e: React.MouseEvent) => { - e.stopPropagation(); - onChange(isMultiple ? [] : null); - }, - [onChange, isMultiple] - ); - - return ( - -
    - - -
    -
    - <> - {((isMultipleValue && selectedItems.length === 0) || selectedItems === null) && ( -
    -

    {placeholder}

    -
    - )} - - {Array.isArray(selectedItems) ? ( -
    - {selectedItems.map((item, index) => ( -
    -

    - {item.label} -

    - {!isDisabled && ( - - )} -
    - ))} -
    - ) : ( -
    -

    {selectedItems?.label}

    -
    - )} - -
    - -
    - <> - {isClearable && !isDisabled && selectedItems !== null && ( -
    - -
    - )} - - - -
    -
    -
    - - -
    - {isSearchable && ( - setInputValue(e.target.value)} - /> - )} - - -
    -
    -
    -
    -
    -
    - ); -} - -export default Select; diff --git a/packages/ui/components/form/selectimproved/components/SelectProvider.tsx b/packages/ui/components/form/selectimproved/components/SelectProvider.tsx deleted file mode 100644 index adbc7e782f..0000000000 --- a/packages/ui/components/form/selectimproved/components/SelectProvider.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import React, { createContext, useContext, useMemo } from "react"; - -import type { ClassNames, Option } from "./type"; - -interface Store { - selectedItems: Option | Option[] | null; - handleValueChange: (selected: Option) => void; - classNames?: ClassNames; -} - -interface Props { - selectedItems: Option | Option[] | null; - handleValueChange: (selected: Option) => void; - children: JSX.Element; - options: { - classNames?: ClassNames; - }; -} - -export const SelectContext = createContext({ - selectedItems: null, - handleValueChange: (selected) => { - return selected; - }, - classNames: undefined, -}); - -export const useSelectContext = (): Store => { - return useContext(SelectContext); -}; - -const SelectProvider: React.FC = ({ selectedItems, handleValueChange, options, children }) => { - const store = useMemo(() => { - return { - selectedItems, - handleValueChange, - classNames: options?.classNames, - } as Store; - }, [handleValueChange, options, selectedItems]); - - return {children}; -}; - -export default SelectProvider; diff --git a/packages/ui/components/form/selectimproved/components/type.ts b/packages/ui/components/form/selectimproved/components/type.ts deleted file mode 100644 index d8d6a52a8a..0000000000 --- a/packages/ui/components/form/selectimproved/components/type.ts +++ /dev/null @@ -1,26 +0,0 @@ -export interface Option { - value?: string; - label: string; - disabled?: boolean; - isSelected?: boolean; - options?: Option[]; - leftNode?: React.ReactNode; -} - -export interface ClassNames { - menuButton?: (args: { isDisabled: boolean }) => string; - menu?: string; - tagItem?: (args: { isDisabled: boolean }) => string; - tagItemText?: string; - tagItemIconContainer?: string; - tagItemIcon?: string; - list?: string; - listGroupLabel?: string; - listItem?: (args: { isSelected: boolean }) => string; - listDisabledItem?: string; - ChevronIcon?: (args: { open: boolean }) => string; - searchContainer?: string; - searchBox?: string; - searchIcon?: string; - closeIcon?: string; -} diff --git a/packages/ui/components/form/selectimproved/index.tsx b/packages/ui/components/form/selectimproved/index.tsx deleted file mode 100644 index 948d811236..0000000000 --- a/packages/ui/components/form/selectimproved/index.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import Select from "./components/Select"; - -export default Select; diff --git a/packages/ui/components/form/selectimproved/selectimproved.stories.mdx b/packages/ui/components/form/selectimproved/selectimproved.stories.mdx deleted file mode 100644 index a8988a5738..0000000000 --- a/packages/ui/components/form/selectimproved/selectimproved.stories.mdx +++ /dev/null @@ -1,85 +0,0 @@ -import { Canvas, Meta, Story, ArgsTable } from "@storybook/addon-docs"; - -import { - Examples, - Example, - Note, - Title, - CustomArgsTable, - VariantRow, - VariantsTable, -} from "@calcom/storybook/components"; - -import Select from "./components/Select"; - - - - - -export const options = [ - { - //4 - label: "Cal.com Inc", - options: [ - { value: "UserA", label: "Pro" }, // 5 - { value: "UserB", label: "Teampro" }, // 6 - { value: "UserC", label: "Example" }, - { value: "UserD", label: "Admin", disabled: true }, - ], - }, - { - // 5 - label: "Acme Inc", - options: [ - { value: "UserE", label: "Acme Pro" }, // 1 == 6 - { value: "UserF", label: "Acme Teampro" }, - { value: "UserG", label: "Acme example" }, - { value: "UserH", label: "Acme Admin", disabled: true }, - ], - }, -]; - -export const SelectWithState = (...args) => { - const [value, setValue] = React.useState(options[0].options[0]); - return <Select options={options} selectedItems={value} onChange={(e) => setValue(e)} isClearable />; -}; - -export const MultiWithState = (...args) => { - const [value, setValue] = React.useState([options[0].options[0]]); - return ( - <Select - options={options} - selectedItems={value} - onChange={(e) => { - setValue(e); - }} - isSearchable - isMultiple - isClearable - /> - ); -}; - -<Examples title="State"> - <Example title="Single" isFullWidth> - <SelectWithState /> - </Example> - <Example title="Multi" isFullWidth> - <MultiWithState /> - </Example> -</Examples> - -<Canvas> - <Story name="Default"> - <div className="flex flex-col space-y-4"> - <VariantsTable titles={[]} columnMinWidth={300}> - <VariantRow variant="Single"> - <SelectWithState /> - </VariantRow> - <VariantRow variant="Multi"> - <MultiWithState /> - </VariantRow> - </VariantsTable> - </div> - </Story> -</Canvas>