[WEB-4154] fix: dropdown container classname (#7085)

* fix: dropdown container classname

* improvement: update string utils for joinWithConjunction

* improvement: add more string utils
This commit is contained in:
Prateek Shourya
2025-05-23 13:53:16 +05:30
committed by GitHub
parent 0a8cc24da5
commit 4460529b37
4 changed files with 48 additions and 55 deletions

View File

@@ -4,7 +4,7 @@ export interface IDropdown {
// root props
onOpen?: () => void;
onClose?: () => void;
containerClassName?: (isOpen: boolean) => string;
containerClassName?: string | ((isOpen: boolean) => string);
tabIndex?: number;
placement?: Placement;
disabled?: boolean;

View File

@@ -1,19 +1,14 @@
import React, { FC, useMemo, useRef, useState } from "react";
import sortBy from "lodash/sortBy";
// headless ui
import { Combobox } from "@headlessui/react";
// popper-js
import sortBy from "lodash/sortBy";
import React, { FC, useMemo, useRef, useState } from "react";
import { usePopper } from "react-popper";
// plane helpers
// plane imports
import { useOutsideClickDetector } from "@plane/hooks";
// components
// local imports
import { cn } from "../../helpers";
import { useDropdownKeyPressed } from "../hooks/use-dropdown-key-pressed";
import { DropdownButton } from "./common";
import { DropdownOptions } from "./common/options";
// hooks
import { useDropdownKeyPressed } from "../hooks/use-dropdown-key-pressed";
// helper
import { cn } from "../../helpers";
// types
import { IMultiSelectDropdown } from "./dropdown";
export const MultiSelectDropdown: FC<IMultiSelectDropdown> = (props) => {
@@ -118,7 +113,10 @@ export const MultiSelectDropdown: FC<IMultiSelectDropdown> = (props) => {
ref={dropdownRef}
value={value}
onChange={onChange}
className={cn("h-full", containerClassName)}
className={cn(
"h-full",
typeof containerClassName === "function" ? containerClassName(isOpen) : containerClassName
)}
tabIndex={tabIndex}
multiple
onKeyDown={handleKeyDown}

View File

@@ -1,19 +1,14 @@
import React, { FC, useMemo, useRef, useState } from "react";
import sortBy from "lodash/sortBy";
// headless ui
import { Combobox } from "@headlessui/react";
// popper-js
import sortBy from "lodash/sortBy";
import React, { FC, useMemo, useRef, useState } from "react";
import { usePopper } from "react-popper";
// plane helpers
// plane imports
import { useOutsideClickDetector } from "@plane/hooks";
// components
// local imports
import { cn } from "../../helpers";
import { useDropdownKeyPressed } from "../hooks/use-dropdown-key-pressed";
import { DropdownButton } from "./common";
import { DropdownOptions } from "./common/options";
// hooks
import { useDropdownKeyPressed } from "../hooks/use-dropdown-key-pressed";
// helper
import { cn } from "../../helpers";
// types
import { ISingleSelectDropdown } from "./dropdown";
export const Dropdown: FC<ISingleSelectDropdown> = (props) => {
@@ -118,7 +113,10 @@ export const Dropdown: FC<ISingleSelectDropdown> = (props) => {
ref={dropdownRef}
value={value}
onChange={onChange}
className={cn("h-full", containerClassName)}
className={cn(
"h-full",
typeof containerClassName === "function" ? containerClassName(isOpen) : containerClassName
)}
tabIndex={tabIndex}
onKeyDown={handleKeyDown}
disabled={disabled}

View File

@@ -86,36 +86,6 @@ export const copyUrlToClipboard = async (path: string) => {
await copyTextToClipboard(url.toString());
};
/**
* @description Generates a deterministic HSL color based on input string
* @param {string} string - Input string to generate color from
* @returns {string} HSL color string
* @example
* generateRandomColor("hello") // returns consistent HSL color for "hello"
* generateRandomColor("") // returns "rgb(var(--color-primary-100))"
*/
export const generateRandomColor = (string: string): string => {
if (!string) return "rgb(var(--color-primary-100))";
string = `${string}`;
const uniqueId = string.length.toString() + string;
const combinedString = uniqueId + string;
const hash = Array.from(combinedString).reduce((acc, char) => {
const charCode = char.charCodeAt(0);
return (acc << 5) - acc + charCode;
}, 0);
const hue = hash % 360;
const saturation = 70;
const lightness = 60;
const randomColor = `hsl(${hue}, ${saturation}%, ${lightness}%)`;
return randomColor;
};
/**
* @description Gets first character of first word or first characters of first two words
* @param {string} str - Input string
@@ -275,6 +245,33 @@ export const checkURLValidity = (url: string): boolean => {
return urlPattern.test(url);
};
/**
* Combines array elements with a separator and adds a conjunction before the last element
* @param array Array of strings to combine
* @param separator Separator to use between elements (default: ", ")
* @param conjunction Conjunction to use before last element (default: "and")
* @returns Combined string with conjunction before the last element
*/
export const joinWithConjunction = (array: string[], separator: string = ", ", conjunction: string = "and"): string => {
if (!array || array.length === 0) return "";
if (array.length === 1) return array[0];
if (array.length === 2) return `${array[0]} ${conjunction} ${array[1]}`;
const lastElement = array[array.length - 1];
const elementsExceptLast = array.slice(0, -1);
return `${elementsExceptLast.join(separator)}${separator}${conjunction} ${lastElement}`;
};
/**
* @description Ensures a URL has a protocol
* @param {string} url
* @returns {string}
* @example
* ensureUrlHasProtocol("example.com") => "http://example.com"
*/
export const ensureUrlHasProtocol = (url: string): string => (url.startsWith("http") ? url : `http://${url}`);
// Browser-only clipboard functions
// let copyTextToClipboard: (text: string) => Promise<void>;