[WEB-4660] chore: replace jsx element with react node (#7567)

* chore: replace jsx element with react node

* fix: review comments

* fix: tooltip types update

* fix: propel pacakge fix
This commit is contained in:
sriram veeraghanta 2025-08-11 18:42:23 +05:30 committed by GitHub
parent 1ef30746a2
commit a085c0ec62
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 102 additions and 57 deletions

View file

@ -7,8 +7,8 @@ import { cn } from "@plane/utils";
type Props = {
name: string;
description: string;
icon: JSX.Element;
config: JSX.Element;
icon: React.ReactNode;
config: React.ReactNode;
disabled?: boolean;
withBorder?: boolean;
unavailable?: boolean;

View file

@ -13,7 +13,7 @@ type Props = {
type: "text" | "password";
name: string;
label: string;
description?: string | JSX.Element;
description?: string | React.ReactNode;
placeholder: string;
error: boolean;
required: boolean;
@ -23,7 +23,7 @@ export type TControllerInputFormField = {
key: string;
type: "text" | "password";
label: string;
description?: string | JSX.Element;
description?: string | React.ReactNode;
placeholder: string;
error: boolean;
required: boolean;

View file

@ -9,14 +9,14 @@ import { Button, TOAST_TYPE, setToast } from "@plane/ui";
type Props = {
label: string;
url: string;
description: string | JSX.Element;
description: string | React.ReactNode;
};
export type TCopyField = {
key: string;
label: string;
url: string;
description: string | JSX.Element;
description: string | React.ReactNode;
};
export const CopyField: React.FC<Props> = (props) => {

View file

@ -3,7 +3,7 @@ import { TLoader } from "@plane/types";
import { LogoSpinner } from "@/components/common";
interface Props {
children: string | JSX.Element | JSX.Element[];
children: string | React.ReactNode | React.ReactNode[];
getGroupIssueCount: (
groupId: string | undefined,
subGroupId: string | undefined,

View file

@ -31,7 +31,7 @@ const ProfileActivityPage = observer(() => {
const handleLoadMore = () => setPageCount((prev) => prev + 1);
const activityPages: JSX.Element[] = [];
const activityPages: React.ReactNode[] = [];
for (let i = 0; i < pageCount; i++)
activityPages.push(
<WorkspaceActivityListPage

View file

@ -6,7 +6,7 @@ import { useParams } from "next/navigation";
// icons
import { Calendar, ChevronDown, Kanban, List } from "lucide-react";
// plane imports
import { EIssueFilterType, ISSUE_LAYOUTS, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
import { EIssueFilterType, ISSUE_DISPLAY_FILTERS_BY_PAGE } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import {
EIssuesStoreType,
@ -15,7 +15,6 @@ import {
IIssueFilterOptions,
EIssueLayoutTypes,
} from "@plane/types";
import { CustomMenu } from "@plane/ui";
import { isIssueFilterActive } from "@plane/utils";
// components
import { WorkItemsModal } from "@/components/analytics/work-items/modal";
@ -23,7 +22,6 @@ import {
DisplayFiltersSelection,
FilterSelection,
FiltersDropdown,
IssueLayoutIcon,
MobileLayoutSelection,
} from "@/components/issues/issue-layouts";
// helpers

View file

@ -34,7 +34,7 @@ const ProfileActivityPage = observer(() => {
const handleLoadMore = () => setPageCount((prev) => prev + 1);
const activityPages: JSX.Element[] = [];
const activityPages: React.ReactNode[] = [];
for (let i = 0; i < pageCount; i++)
activityPages.push(
<ProfileActivityListPage

View file

@ -37,7 +37,7 @@ const ProfileActivityPage = observer(() => {
const handleLoadMore = () => setPageCount((prev) => prev + 1);
const activityPages: JSX.Element[] = [];
const activityPages: React.ReactNode[] = [];
for (let i = 0; i < pageCount; i++)
activityPages.push(
<ProfileActivityListPage

View file

@ -18,7 +18,7 @@ import { IssueIdentifier } from "@/plane-web/components/issues";
export type TCommandGroups = {
[key: string]: {
icon: JSX.Element | null;
icon: React.ReactNode | null;
itemName: (item: any) => React.ReactNode;
path: (item: any, projectId: string | undefined) => string;
title: string;

View file

@ -7,7 +7,7 @@ export type TStateOptionProps = {
option: {
value: string | undefined;
query: string;
content: JSX.Element;
content: React.ReactNode;
};
selectedValue: string | null | undefined;
className?: string;

View file

@ -10,7 +10,7 @@ type Props = {
placeholder?: string;
hiddenOptions?: ChartXAxisProperty[];
allowNoValue?: boolean;
label?: string | JSX.Element;
label?: string | React.ReactNode;
};
export const SelectXAxis: React.FC<Props> = (props) => {

View file

@ -12,9 +12,9 @@ interface IListItemProps {
title: string;
itemLink: string;
onItemClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
prependTitleElement?: JSX.Element;
appendTitleElement?: JSX.Element;
actionableItems?: JSX.Element;
prependTitleElement?: React.ReactNode;
appendTitleElement?: React.ReactNode;
actionableItems?: React.ReactNode;
isMobile?: boolean;
parentRef: React.RefObject<HTMLDivElement>;
disableLink?: boolean;
@ -22,7 +22,7 @@ interface IListItemProps {
itemClassName?: string;
actionItemContainerClassName?: string;
isSidebarOpen?: boolean;
quickActionElement?: JSX.Element;
quickActionElement?: React.ReactNode;
preventDefaultProgress?: boolean;
leftElementClassName?: string;
rightElementClassName?: string;

View file

@ -22,7 +22,7 @@ type Props = {
onError?: (error: any) => void;
placement?: Placement;
prompt?: string;
button: JSX.Element;
button: React.ReactNode;
className?: string;
workspaceId: string;
workspaceSlug: string;

View file

@ -23,7 +23,7 @@ type DropdownOptions =
| {
value: string | null;
query: string;
content: JSX.Element;
content: React.ReactNode;
}[]
| undefined;

View file

@ -33,7 +33,7 @@ type DropdownOptions =
| {
value: string | null;
query: string;
content: JSX.Element;
content: React.ReactNode;
}[]
| undefined;

View file

@ -18,7 +18,7 @@ type DropdownOptions =
| {
value: string | null;
query: string;
content: JSX.Element;
content: React.ReactNode;
}[]
| undefined;

View file

@ -46,7 +46,7 @@ type Props = {
currentView: TGanttViews,
targetDate?: Date
) => ChartDataType | undefined;
quickAdd?: React.JSX.Element | undefined;
quickAdd?: React.ReactNode | undefined;
isEpic?: boolean;
};

View file

@ -43,7 +43,7 @@ type ChartViewRootProps = {
loadMoreBlocks?: () => void;
updateBlockDates?: (updates: IBlockUpdateDependencyData[]) => Promise<void>;
canLoadMoreBlocks?: boolean;
quickAdd?: React.JSX.Element | undefined;
quickAdd?: React.ReactNode | undefined;
showToday: boolean;
isEpic?: boolean;
};

View file

@ -14,7 +14,7 @@ type GanttChartRootProps = {
blockUpdateHandler: (block: any, payload: IBlockUpdateData) => void;
blockToRender: (data: any) => React.ReactNode;
sidebarToRender: (props: any) => React.ReactNode;
quickAdd?: React.JSX.Element | undefined;
quickAdd?: React.ReactNode | undefined;
canLoadMoreBlocks?: boolean;
loadMoreBlocks?: () => void;
updateBlockDates?: (updates: IBlockUpdateDependencyData[]) => Promise<void>;

View file

@ -13,7 +13,7 @@ type Props = {
id: string;
isLastChild: boolean;
isDragEnabled: boolean;
children: (isDragging: boolean) => JSX.Element;
children: (isDragging: boolean) => React.ReactNode;
onDrop: (draggingBlockId: string | undefined, droppedBlockId: string | undefined, dropAtEndOfList: boolean) => void;
};

View file

@ -22,7 +22,7 @@ type Props = {
enableSelection: boolean | ((blockId: string) => boolean);
sidebarToRender: (props: any) => React.ReactNode;
title: string;
quickAdd?: React.JSX.Element | undefined;
quickAdd?: React.ReactNode | undefined;
selectionHelpers: TSelectionHelper;
isEpic?: boolean;
};

View file

@ -15,7 +15,7 @@ import { ProjectService } from "@/services/project";
type Props = {
integration: IWorkspaceIntegration;
value: any;
label: string | JSX.Element;
label: string | React.ReactNode;
onChange: (repo: any) => void;
characterLimit?: number;
};

View file

@ -66,7 +66,7 @@ export const SingleUserSelect: React.FC<Props> = ({ collaborator, index, users,
| {
value: string;
query: string;
content: JSX.Element;
content: React.ReactNode;
}[]
| undefined;

View file

@ -54,7 +54,7 @@ export const JiraImportUsers: FC = () => {
| {
value: string;
query: string;
content: JSX.Element;
content: React.ReactNode;
}[]
| undefined;

View file

@ -4,7 +4,7 @@ import React, { FC } from "react";
import { cn } from "@plane/utils";
type Props = {
icon: JSX.Element;
icon: React.ReactNode;
title: string;
disabled?: boolean;
};

View file

@ -31,7 +31,7 @@ const ActiveLoader = (props: { layout: EIssueLayoutTypes }) => {
};
interface Props {
children: string | JSX.Element | JSX.Element[];
children: string | React.ReactNode | React.ReactNode[];
layout: EIssueLayoutTypes;
}

View file

@ -42,7 +42,7 @@ type TQuickAddIssueRoot = {
layout: EIssueLayoutTypes;
prePopulatedData?: Partial<TIssue>;
QuickAddButton?: FC<TQuickAddIssueButton>;
customQuickAddButton?: JSX.Element;
customQuickAddButton?: React.ReactNode;
containerClassName?: string;
setIsQuickAddOpen?: (isOpen: boolean) => void;
quickAddCallback?: (projectId: string | null | undefined, data: TIssue) => Promise<TIssue | undefined>;

View file

@ -21,7 +21,7 @@ export type TWorkItemLabelSelectBaseProps = {
createLabelEnabled?: boolean;
disabled?: boolean;
getLabelById: (labelId: string) => IIssueLabel | null;
label?: JSX.Element;
label?: React.ReactNode;
labelIds: string[];
onChange: (value: string[]) => void;
onDropdownOpen?: () => void;

View file

@ -42,7 +42,7 @@ type Props = {
isDragging: boolean,
isDroppingInLabel: boolean,
dragHandleRef: MutableRefObject<HTMLButtonElement | null>
) => JSX.Element;
) => React.ReactNode;
onDrop: (
draggingLabelId: string,
droppedParentId: string | null,

View file

@ -50,7 +50,7 @@ export const MemberSelect: React.FC<Props> = observer((props) => {
| {
value: string;
query: string;
content: React.JSX.Element;
content: React.ReactNode;
}[]
| undefined;
const selectedOption = projectId ? getProjectMemberDetails(value, projectId.toString()) : null;

View file

@ -163,7 +163,7 @@ export const SendProjectInvitationModal: React.FC<Props> = observer((props) => {
| {
value: string;
query: string;
content: React.JSX.Element;
content: React.ReactNode;
}[]
| undefined;

View file

@ -9,7 +9,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
type Props = {
href: string;
title: string;
icon: JSX.Element;
icon: React.ReactNode;
};
export const FavoriteItemTitle: FC<Props> = observer((props) => {

View file

@ -158,7 +158,7 @@ const CustomBarLollipop = React.memo((props: TBarProps) => {
*/
const createShapeVariant =
(Component: React.ComponentType<TBarProps>, factoryProps?: Partial<TBarProps>) =>
(shapeProps: TShapeProps, bar: TBarItem<string>, stackKeys: string[]): JSX.Element => {
(shapeProps: TShapeProps, bar: TBarItem<string>, stackKeys: string[]): React.ReactNode => {
const showTopBorderRadius = bar.showTopBorderRadius?.(shapeProps.dataKey, shapeProps.payload);
const showBottomBorderRadius = bar.showBottomBorderRadius?.(shapeProps.dataKey, shapeProps.payload);
@ -178,7 +178,7 @@ const createShapeVariant =
export const barShapeVariants: Record<
TBarChartShapeVariant,
(props: TShapeProps, bar: TBarItem<string>, stackKeys: string[]) => JSX.Element
(props: TShapeProps, bar: TBarItem<string>, stackKeys: string[]) => React.ReactNode
> = {
bar: createShapeVariant(CustomBar), // Standard bar with rounded corners
lollipop: createShapeVariant(CustomBarLollipop), // Line with circle at top

View file

@ -68,7 +68,8 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
opacity={!!activeLegend && activeLegend !== bar.key ? 0.1 : 1}
shape={(shapeProps: any) => {
const shapeVariant = barShapeVariants[bar.shapeVariant ?? "bar"];
return shapeVariant(shapeProps, bar, stackKeys);
const node = shapeVariant(shapeProps, bar, stackKeys);
return React.isValidElement(node) ? node : <>{node}</>;
}}
className="[&_path]:transition-opacity [&_path]:duration-200"
onMouseEnter={() => setActiveBar(bar.key)}

View file

@ -26,9 +26,15 @@
"fix:format": "prettier --write \"**/*.{ts,tsx,md,json,css,scss}\"",
"clean": "rm -rf .turbo && rm -rf .next && rm -rf node_modules && rm -rf dist"
},
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@plane/eslint-config": "*",
"@plane/typescript-config": "*",
"@types/react": "18.3.11",
"@types/react-dom": "18.3.1",
"tsup": "8.4.0",
"typescript": "5.8.3"
}

View file

@ -2,8 +2,8 @@ export type TInstanceAuthenticationModes = {
key: string;
name: string;
description: string;
icon: JSX.Element;
config: JSX.Element;
icon: React.ReactNode;
config: React.ReactNode;
unavailable?: boolean;
};

View file

@ -7,7 +7,7 @@ import { Tooltip } from "../tooltip";
import { Breadcrumbs } from "./breadcrumbs";
type TBreadcrumbNavigationSearchDropdownProps = {
icon?: React.JSX.Element;
icon?: React.ReactNode;
title?: string;
selectedItem: string;
navigationItems: ICustomSearchSelectOption[];

View file

@ -7,10 +7,10 @@ export interface IDropdownProps {
customButtonTabIndex?: number;
buttonClassName?: string;
className?: string;
customButton?: JSX.Element;
customButton?: React.ReactNode;
disabled?: boolean;
input?: boolean;
label?: string | JSX.Element;
label?: string | React.ReactNode;
maxHeight?: "sm" | "rg" | "md" | "lg";
noChevron?: boolean;
chevronClassName?: string;
@ -48,7 +48,7 @@ export interface ICustomSelectProps extends IDropdownProps {
}
interface CustomSearchSelectProps {
footerOption?: JSX.Element;
footerOption?: React.ReactNode;
onChange: any;
onClose?: () => void;
noResultsMessage?: string;

View file

@ -1,8 +1,8 @@
export type TTableColumn<T> = {
key: string;
content: string;
thRender?: () => JSX.Element;
tdRender: (rowData: T) => JSX.Element;
thRender?: () => React.ReactNode;
tdRender: (rowData: T) => React.ReactNode;
};
export type TTableData<T> = {

View file

@ -29,7 +29,7 @@ type SetToastProps =
};
type PromiseToastCallback<ToastData> = (data: ToastData) => string;
type ActionItemsPromiseToastCallback<ToastData> = (data: ToastData) => JSX.Element;
type ActionItemsPromiseToastCallback<ToastData> = (data: ToastData) => React.ReactNode;
type PromiseToastData<ToastData> = {
title: string;

View file

@ -24,7 +24,7 @@ interface ITooltipProps {
tooltipHeading?: string;
tooltipContent: string | React.ReactNode;
position?: TPosition;
children: JSX.Element;
children: React.ReactElement;
disabled?: boolean;
className?: string;
openDelay?: number;

View file

@ -37,7 +37,7 @@ export const getEditorAssetDownloadSrc = (args: TEditorSrcArgs): string | undefi
return url;
};
export const getTextContent = (jsx: JSX.Element | React.ReactNode | null | undefined): string => {
export const getTextContent = (jsx: React.ReactNode | React.ReactNode | null | undefined): string => {
if (!jsx) return "";
const div = document.createElement("div");

View file

@ -2678,6 +2678,13 @@
dependencies:
"@types/react" "*"
"@types/react-dom@18.3.1":
version "18.3.1"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.1.tgz#1e4654c08a9cdcfb6594c780ac59b55aad42fe07"
integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==
dependencies:
"@types/react" "*"
"@types/react-dom@^18.2.18":
version "18.3.7"
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.7.tgz#b89ddf2cd83b4feafcc4e2ea41afdfb95a0d194f"
@ -2703,6 +2710,14 @@
"@types/prop-types" "*"
csstype "^3.0.2"
"@types/react@18.3.11":
version "18.3.11"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.11.tgz#9d530601ff843ee0d7030d4227ea4360236bd537"
integrity sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==
dependencies:
"@types/prop-types" "*"
csstype "^3.0.2"
"@types/react@^18.3.11":
version "18.3.23"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.23.tgz#86ae6f6b95a48c418fecdaccc8069e0fbb63696a"
@ -9526,7 +9541,16 @@ streamx@^2.15.0, streamx@^2.21.0:
optionalDependencies:
bare-events "^2.2.0"
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -9619,7 +9643,14 @@ string_decoder@^1.1.1, string_decoder@^1.3.0:
dependencies:
safe-buffer "~5.2.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -10791,7 +10822,16 @@ word-wrap@^1.2.5:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==